+++ /dev/null
-AFS_component_version_number.c
-Makefile
-afs_trace.h
-afs_trace.msf
-afszcm.cat
-unified_afs.c
-unified_afs.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
-
-# $Locker: $
-#
-# misc.s - miscellaneous assembler routines for the rs/6000
-#
-
-#
-# get_toc - return the current TOC
-#
- .csect .get_toc[PR]
- .globl .get_toc[PR]
- mr 3,2 # get TOC
- br
- .align 2
- .tbtag 0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
-
- .toc
- .csect get_toc[DS]
- .globl get_toc[DS]
- .long .get_toc[PR]
- .long TOC[t0]
-
-#
-# get_ret_addr - return the caller's return address
-#
- .csect .get_ret_addr[PR]
- .globl .get_ret_addr[PR]
- l 3, 0(1) # caller's saved stack pointer
- l 3, 8(3) # caller's saved link register
- br
- .align 2
- .tbtag 0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
- .toc
- .csect get_ret_addr[DS]
- .globl get_ret_addr[DS]
- .long .get_ret_addr[PR]
- .long TOC[t0]
+++ /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
- */
-
-/*
- * Implements:
- * afs_config
- * mem_getbytes
- * mem_freebytes
- * kmem_alloc
- * kmem_free
- * VN_RELE
- * VN_HOLD
- * kludge_init
- * ufdalloc
- * ufdfree
- * ffree
- * iptovp
- * dev_ialloc
- * iget
- * iput
- * commit
- * fs_simple_lock
- * fs_read_lock
- * fs_write_lock
- * fs_complex_unlock
- * ksettimer
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_config.c,v 1.8 2003/07/15 23:14:16 shadow Exp $");
-
-#include "sys/limits.h"
-#include "sys/types.h"
-#include "sys/user.h"
-#include "sys/vnode.h"
-#include "sys/conf.h"
-#include "sys/errno.h"
-#include "sys/device.h"
-#include "sys/vfs.h"
-#include "sys/vmount.h"
-#include "sys/gfs.h"
-#include "sys/uio.h"
-#include "sys/pri.h"
-#include "sys/priv.h" /* XXX */
-#include "sys/lockl.h"
-#include "sys/malloc.h"
-#include <sys/syspest.h> /* to define the assert and ASSERT macros */
-#include <sys/timer.h> /* For the timer related defines */
-#include <sys/intr.h> /* for the serialization defines */
-#include <sys/malloc.h> /* for the parameters to xmalloc() */
-#include "afs/afs_osi.h" /* pick up osi_timeval_t for afs_stats.h */
-#include "afs/afs_stats.h"
-#include "export.h"
-
-#ifdef KOFF
-#define KOFF_PRESENT 1
-#else
-#define KOFF_PRESENT 0
-#endif
-
-#if !KOFF_PRESENT
-_db_trace()
-{;
-}
-
-long db_tflags = 0;
-#endif
-
-extern struct gfs afs_gfs;
-extern struct vnodeops locked_afs_gn_vnodeops;
-
-#ifdef __64BIT__
-afs_uint64 get_toc();
-#else
-afs_uint32 get_toc();
-#endif
-
-#define AFS_CALLOUT_TBL_SIZE 256
-
-#include <sys/lock_alloc.h>
-extern Simple_lock afs_callout_lock;
-
-/*
- * afs_config - handle AFS configuration requests
- *
- * Input:
- * cmd - add/delete command
- * uiop - uio vector describing any config params
- */
-afs_config(cmd, uiop)
- struct uio *uiop;
-{
- int err;
- extern struct vnodeops *afs_ops;
-
- AFS_STATCNT(afs_config);
-
- err = 0;
- AFS_GLOCK();
- if (cmd == CFG_INIT) { /* add AFS gfs */
- /*
- * init any vrmix mandated kluges
- */
- if (err = kluge_init())
- goto out;
- /*
- * make sure that we pin everything
- */
- if (err = pincode(afs_config))
- goto out;
- err = gfsadd(AFS_MOUNT_AFS, &afs_gfs);
- /*
- * ok, if already installed
- */
- if (err == EBUSY)
- err = 0;
- if (!err) {
- pin(&afs_callout_lock, sizeof(afs_callout_lock));
- lock_alloc(&afs_callout_lock, LOCK_ALLOC_PIN, 0, 5);
- simple_lock_init(&afs_callout_lock);
- afs_ops = &locked_afs_gn_vnodeops;
- timeoutcf(AFS_CALLOUT_TBL_SIZE);
- } else {
- unpincode(afs_config);
- goto out;
- }
- if (KOFF_PRESENT) {
- extern void *db_syms[];
- extern db_nsyms;
-
- koff_addsyms(db_syms, db_nsyms);
- }
- } else if (cmd == CFG_TERM) { /* delete AFS gfs */
- err = gfsdel(AFS_MOUNT_AFS);
- /*
- * ok, if already deleted
- */
- if (err == ENOENT)
- err = 0;
- else if (!err) {
- if (err = unpincode(afs_config))
- err = 0;
-
- timeoutcf(-AFS_CALLOUT_TBL_SIZE);
- }
- } else /* unknown command */
- err = EINVAL;
-
- out:
- AFS_GUNLOCK();
- if (!err && (cmd == CFG_INIT))
- osi_Init();
-
- return err;
-}
-
-/*
- * The following stuff is (hopefully) temporary.
- */
-
-
-/*
- * mem_getbytes - memory allocator
- *
- * Seems we can't make up our mind what to call these
- */
-char *
-mem_getbytes(size)
-{
-
- return malloc(size);
-}
-
-/*
- * mem_freebytes - memory deallocator
- */
-mem_freebytes(p, size)
- char *p;
-{
-
- free(p);
-}
-
-char *
-kmem_alloc(size)
-{
-
- return malloc(size);
-}
-
-kmem_free(p, size)
- char *p;
-{
-
- free(p);
-}
-
-VN_RELE(vp)
- register struct vnode *vp;
-{
-
- VNOP_RELE(vp);
-}
-
-VN_HOLD(vp)
- register struct vnode *vp;
-{
-
- VNOP_HOLD(vp);
-}
-
-/*
- * The following stuff is to account for the fact that stuff we need exported
- * from the kernel isn't, so we must be devious.
- */
-
-int (*kluge_ufdalloc) ();
-int (*kluge_fpalloc) ();
-void *(*kluge_ufdfree) ();
-void *(*kluge_ffree) ();
-int (*kluge_iptovp) ();
-int (*kluge_dev_ialloc) ();
-int (*kluge_iget) ();
-int (*kluge_iput) ();
-int (*kluge_commit) ();
-void *(*kluge_ksettimer) ();
-void *(*kluge_fsSimpleLock) ();
-void *(*kluge_fsSimpleUnlock) ();
-void *(*kluge_fsReadLock) ();
-void *(*kluge_fsWriteLock) ();
-void *(*kluge_fsCxUnlock) ();
-
-/*
- * kernel function import list
- */
-
-struct k_func kfuncs[] = {
- {(void *(**)())&kluge_ufdalloc, ".ufdalloc"},
- {(void *(**)())&kluge_fpalloc, ".fpalloc"},
- {&kluge_ufdfree, ".ufdfree"},
- {&kluge_ffree, ".ffree"},
- {(void *(**)())&kluge_iptovp, ".iptovp"},
- {(void *(**)())&kluge_dev_ialloc, ".dev_ialloc"},
- {(void *(**)())&kluge_iget, ".iget"},
- {(void *(**)())&kluge_iput, ".iput"},
- {(void *(**)())&kluge_commit, ".commit"},
- {&kluge_ksettimer, ".ksettimer"},
-#ifdef _FSDEBUG
- {&kluge_fsSimpleLock, ".fs_simple_lock"},
- {&kluge_fsSimpleUnlock, ".fs_simple_unlock"},
- {&kluge_fsReadLock, ".fs_read_lock"},
- {&kluge_fsWriteLock, ".fs_write_lock"},
- {&kluge_fsCxUnlock, ".fs_complex_unlock"},
-#endif
- {0, 0},
-};
-
-void *vnodefops; /* dummy vnodeops */
-struct ifnet *ifnet;
-Simple_lock jfs_icache_lock;
-Simple_lock proc_tbl_lock;
-
-/*
- * kernel variable import list
- */
-struct k_var kvars[] = {
- {(void *)&vnodefops, "vnodefops"},
- {(void *)&ifnet, "ifnet"},
- {(void *)&jfs_icache_lock, "jfs_icache_lock"},
-#ifndef AFS_AIX51_ENV
- {(void *)&proc_tbl_lock, "proc_tbl_lock"},
-#endif
- {0, 0},
-};
-
-/*
- * kluge_init - initialise the kernel imports kluge
- */
-kluge_init()
-{
- register struct k_func *kf;
- register struct k_var *kv;
-#ifdef __64BIT__
- register afs_uint64 toc;
-#else
- register afs_uint32 toc;
-#endif
- register err = 0;
-
- toc = get_toc();
- for (kf = kfuncs; !err && kf->name; ++kf) {
- err = import_kfunc(kf);
- }
- for (kv = kvars; !err && kv->name; ++kv) {
- err = import_kvar(kv, toc);
- }
-
- return err;
-}
-
-ufdalloc(i, fdp)
- int *fdp;
-{
-
- return (*kluge_ufdalloc) (i, fdp);
-}
-
-fpalloc(vp, flag, type, ops, fpp)
- struct vnode *vp;
- struct fileops *ops;
- struct file **fpp;
-{
-
- return (*kluge_fpalloc) (vp, flag, type, ops, fpp);
-}
-
-void
-ufdfree(fd)
-{
-
- (void)(*kluge_ufdfree) (fd);
-}
-
-void
-ffree(fp)
- struct file *fp;
-{
-
- (void)(*kluge_ffree) (fp);
-}
-
-iptovp(vfsp, ip, vpp)
- struct vfs *vfsp;
- struct inode *ip, **vpp;
-{
-
- return (*kluge_iptovp) (vfsp, ip, vpp);
-}
-
-dev_ialloc(pip, ino, mode, vfsp, ipp)
- struct inode *pip;
- ino_t ino;
- mode_t mode;
- struct vfs *vfsp;
- struct inode **ipp;
-{
-
- return (*kluge_dev_ialloc) (pip, ino, mode, vfsp, ipp);
-
-}
-
-iget(dev, ino, ipp, doscan, vfsp)
- dev_t dev;
- ino_t ino;
-#ifdef __64BIT__
- afs_size_t doscan;
-#endif
- struct vfs *vfsp;
- struct inode **ipp;
-{
-#ifdef __64BIT__
- afs_int64 dummy[10];
- dummy[0] = doscan;
-
- return (*kluge_iget) (dev, ino, ipp, (afs_size_t) doscan, vfsp, &dummy);
-#else
- return (*kluge_iget) (dev, ino, ipp, doscan, vfsp);
-#endif
-}
-
-iput(ip, vfsp)
- struct vfs *vfsp;
- struct inode *ip;
-{
- return (*kluge_iput) (ip, vfsp);
-}
-
-commit(n, i0, i1, i2)
- struct inode *i0, *i1, *i2;
-{
-
- return (*kluge_commit) (n, i0, i1, i2);
-}
-
-
-#ifdef _FSDEBUG
-fs_simple_lock(void *lp, int type)
-{
- return (*kluge_fsSimpleLock) (lp, type);
-}
-
-fs_simple_unlock(void *lp, int type)
-{
- return (*kluge_fsSimpleUnlock) (lp, type);
-}
-
-fs_read_lock(complex_lock_t lp, int type)
-{
- return (*kluge_fsReadLock) (lp, type);
-}
-
-fs_write_lock(complex_lock_t lp, int type)
-{
- return (*kluge_fsWriteLock) (lp, type);
-}
-
-fs_complex_unlock(complex_lock_t lp, int type)
-{
- return (*kluge_fsCxUnlock) (lp, type);
-}
-#endif
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_file.c,v 1.9 2003/07/15 23:14:16 shadow Exp $");
-
-#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;
-struct AFS_UCRED afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct vfs *afs_cacheVfsp;
-
-
-void *
-osi_UFSOpen(afs_int32 ainode)
-{
- struct inode *ip;
- register struct osi_file *afile = NULL;
- extern struct vfs *rootvfs;
- struct vnode *vp = 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");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- setuerror(0);
- AFS_GUNLOCK();
- ip = (struct inode *)igetinode((dev_t) cacheDev.dev, rootvfs,
- (ino_t) ainode, &vp, &dummy);
- AFS_GLOCK();
- if (getuerror()) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UFSOpen: igetinode failed");
- }
- afile->vnode = vp; /* Save the vnode pointer for the inode ip; also ip is already prele'ed in igetinode */
- afile->size = VTOI(afile->vnode)->i_size;
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- code = VNOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-int
-osi_UFSClose(register struct osi_file *afile)
-{
- AFS_STATCNT(osi_Close);
- if (afile->vnode) {
- /* AIX writes entire data regions at a time when dumping core. We've
- * seen a 26M write go through the system. When this happens, we run
- * out of available pages. So, we'll flush the vnode's vm if we're short
- * on space.
- */
- if (vmPageHog) {
- int code;
- if (afile->vnode->v_gnode->gn_seg) {
- /* 524287 is the max number of pages for a file. See test in
- * vm_writep.
- */
- code = vm_writep(afile->vnode->v_gnode->gn_seg, 0, 524287);
- }
- }
- AFS_RELE(afile->vnode);
- }
-
- osi_FreeSmallSpace(afile);
- return 0;
-}
-
-int
-osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- struct vattr tvattr;
- register afs_int32 code;
- struct osi_stat tstat;
- afs_int32 mode = FWRITE | FSYNC;
- 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;
- MObtainWriteLock(&afs_xosi, 321);
- /*
- * If we're truncating an unopened file to a non-zero length,
- * we need to bind it to a vm segment
- * Note that that the binding will actually happen inside
- * jfs by xix_ftrunc; setting mode to 0 will enable that.
- */
- if (asize && !VTOGP(afile->vnode)->gn_seg)
- mode = 0;
- AFS_GUNLOCK();
- code = VNOP_FTRUNC(afile->vnode, mode, asize, (caddr_t) 0, &afs_osi_cred);
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- struct inode *ip = VTOIP(avp);
- ip->i_flag &= ~IACC;
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct AFS_UCRED *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;
- retry_IO:
- /* Note the difference in the way the afile->offset is passed (see comments in gop_rdwr() in afs_aix_subr.c for comments) */
- AFS_GUNLOCK();
-#ifdef AFS_64BIT_KERNEL
- code =
- gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize,
- &afile->offset, AFS_UIOSYS, NULL, &resid);
-#else
- code =
- gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize,
- (off_t) & afile->offset, AFS_UIOSYS, NULL, &resid);
-#endif
- 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);
- /*
- * To handle periodic low-level EFAULT failures that we've seen with the
- * Weitek chip; in all observed failed cases a second read succeeded.
- */
- if ((code == EFAULT) && (cnt1++ < 5)) {
- afs_stats_cmperf.osiread_efaults++;
- goto retry_IO;
- }
- setuerror(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)
-{
- struct AFS_UCRED *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;
- /* Note the difference in the way the afile->offset is passed (see comments in gop_rdwr() in afs_aix_subr.c for comments) */
- AFS_GUNLOCK();
-#ifdef AFS_64BIT_KERNEL
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- &afile->offset, AFS_UIOSYS, NULL, &resid);
-#else
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- (off_t) & afile->offset, AFS_UIOSYS, NULL, &resid);
-#endif
- AFS_GLOCK();
- if (code == 0) {
- if (resid)
- afs_Trace3(afs_iclSetp, CM_TRACE_WRITEFAILED, ICL_TYPE_INT32,
- asize, ICL_TYPE_INT32, resid, ICL_TYPE_INT32, code);
- code = asize - resid;
- afile->offset += code;
- } else {
- afs_Trace3(afs_iclSetp, CM_TRACE_WRITEFAILED, ICL_TYPE_INT32, asize,
- ICL_TYPE_INT32, resid, ICL_TYPE_INT32, code);
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
- setuerror(code);
- 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)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * setgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_groups.c,v 1.8 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-
-static int
- afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
-
-static int
- afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
- int change_parent);
-
-#ifndef AFS_AIX51_ENV
-int
-setgroups(ngroups, gidset)
- int ngroups;
- gid_t *gidset;
-{
- int code = 0;
- struct vrequest treq;
- struct ucred *credp;
- struct ucred *credp0;
-
- AFS_STATCNT(afs_xsetgroups);
-
- credp = crref();
- AFS_GLOCK();
- code = afs_InitReq(&treq, credp);
- AFS_GUNLOCK();
- crfree(credp);
- if (code)
- return code;
-
- code = osetgroups(ngroups, gidset);
-
- /* Note that if there is a pag already in the new groups we don't
- * overwrite it with the old pag.
- */
- credp = crref();
- credp0 = credp;
-
- if (PagInCred(credp) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- AddPag(treq.uid, &credp);
- AFS_GUNLOCK();
- }
- }
-
- /* If AddPag() didn't make a new cred, then free our cred ref */
- if (credp == credp0) {
- crfree(credp);
- }
- return code;
-}
-#endif
-
-int
-setpag(cred, pagvalue, newpag, change_parent)
- 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);
-#ifndef AFS_AIX51_ENV
- 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 (setuerror(E2BIG), E2BIG);
- }
- for (j = ngroups - 1; j >= 0; j--) {
- gidset[j + 2] = gidset[j];
- }
- ngroups += 2;
- }
-#endif
- *newpag = (pagvalue == -1 ? genpag() : pagvalue);
-#ifdef AFS_AIX51_ENV
- if (change_parent) {
- code = kcred_setpag(*cred, PAG_AFS, *newpag);
- } else {
- struct ucred *newcr = crdup(*cred);
-
- crset(newcr);
- code = kcred_setpag(newcr, PAG_AFS, *newpag);
- *cred = newcr;
- }
-#else
- afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
- if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
- return (setuerror(code), code);
- }
-#endif
- return code;
-}
-
-
-#ifndef AFS_AIX51_ENV
-static int
-afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
-{
- int ngrps, savengrps;
- gid_t *gp;
-
- gidset[0] = gidset[1] = 0;
- AFS_STATCNT(afs_getgroups);
-
- savengrps = ngrps = MIN(ngroups, cred->cr_ngrps);
- gp = cred->cr_groups;
- while (ngrps--)
- *gidset++ = *gp++;
- return savengrps;
-}
-
-/* the caller is responsible for checking that ngroups <= NGROUPS */
-
-static void
-copy_to_cred(newcr, ngroups, gidset)
- struct ucred *newcr;
- int ngroups;
- gid_t *gidset;
-{
- gid_t *gp;
- int newngroups;
-
- newngroups = ngroups;
- gp = newcr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- newcr->cr_ngrps = newngroups;
-}
-
-/*
- * If change_parent is true, then we want to affect the parent process as well
- * as the current process. We do this by writing into the given cred, on
- * the assumption that it is shared with the parent process.
- *
- * Note that it is important that we do NOT actually do anything to the
- * parent process, because the NFS/AFS translator uses this routine to
- * write into a given cred, and it has no intention of affecting the parent
- * process.
- *
- * If change_parent is false, then we want to affect only the current process.
- */
-
-static int
-afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
- int change_parent)
-{
- AFS_STATCNT(afs_setgroups);
-
- if (ngroups > NGROUPS)
- return EINVAL;
-
- if (change_parent) {
-
- /*
- * klog -setpag goes through this code to change the cred
- * shared with the parent process. Historically this did
- * not work on AIX, but the problem in AIX has now been
- * fixed.
- *
- * The NFS/AFS translator also uses this code in order to
- * write into a given cred; it certainly doesn't use it
- * in order to affect any other process.
- */
- copy_to_cred(*cred, ngroups, gidset);
-
- } else {
-
- struct ucred *newcr = crdup(*cred);
-
- copy_to_cred(newcr, ngroups, gidset);
-
- crset(newcr);
- *cred = newcr;
- }
- return 0;
-}
-#endif
+++ /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
- */
-
-/*
- * AIX inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_inode.c,v 1.8 2003/07/15 23:14:17 shadow Exp $");
-
-#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/syspest.h"
-
-#if !defined(offsetof)
-#include <stddef.h> /* for definition of offsetof() */
-#endif
-
-extern Simple_lock jfs_icache_lock;
-#define ICACHE_LOCK() simple_lock(&jfs_icache_lock)
-#define ICACHE_UNLOCK() simple_unlock(&jfs_icache_lock)
-
-/*
- * In AIX 4.2.0, the inode member to lock is i_rdwrlock. The inode
- * structure conditionally contains a member called i_nodelock which we
- * do NOT want to use.
- *
- * In AIX 4.2.1 and later, the inode member to lock is i_nodelock, which
- * was relocated to coincide with the AIX 4.2.0 position of i_rdwrlock.
- * The AIX 4.2.1 and later inode structure does not contain a field
- * named i_rdwrlock.
- *
- * We use an accident of the system header files to distinguish between
- * AIX 4.2.0 and AIX 4.2.1 and later. This allows this part of the code
- * to compile on AIX 4.2.1 and later without introducing a new system
- * type.
- *
- * The macro IACTIVITY is 0x0020 on AIX 4.2.0, and 0x0010 on AIX 4.2.1
- * and later (at least through AIX 4.3.3). If IACTIVITY is undefined,
- * or has an unknown value, then the system header files are different
- * than what we've seen and we'll need to take a look at them anyway to
- * get AFS to work.
- *
- * The osi_Assert() statement in igetinode() checks that the lock field
- * is at an expected offset.
- */
-
-#if IACTIVITY == 0x0020 /* in <jfs/inode.h> on AIX 4.2.0 */
-#define afs_inode_lock i_rdwrlock
-#endif
-
-#if IACTIVITY == 0x0010 /* in <jfs/inode.h> on AIX 4.2.1 and later */
-#define afs_inode_lock i_nodelock
-#endif
-
-#define IREAD_LOCK(ip) simple_lock(&((ip)->afs_inode_lock))
-#define IREAD_UNLOCK(ip) simple_unlock(&((ip)->afs_inode_lock))
-#define IWRITE_LOCK(ip) simple_lock(&((ip)->afs_inode_lock))
-#define IWRITE_UNLOCK(ip) simple_unlock(&((ip)->afs_inode_lock))
-
-#define SYSENT(name, arglist, decls) \
-name arglist \
-decls { \
- lock_t lockt; \
- int rval1 = 0; \
- label_t jmpbuf; \
- int rc; \
- \
- \
- setuerror(0); \
- \
- if ((rc = setjmpx(&jmpbuf)) == 0) { \
- rval1 = afs_syscall_ ## name arglist; \
- clrjmpx(&jmpbuf); \
- } else { \
- if (rc != EINTR) { \
- longjmpx(rc); \
- } \
- setuerror(rc); \
- } \
- \
- \
- return(getuerror() ? -1 : rval1); \
-} \
-afs_syscall_ ## name arglist \
-decls \
-
-
-/*
- * This structure is used to pass information between devtovfs() and
- * devtovfs_func() via vfs_search().
- */
-
-struct devtovfs_args {
- dev_t dev;
- struct vfs *ans;
-};
-
-/*
- * If the given vfs matches rock->dev, set rock->ans to vfsp and return
- * nonzero. Otherwise return zero.
- *
- * (Returning nonzero causes vfs_search() to terminate the search.)
- */
-
-static int
-devtovfs_func(struct vfs *vfsp, struct devtovfs_args *rock)
-{
- if (vfsp->vfs_mntd != NULL && vfsp->vfs_type == MNT_JFS
- && (vfsp->vfs_flag & VFS_DEVMOUNT)) {
- struct inode *ip = VTOIP(vfsp->vfs_mntd);
- if (brdev(ip->i_dev) == brdev(rock->dev)) {
- rock->ans = vfsp;
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- * Return the vfs entry for the given device.
- */
-
-static struct vfs *
-devtovfs(dev_t dev)
-{
- struct devtovfs_args a;
-
- AFS_STATCNT(devtovfs);
-
- a.dev = dev;
- a.ans = NULL;
- vfs_search(devtovfs_func, &a);
- return a.ans;
-}
-
-/* Keep error values around in case iget fails. UFSOpen panics when
- * igetinode fails.
- */
-int IGI_error;
-ino_t IGI_inode;
-int IGI_nlink;
-int IGI_mode;
-/* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
-/* Also used by rmt_remote to support passing of inode number from venus */
-extern int iget();
-extern struct vnode *filevp;
-struct inode *
-igetinode(dev, vfsp, inode, vpp, perror)
- struct vfs *vfsp;
- struct vnode **vpp; /* vnode associated with the inode */
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct inode *ip;
- register was_locked;
- struct vfs *nvfsp = NULL;
- int code;
- *perror = 0;
- *vpp = NULL;
- AFS_STATCNT(igetinode);
-
- /*
- * Double check that the inode lock is at a known offset.
- *
- * If it isn't, then we need to reexamine our code to make
- * sure that it is still okay.
- */
-#ifdef __64BIT__
-/* osi_Assert(offsetof(struct inode, afs_inode_lock) == 208); */
-#else
- osi_Assert(offsetof(struct inode, afs_inode_lock) == 128);
-#endif
-
- if (!vfsp && !(vfsp = devtovfs((dev_t) dev))) {
- afs_warn("Dev=%d not mounted!!; quitting\n", dev);
- setuerror(ENODEV);
- ip = 0;
- goto out;
- }
- if (vfsp->vfs_flag & VFS_DEVMOUNT)
- nvfsp = vfsp;
-
- /* Check if inode 0. This is the mount inode for the device
- * and will panic the aix system if removed: defect 11434.
- * No file should ever point to this inode.
- */
- if (inode == 0) {
- afs_warn("Dev=%d zero inode.\n", dev);
- setuerror(ENOENT);
- ip = 0;
- goto out;
- }
-
- ICACHE_LOCK();
-#ifdef __64BIT__
- if ((code = iget(dev, inode, &ip, (afs_size_t) 1, nvfsp))) {
-#else
- if ((code = iget(dev, inode, &ip, 1, nvfsp))) {
-#endif
- IGI_error = code;
- IGI_inode = inode;
- *perror = BAD_IGET;
- ICACHE_UNLOCK();
- setuerror(ENOENT); /* Well... */
- ip = 0;
- goto out;
- }
- ICACHE_UNLOCK();
- IREAD_LOCK(ip);
- if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
- IGI_error = 0;
- IGI_inode = inode;
- IGI_nlink = ip->i_nlink;
- IGI_mode = ip->i_mode;
- IREAD_UNLOCK(ip);
- ICACHE_LOCK();
- iput(ip, NULL);
- ICACHE_UNLOCK();
- setuerror(ENOENT);
- ip = 0;
- goto out;
- }
- IREAD_UNLOCK(ip);
- if (vpp) {
- if (nvfsp)
- *vpp = ip->i_gnode.gn_vnode;
- else
- setuerror(iptovp(vfsp, ip, vpp));
- }
- out:
- return ip;
-}
-
-
-#ifndef INODESPECIAL
-/*
- * `INODESPECIAL' type inodes are ones that describe volumes. These are
- * marked as journalled. We would also like to journal inodes corresponding
- * to directory information...
- */
-#define INODESPECIAL 0xffffffff /* ... from ../vol/viceonode.h */
-#endif
-
-SYSENT(icreate, (dev, near_inode, param1, param2, param3, param4),)
-{
- struct inode *ip, *newip, *pip;
- register int err, rval1, rc = 0;
- struct vnode *vp = NULL;
- extern struct vfs *rootvfs;
- register struct vfs *vfsp;
- struct vfs *nvfsp = NULL;
- char error;
- ino_t ino = near_inode;
-
- AFS_STATCNT(afs_syscall_icreate);
- if (!suser(&error)) {
- setuerror(error);
- return -1;
- }
-
- if ((vfsp = devtovfs((dev_t) dev)) == 0) {
- afs_warn("Dev=%d not mounted!!; quitting\n", dev);
- setuerror(ENODEV);
- return -1;
- }
- if (vfsp->vfs_flag & VFS_DEVMOUNT)
- nvfsp = vfsp;
- ICACHE_LOCK();
- rc = iget(dev, 0, &pip, 1, nvfsp);
- if (!rc) {
- /*
- * this is the mount inode, and thus we should be
- * safe putting it back.
- */
- iput(pip, nvfsp);
- }
- ICACHE_UNLOCK();
-
- if (rc) {
- setuerror(EINVAL);
- return -1;
- }
-
- if (setuerror(dev_ialloc(pip, ino, IFREG, nvfsp, &newip)))
- return -1;
- newip->i_flag |= IACC | IUPD | ICHG;
- newip->i_gid = -2; /* Put special gid flag */
- newip->i_vicemagic = VICEMAGIC;
- newip->i_vicep1 = param1;
- newip->i_vicep2 = param2;
- newip->i_vicep3 = param3;
- newip->i_vicep4 = param4;
- IWRITE_UNLOCK(newip);
- if (nvfsp) {
- vp = newip->i_gnode.gn_vnode;
- } else {
- rc = iptovp(vfsp, newip, &vp);
- }
- setuerror(rc);
-
- rval1 = newip->i_number;
- if (vp) {
- VNOP_RELE(vp);
- }
- return getuerror()? -1 : rval1;
-}
-
-SYSENT(iopen, (dev, inode, usrmod),)
-{
- struct file *fp;
- register struct inode *ip;
- struct vnode *vp = NULL;
- extern struct fileops vnodefops;
- register struct vfs *vfsp;
- int fd;
- char error;
- struct ucred *credp;
- int dummy;
-
- AFS_STATCNT(afs_syscall_iopen);
- if (!suser(&error)) {
- setuerror(error);
- return -1;
- }
-
- if ((vfsp = devtovfs((dev_t) dev)) == 0) {
- afs_warn("Dev=%d not mounted!!; quitting\n", dev);
- setuerror(ENODEV);
- return -1;
- }
- ip = igetinode((dev_t) dev, vfsp, (ino_t) inode, &vp, &dummy);
- if (getuerror())
- return -1;
-
- credp = crref();
- if (setuerror
- (ufdcreate
- ((usrmod - FOPEN) & FMASK, &vnodefops, vp, DTYPE_VNODE, &fd,
- credp))) {
- crfree(credp);
- VNOP_RELE(vp);
- return -1;
- }
-
- if (setuerror(VNOP_OPEN(vp, (usrmod - FOPEN) & FMASK, 0, 0, credp))) {
- close(fd);
- crfree(credp);
- return -1;
- }
- crfree(credp);
- return fd;
-}
-
-
-/*
- * Support for iinc() and idec() system calls--increment or decrement
- * count on inode.
- * Restricted to super user.
- * Only VICEMAGIC type inodes.
- */
-iinc(dev, inode, inode_p1)
-{
-
- AFS_STATCNT(iinc);
- return iincdec(dev, inode, inode_p1, 1);
-}
-
-idec(dev, inode, inode_p1)
-{
-
- AFS_STATCNT(idec);
- return iincdec(dev, inode, inode_p1, -1);
-}
-
-
-SYSENT(iincdec, (dev, inode, inode_p1, amount),)
-{
- register struct inode *ip;
- char error;
- struct vnode *vp = NULL;
- int dummy;
-
- AFS_STATCNT(afs_syscall_iincdec);
- if (!suser(&error)) {
- setuerror(error);
- return -1;
- }
-
- ip = igetinode((dev_t) dev, 0, (ino_t) inode, &vp, &dummy);
- if (getuerror()) {
- return -1;
- }
- IWRITE_LOCK(ip);
- if (ip->i_vicemagic != VICEMAGIC)
- setuerror(EPERM);
- else if (ip->i_vicep1 != inode_p1)
- setuerror(ENXIO);
- else {
- ip->i_nlink += amount;
- if (ip->i_nlink == 0) {
- ip->i_vicemagic = 0;
- ip->i_cflag &= ~CMNEW;
- }
- ip->i_flag |= ICHG;
- commit(1, ip); /* always commit */
- }
- IWRITE_UNLOCK(ip);
- VNOP_RELE(vp);
-/*
- ICACHE_LOCK();
- iput(ip, 0);
- ICACHE_UNLOCK();
-*/
- return getuerror()? -1 : 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
- */
-
-/*
- * Inode information required for AIX servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0x84fa1cb6
-
-/* These exist because HP requires more work to extract uid. */
-#define DI_VICEP3(p) ( (p)->di_vicep3 )
-#define I_VICE3(p) ( (p)->i_vicep3 )
-
-/* rsvrd[4] is in use in large files filesystems for file size. */
-#define di_vicemagic di_rsrvd[0]
-#define di_vicep1 di_rsrvd[1]
-#define di_vicep2 di_rsrvd[2]
-#define di_vicep3 di_rsrvd[3]
-#define di_vicep4 di_rsrvd[4]
-
-#define i_vicemagic i_dinode.di_vicemagic
-#define i_vicep1 i_dinode.di_vicep1
-#define i_vicep2 i_dinode.di_vicep2
-#define i_vicep3 i_dinode.di_vicep3
-#define i_vicep4 i_dinode.di_vicep4
-
-#define IS_VICEMAGIC(ip) ((ip)->i_vicemagic == VICEMAGIC ? 1 : 0)
-#define IS_DVICEMAGIC(dp) ((dp)->di_vicemagic == VICEMAGIC ? 1 : 0)
-
-#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
- */
-
-/*
- * AIX 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_
-
-
-#undef osi_ThreadUnique
-#define osi_ThreadUnique() thread_self()
-
-#define afs_hz HZ
-extern long time;
-#define osi_Time() (time)
-
-#define AFS_UCRED ucred
-#define AFS_PROC struct proc
-
-#define afs_bufferpages v.v_bufhw
-
-#define osi_vnhold(avc, r) do { (avc)->vrefCount++; } while (0)
-#undef AFS_FAST_HOLD
-#define AFS_FAST_HOLD(vp) (vp)->vrefCount++
-#undef AFS_FAST_RELE
-#define AFS_FAST_RELE(vp) (vp)->vrefCount--
-
-#undef gop_lookupname
-#define gop_lookupname(fnamep,segflg,followlink,dirvpp,compvpp) \
- lookupvp((fnamep), (followlink), (compvpp), &afs_osi_cred)
-
-#undef afs_suser
-
-#undef setuerror
-#undef getuerror
-/* #undef getpid getpid() provided by native kernel */
-#include <ulimit.h>
-#define get_ulimit() (ulimit(GET_FSIZE, 0) << UBSHIFT)
-
-#ifdef KERNEL
-#include <sys/lockl.h>
-#include <sys/lock_def.h>
-#include <sys/lock_alloc.h>
-#include <sys/sleep.h>
-
-extern simple_lock_data afs_global_lock;
-#define AFS_GLOCK() do { \
- if (lock_mine((void *)&afs_global_lock)) \
- osi_Panic("AFS_GLOCK %s %d", \
- __FILE__, __LINE__); \
- simple_lock((void *)&afs_global_lock); \
- } while(0)
-#define AFS_GUNLOCK() do { \
- if (!lock_mine((void *)&afs_global_lock)) \
- osi_Panic("AFS_GUNLOCK %s %d", \
- __FILE__, __LINE__); \
- simple_unlock((void *)&afs_global_lock); \
- } while(0)
-#define ISAFS_GLOCK() lock_mine((void *)&afs_global_lock)
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-#endif
-
-#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
- */
-
-/*
- * Implements:
- * Afs_init
- * gop_rdwr
- * aix_gnode_rele
- * afs_suser
- * aix_vattr_null
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_misc.c,v 1.7 2003/07/15 23:14:17 shadow Exp $");
-
-#include "h/systm.h"
-#include "h/types.h"
-#include "h/errno.h"
-#include "h/stat.h"
-#include "h/user.h"
-#include "h/uio.h"
-#include "h/vattr.h"
-#include "h/file.h"
-#include "h/vfs.h"
-#include "h/chownx.h"
-#include "h/systm.h"
-#include "h/access.h"
-#include "rpc/types.h"
-#include "osi_vfs.h"
-#include "netinet/in.h"
-#include "h/mbuf.h"
-#include "rpc/types.h"
-#include "rpc/xdr.h"
-#include "h/vmuser.h"
-#include "h/syspest.h"
-
-#include "afs/stds.h"
-#include "afs/afs_osi.h"
-#define RFTP_INTERNALS 1
-#include "afs/volerrors.h"
-#include "afsint.h"
-#include "vldbint.h"
-#include "afs/lock.h"
-#include "afs/exporter.h"
-#include "afs/afs.h"
-#include "afs/afs_stats.h"
-
-/* In Aix one may specify an init routine routine which is called once during
- * initialization of all gfs; one day we might need to actual do somehing here.
- */
-Afs_init(gfsp)
- char *gfsp; /* this is really struct gfs *, but we do not use it */
-{
- extern int afs_gn_strategy();
-#define AFS_VM_BUFS 50
-
- /* For now nothing special is required during AFS initialization. */
- AFS_STATCNT(afs_init);
-
- (void)vm_mount(D_REMOTE, afs_gn_strategy, AFS_VM_BUFS);
- return 0;
-}
-
-
-/* Some extra handling is needed when calling the aix's version of the local
- * RDWR module, particularly the usage of the uio structure to the lower
- * routine. Note of significant importance to the AFS port is the offset
- * in/out parameter, which in two cases returns a new value back. The cases
- * are: (1) when it's a FIFO file (it's reset to zero) which we don't yet
- * support in AFS and (2) in a regular case when we write
- * (i.e. rw == UIO_WRITE) and are in appending mode (i.e. FAPPEND bit on)
- * where offset is set to the file's size. None of these cases apply to us
- * currently so no problems occur; caution if things change!
- */
-int
-gop_rdwr(rw, vp, base, len, offset, segflg, unit, aresid)
- enum uio_rw rw;
- struct vnode *vp;
- caddr_t base;
-#ifdef AFS_64BIT_KERNEL
- offset_t *offset;
-#else
- off_t *offset;
-#endif
- int len, segflg;
- int *aresid;
- int unit; /* Ignored */
-{
- struct uio uio_struct;
- struct iovec uiovector;
- register int code;
-
- AFS_STATCNT(gop_rdwr);
- /* Set up the uio structure */
- uiovector.iov_base = (caddr_t) base;
- uiovector.iov_len = len;
-
- uio_struct.uio_iov = &uiovector;
- uio_struct.uio_iovcnt = 1;
- uio_struct.uio_offset = *offset;
- uio_struct.uio_segflg = AFS_UIOSYS;
- uio_struct.uio_resid = len;
- uio_struct.uio_fmode = (rw == UIO_READ ? FREAD : FWRITE);
-
-#ifdef AFS_64BIT_KERNEL
- code =
- VNOP_RDWR(vp, rw, (int32long64_t) (rw == UIO_READ ? FREAD : FWRITE),
- &uio_struct, (ext_t) 0, (caddr_t) 0, (struct vattr *)0,
- &afs_osi_cred);
-#else
- code =
- VNOP_RDWR(vp, rw, (rw == UIO_READ ? FREAD : FWRITE), &uio_struct,
- NULL, NULL, NULL, &afs_osi_cred);
-#endif
- *aresid = uio_struct.uio_resid;
- return code;
-}
-
-
-/* Since in AIX a vnode is included in linked lists of its associated vfs and
- * gnode we need to remove these links when removing an AFS vnode (part of the
- * vcache entry). Note that since the accompanied gnode was alloced during
- * vcache creation, we have to free it here too. We don't bother with the
- * vnode itself since it's part of the vcache entry and it's handled fine by
- * default.
- *
- * Note that there is a 1-1 mapping from AFS vnodes to gnodes, so there is
- * no linked list of gnodes to remove this element from.
- */
-aix_gnode_rele(vp)
- struct vnode *vp;
-{
- register struct vnode *tvp;
- register struct vfs *vfsp = vp->v_vfsp;
-
- /* Unlink the vnode from the list the vfs has hanging of it */
- tvp = vfsp->vfs_vnodes;
- if (tvp == vp)
- vfsp->vfs_vnodes = vp->v_vfsnext;
- if (vp->v_vfsnext != NULL)
- vp->v_vfsnext->v_vfsprev = vp->v_vfsprev;
- if (vp->v_vfsprev != NULL)
- vp->v_vfsprev->v_vfsnext = vp->v_vfsnext;
-
- endgnode:
- /* Free the allocated gnode that was accompanying the vcache's vnode */
- if (vp->v_gnode) {
- osi_FreeSmallSpace(vp->v_gnode);
- vp->v_gnode = 0;
- }
-
- return 0;
-}
-
-/*
- * afs_suser() returns true if the caller is superuser, false otherwise.
- *
- * Note that it must NOT set errno.
- */
-
-afs_suser()
-{
- register rc;
- char err;
-
- rc = suser(&err);
- return rc;
-}
+++ /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
- */
-
-#ifndef _OSI_PROTOTYPES_H_
-#define _OSI_PROTOTYPES_H_
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-
-/* osi_groups.c */
-extern void afs_aix_SetupPagRefCount(void);
-
-#endif /* _OSI_PROTOTYPES_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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_sleep.c,v 1.10 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-static char waitV;
-
-static void
-AfsWaitHack(struct trb *trb)
-{
- AFS_STATCNT(WaitHack);
-
- e_clear_wait(trb->func_data, THREAD_TIMED_OUT);
-}
-
-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) thread_self();
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = 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 */
- tid_t 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->cond = EVENT_NULL;
- 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();
- e_assert_wait(&evp->cond, 0);
- AFS_GUNLOCK();
- e_block_thread();
- AFS_GLOCK();
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-/* 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.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- struct timestruc_t ticks;
- struct trb *trb;
- int rc;
-
- ticks.tv_sec = ams / 1000;
- ticks.tv_nsec = (ams - (ticks.tv_sec * 1000)) * 1000000;
-
-
- evp = afs_getevent(event);
-
- trb = talloc();
- if (trb == NULL)
- osi_Panic("talloc returned NULL");
- trb->flags = 0;
- trb->func = AfsWaitHack;
- trb->eventlist = EVENT_NULL;
- trb->ipri = INTTIMER;
- trb->func_data = thread_self();
- trb->timeout.it_value = ticks;
-
- e_assert_wait(&evp->cond, aintok);
- AFS_GUNLOCK();
- tstart(trb);
- rc = e_block_thread();
- while (tstop(trb));
- if (rc == THREAD_INTERRUPTED)
- code = EINTR;
- tfree(trb);
- AFS_GLOCK();
-
- 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++;
- e_wakeup(&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
- */
-
-/*
- * afs_timout.c
- *
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_timeout.c,v 1.7 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "sys/limits.h"
-#include "sys/types.h"
-#include "sys/user.h"
-#include "sys/pri.h"
-#include "sys/priv.h" /* XXX */
-#include "sys/lockl.h"
-#include "sys/malloc.h"
-#include <sys/timer.h> /* For the timer related defines */
-#include <sys/intr.h> /* for the serialization defines */
-
-/* NOTE: This lock makes the callout table MP-safe. timeout itself could
- * be subject to deadlocks if used for anything more complex than we are
- * doing here.
- */
-Simple_lock afs_callout_lock;
-
-#define AFS_DISABLE_LOCK(_pri, _lock) disable_lock((_pri), (_lock))
-#define AFS_UNLOCK_ENABLE(_pri, _lock) unlock_enable((_pri), (_lock))
-
-
-struct tos {
- struct tos *toprev; /* previous tos in callout table */
- struct tos *tonext; /* next tos in callout table */
- struct trb *trb; /* this timer request block */
- afs_int32 type;
- long p1;
-};
-
-struct callo {
- int ncallo; /* number of callout table elements */
- struct tos *head; /* callout table head element */
-};
-
-struct callo afs_callo = { 0, NULL }; /* callout table anchor */
-
-static void timeout_end(struct trb *); /* timeout()'s timeout function */
-extern void tstart(struct trb *);
-extern void i_enable(int);
-
-void
-timeout(register void (*func) (), /* function to call at timeout */
- register caddr_t arg, /* It's argument. */
- register int ticks, /* when to set timeout for */
- register int type, register char *p1)
-{
- register int ipri; /* caller's interrupt priority */
- register struct tos *tos; /* tos to use for timeout */
- register struct trb *trb; /* trb in the tos being used */
- struct itimerstruc_t tv; /* timeout interval */
-
- tv.it_value.tv_sec = ticks / HZ;
- tv.it_value.tv_nsec = (ticks % HZ) * (NS_PER_SEC / HZ);
-
- osi_Assert(afs_callo.ncallo != 0);
-
- timeout_retry:
-
- ipri = AFS_DISABLE_LOCK(INTMAX, &afs_callout_lock);
- /*
- * Run the callout table chain to see if there is already a pending
- * timeout for the specified function. If so, that timeout will
- * be cancelled and the tos re-used.
- */
- for (tos = afs_callo.head; tos != NULL; tos = tos->tonext) {
- if ((tos->trb->tof == func) && (tos->trb->func_data == (ulong) arg)) {
- break;
- }
- }
-
- /*
- * If a pending timeout for the specified function was NOT found,
- * then the callout table chain will have to be run to find an
- * unused tos.
- */
- if (tos == NULL) {
- for (tos = afs_callo.head; tos != NULL; tos = tos->tonext) {
- if (tos->trb->tof == NULL) {
- break;
- }
- }
-
- /*
- * If there isn't an available tos, then there is no error
- * recovery. This means that either the caller has not
- * correctly registered the number of callout table entries
- * that would be needed or is incorrectly using the ones that
- * were registered. Either way, panic is the only recourse.
- */
- osi_Assert(tos != NULL);
- }
- /*
- * A pending timeout for the specified function WAS found.
- * If the request is still active, stop it.
- */
- while (tstop(tos->trb)) {
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
- goto timeout_retry;
- }
-
- tos->type = type; /* Temp */
- tos->p1 = (long)p1; /* Temp */
- tos->trb->knext = NULL;
- tos->trb->kprev = NULL;
- tos->trb->flags = 0;
- tos->trb->timeout = tv;
- tos->trb->tof = func;
- tos->trb->func = timeout_end;
- tos->trb->func_data = (ulong) arg;
- tos->trb->ipri = INTTIMER;
- tos->trb->id = -1;
- tstart(tos->trb);
-
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
-}
-
-
-void
-untimeout(register void (*func) (), register ulong arg)
-{
- register int ipri; /* caller's interrupt priority */
- register struct tos *tos; /* tos to walk callout table */
- register struct trb *trb; /* trb for this tos */
-
- untimeout_retry:
-
- ipri = AFS_DISABLE_LOCK(INTMAX, &afs_callout_lock);
- /* Run the callout table chain looking for the timeout. */
- for (tos = afs_callo.head; tos != NULL; tos = tos->tonext) {
- if (tos->trb->tof == func && tos->trb->func_data == arg) {
- break;
- }
- }
-
- if (tos) {
- /*
- * Found it on the timeout list - stop the pending timeout
- * if it is active.
- */
- while (tstop(tos->trb)) {
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
- goto untimeout_retry;
- }
-
- /* Mark this callout table entry as free. */
- tos->trb->knext = NULL;
- tos->trb->kprev = NULL;
- tos->trb->tof = NULL;
- }
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
-}
-
-
-static void
-timeout_end(struct trb *trb)
-{ /* trb of the current timeout */
- register void (*func) (); /* function to call at timeout */
- int ipri;
- ipri = AFS_DISABLE_LOCK(INTMAX, &afs_callout_lock);
-
- func = trb->tof;
- trb->func = NULL;
- trb->tof = NULL; /* Zero out pointer to user function */
-
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
-
- (*func) (trb->func_data);
- /* for compatibility with untimeout() */
-}
-
-
-int
-timeoutcf(register int cocnt)
-{ /* # entries to change callout table by */
- register int ipri; /* caller's interrupt priority */
- register int rv; /* return value to the caller */
- register struct tos *tos; /* tos to add to/remove from table */
- register struct trb *trb; /* trb in the tos to be added/removed */
-
- rv = 0;
-
- if (cocnt > 0) {
- /*
- * Callout table is being enlarged - keep working until the
- * right number of elements have been added.
- */
- while (cocnt > 0) {
- /* Allocate a timer request block. */
- trb = (struct trb *)talloc();
-
- /*
- * If the low-level timer service could not provide
- * a trb, the callout table can't be expanded any
- * more so get out.
- */
- if (trb == NULL) {
- rv = -1;
- break;
- }
-
- /* Allocate memory for the callout table structure. */
- tos = (struct tos *)
- xmalloc((uint) sizeof(struct tos), (uint) 0, pinned_heap);
-
- /*
- * If memory couldn't be allocated for the tos, the
- * callout table can't be expanded any more so get out.
- */
- if (tos == NULL) {
- rv = -1;
- break;
- } else {
- memset(tos, 0, sizeof(struct tos));
- }
-
- /* The trb and the tos were both allocated. */
- tos->trb = trb;
-#ifdef DEBUG
- /*
- * Debug code to ensure that the low-level timer
- * service talloc() clears out the pointers.
- */
- osi_Assert(trb->knext == NULL);
- osi_Assert(trb->kprev == NULL);
-#endif /* DEBUG */
-
- ipri = AFS_DISABLE_LOCK(INTMAX, &afs_callout_lock);
- if (afs_callo.head == NULL) {
- /*
- * The callout table is currently empty. This
- * is the easy case, just set the head of the
- * callout chain to this tos.
- */
- afs_callo.head = tos;
- } else {
- /*
- * The callout table is not empty. Chain this
- * trb to the head of the callout chain.
- */
- tos->tonext = afs_callo.head;
- afs_callo.head->toprev = tos;
- afs_callo.head = tos;
- }
-
- /* Just finished adding a trb to the callout table. */
- afs_callo.ncallo++;
- cocnt--;
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
- }
- } else {
- /*
- * Callout table is being shrunk - keep working until the
- * right number of elements have been removed being careful
- * only to remove elements which do not belong to timeout
- * requests that are currently active.
- */
- if (cocnt < 0) {
-
- /*
- * There had better be at least as many tos's in
- * the callout table as the size by which the caller
- * wants to decrease the size of the table.
- */
- osi_Assert(afs_callo.ncallo >= -cocnt);
-
- while (cocnt < 0) {
-
- /*
- * Start from the head of the callout chain,
- * making sure that there is a tos at the
- * head (i.e. that there is a callout chain).
- */
- ipri = AFS_DISABLE_LOCK(INTMAX, &afs_callout_lock);
- tos = afs_callo.head;
- osi_Assert(tos != NULL);
-
- /*
- * Keep walking down the callout chain until
- * a tos is found which is not currently
- * active.
- */
- while ((tos != NULL) && (tos->trb->tof != NULL)) {
- tos = tos->tonext;
- }
-
- /*
- * If trb is not NULL, then there was not a
- * callout table entry that wasn't set to
- * timeout. Panic.
- */
- osi_Assert(tos != NULL);
-
- /*
- * Found a free callout table element, free
- * it and remove it from the callout table.
- */
- tfree(tos->trb);
- if (afs_callo.head == tos) {
- afs_callo.head = tos->tonext;
- if (afs_callo.head != NULL) {
- afs_callo.head->toprev = NULL;
- }
- } else {
- osi_Assert(tos->toprev != NULL);
- tos->toprev->tonext = tos->tonext;
- if (tos->tonext != NULL) {
- tos->tonext->toprev = tos->toprev;
- }
- }
- /*
- * Just finished removing a trb from the
- * callout table.
- */
- afs_callo.ncallo--;
- cocnt++;
- AFS_UNLOCK_ENABLE(ipri, &afs_callout_lock);
- xmfree((void *)tos, pinned_heap);
-
- }
- }
- }
-
- return (rv);
-}
+++ /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
- */
-
-#define VREAD R_ACC
-#define VEXEC X_ACC
-#define VWRITE W_ACC
-#define VSUID S_ISUID
-#define VSGID S_ISGID
-#define VSVTX S_ISVTX
-
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#define bcopyin copyin /* Aux has identical bcopyin */
-
-#define BLKDEV_IOSIZE BSIZE
-/*#define MAXBSIZE NFS_MAXDATA*/
-#define VROOT V_ROOT
-#define VTEXT V_TEXT
-/*#define IO_SYNC FSYNC*/
-#define IO_APPEND FAPPEND
-/*#define IO_NDELAY FNDELAY*/
-#define VTOI VTOIP
-/*#define v_pdata v_data*/
-#define v_op v_gnode->gn_ops
-#define iunlock(x) irele(x)
-
-#if !defined(_SUN)
-/*
- * if _SUN is defined, this is in vnode.h (at least today... who knows where
- * they will hide it tomorrow)
- */
-enum vcexcl { NONEXCL, EXCL }; /* (non)exclusive create */
-#endif
-
-struct buf *getblk(), *geteblk(), *breada(), *bread();
-#define b_actf av_forw
-#define dbtob(db) ((unsigned)(db) << 9) /* (db * 512) */
+++ /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 AIX
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_vfsops.c,v 1.11 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-
-
-#ifdef AFS_AIX_IAUTH_ENV
-#include "afs/nfsclient.h"
-#include "afs/exporter.h"
-extern struct afs_exporter *afs_nfsexporter;
-#endif
-
-#define AFS_VFSLOCK_DECL register int glockOwner = ISAFS_GLOCK()
-#define AFS_VFSLOCK() if (!glockOwner) AFS_GLOCK()
-#define AFS_VFSUNLOCK() if (!glockOwner) AFS_GUNLOCK()
-
-struct vfs *afs_globalVFS = 0;
-struct vcache *afs_globalVp = 0;
-
-
-static int afs_root_nolock(struct vfs *afsp, struct vnode **avpp);
-
-static int
-afs_mount(afsp, path, data)
- char *path;
- caddr_t data;
- struct vfs *afsp;
-{
- struct vnode *afsrootvp = NULL;
- int error;
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- AFS_STATCNT(afs_mount);
-
- if (afs_globalVFS) {
- /* Don't allow remounts since some system (like AIX) don't handle
- * it well.
- */
- AFS_VFSUNLOCK();
- return (setuerror(EBUSY));
- }
-
-
- afs_globalVFS = afsp;
- afsp->vfs_bsize = 8192;
- afsp->vfs_count = 0;
-#ifdef AFS_64BIT_CLIENT
- afsp->vfs_flag |= VFS_DEVMOUNT;
-#endif /* AFS_64BIT_CLIENT */
-
- afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
- afsp->vfs_fsid.val[1] = AFS_VFSFSID;
-
- /* For AFS, we don't allow file over file mounts. */
- if (afsp->vfs_mntdover->v_type != VDIR)
- return (ENOTDIR);
- /* try to get the root vnode, but don't worry if you don't. The actual
- * setting of the root vnode (vfs_mntd) is done in afs_root, so that it
- * get re-eval'd at the right time if things aren't working when we
- * first try the mount.
- */
- afs_root_nolock(afsp, &afsrootvp);
-
- afsp->vfs_mntdover->v_mvfsp = afsp;
- afsp->vfs_mdata->vmt_flags |= MNT_REMOTE;
-
-#ifdef AFS_AIX_IAUTH_ENV
- if (afs_iauth_register() < 0)
- afs_warn("Can't register AFS iauth interface.\n");
-#endif
- AFS_VFSUNLOCK();
- return 0;
-}
-
-static int
-afs_unmount(struct vfs *afsp, int flag)
-{
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- AFS_STATCNT(afs_unmount);
-
- afs_globalVFS = 0;
- afs_shutdown();
-
- AFS_VFSUNLOCK();
- return 0;
-}
-
-static int
-afs_root_nolock(struct vfs *afsp, struct vnode **avpp)
-{
- register afs_int32 code = 0;
- struct vrequest treq;
- register struct vcache *tvp = 0;
-
- AFS_STATCNT(afs_root);
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- struct ucred *credp;
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
- credp = crref();
- if (!(code = afs_InitReq(&treq, credp)) && !(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;
- }
- crfree(credp);
- }
- if (tvp) {
- VN_HOLD(AFSTOV(tvp));
-
- VN_LOCK(AFSTOV(tvp));
- AFSTOV(tvp)->v_flag |= VROOT; /* No-op on Ultrix 2.2 */
- VN_UNLOCK(AFSTOV(tvp));
-
- afs_globalVFS = afsp;
- *avpp = AFSTOV(tvp);
- afsp->vfs_mntd = *avpp;
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
- ICL_TYPE_INT32, code);
- return code;
-}
-
-
-static int
-afs_root(struct vfs *afsp, struct vnode **avpp)
-{
- int code;
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- code = afs_root_nolock(afsp, avpp);
- AFS_VFSUNLOCK();
- return code;
-}
-
-static int
-afs_statfs(struct vfs *afsp, struct statfs *abp, struct ucred *credp)
-{
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- AFS_STATCNT(afs_statfs);
-
- abp->f_version = 0;
- abp->f_type = 0;
- abp->f_bsize = afsp->vfs_bsize;
- abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
- abp->f_ffree = 9000000;
- abp->f_vfstype = AFS_VFSFSID;
- abp->f_vfsnumber = afsp->vfs_number;
- abp->f_vfsoff = abp->f_vfslen = abp->f_vfsvers = -1;
- abp->f_fsize = 4096; /* fundamental filesystem block size */
- abp->f_fsid = afsp->vfs_fsid;
- (void)strcpy(abp->f_fname, "/afs");
- (void)strcpy(abp->f_fpack, "AFS");
- abp->f_name_max = 256;
-
- AFS_VFSUNLOCK();
- return 0;
-}
-
-static int
-afs_sync()
-{
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- AFS_STATCNT(afs_sync);
-
- AFS_VFSUNLOCK();
- return 0;
-}
-
-
-/* Note that the cred is only for AIX 4.1.5+ and AIX 4.2+ */
-static int
-afs_vget(struct vfs *vfsp, struct vnode **avcp, struct fileid *fidp,
- struct ucred *credp)
-{
- int code;
- struct vrequest treq;
- AFS_VFSLOCK_DECL;
- AFS_VFSLOCK();
- AFS_STATCNT(afs_vget);
- *avcp = NULL;
-
-#ifdef AFS_AIX_IAUTH_ENV
- /* If the exporter is off and this is an nfsd, fail immediately. */
- if (AFS_NFSXLATORREQ(credp)
- && !(afs_nfsexporter->exp_states & EXP_EXPORTED)) {
- return EACCES;
- }
-#endif
-
- if ((code = afs_InitReq(&treq, credp)) == 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_VFSUNLOCK();
- return code;
-}
-
-static int
-afs_badop()
-{
- return EOPNOTSUPP;
-}
-
-
-struct vfsops Afs_vfsops = {
- afs_mount,
- afs_unmount,
- afs_root,
- afs_statfs,
- afs_sync,
- afs_vget,
- afs_badop, /* vfs_cntl */
- afs_badop /* vfs_quotactl */
-#ifdef AFS_AIX51_ENV
- , afs_badop /* vfs_syncvfs */
-#endif
-};
-
-/*
- * VFS is initialized in osi_config.c
- */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_vm.c,v 1.9 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-/* 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.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- if (avc->vrefCount != 0)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* Just in case someone is still referring to the vnode we
- * give up trying to get rid of this guy */
- if (avc->vrefCount || CheckLock(&avc->lock) || LockWaiters(&avc->lock))
- return EBUSY;
-
- if (avc->segid) {
- AFS_GUNLOCK();
- vms_delete(avc->segid);
- AFS_GLOCK();
- avc->segid = avc->vmh = NULL;
- }
-
- if (avc->credp) {
- crfree(avc->credp);
- avc->credp = NULL;
- }
-
- /* Free the alloced gnode that was accompanying the vcache's vnode */
- aix_gnode_rele(AFSTOV(avc));
-
- return 0;
-}
-
-/* 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)
-{
- if (avc->segid) {
- /*
- * The execsOrWriters test is done so that we don't thrash on
- * the vm_writep call below. We only initiate a pageout of the
- * dirty vm pages on the last store...
- * this is strictly a pragmatic decision, and _does_ break the
- * advertised AFS consistency semantics. Without this hack,
- * AIX systems panic under heavy load. I consider the current
- * behavior a bug introduced to hack around a worse bug. XXX
- *
- * Removed do_writep governing sync'ing behavior.
- */
- ReleaseWriteLock(&avc->lock); /* XXX */
- AFS_GUNLOCK();
- vm_writep(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
- vms_iowait(avc->segid);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 93); /* XXX */
- /*
- * The following is necessary because of the following
- * asynchronicity: We open a file, write to it and
- * close the file
- * if CCore flag is set, we clear it and do the extra
- * decrement ourselves now.
- * If we're called by the CCore clearer, the CCore flag
- * will already be clear, so we don't have to worry about
- * clearing it twice.
- * avc was "VN_HELD" and "crheld" when CCore was set in
- * afs_FakeClose
- */
- if (avc->states & CCore) {
- avc->states &= ~CCore;
- avc->opens--;
- avc->execsOrWriters--;
- AFS_RELE(AFSTOV(avc));
- crfree((struct ucred *)avc->linkData);
- avc->linkData = NULL;
- }
- }
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- if (avc->segid) {
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
- vms_iowait(avc->segid); /* XXX Wait?? XXX */
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 60);
- }
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- if (avc->segid) {
- vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
- /*
- * XXX We probably don't need to wait but better be safe XXX
- */
- vms_iowait(avc->segid);
- }
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- if (avc->segid) {
- int firstpage = (alen + PAGESIZE - 1) / PAGESIZE;
- vm_releasep(avc->segid, firstpage, MAXFSIZE / PAGESIZE - firstpage);
- vms_iowait(avc->segid); /* Do we need this? */
- }
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/AIX/osi_vnodeops.c,v 1.15 2004/03/17 02:29:39 shadow Exp $");
-
-#include "h/systm.h"
-#include "h/types.h"
-#include "h/errno.h"
-#include "h/stat.h"
-#include "h/user.h"
-#include "h/uio.h"
-#include "h/vattr.h"
-#include "h/file.h"
-#include "h/vfs.h"
-#include "h/chownx.h"
-#include "h/systm.h"
-#include "h/access.h"
-#ifdef AFS_AIX51_ENV
-#include "h/acl.h"
-#endif
-#include "rpc/types.h"
-#include "osi_vfs.h"
-#include "netinet/in.h"
-#include "h/mbuf.h"
-#include "h/vmuser.h"
-#include "h/shm.h"
-#include "rpc/types.h"
-#include "rpc/xdr.h"
-
-#include "afs/stds.h"
-#include "afs/afs_osi.h"
-#define RFTP_INTERNALS 1
-#include "afs/volerrors.h"
-#include "afsint.h"
-#include "vldbint.h"
-#include "afs/lock.h"
-#include "afs/exporter.h"
-#include "afs/afs.h"
-#include "afs/afs_chunkops.h"
-#include "afs/afs_stats.h"
-#include "afs/nfsclient.h"
-#include "afs/icl.h"
-#include "afs/prs_fs.h"
-#include "h/flock.h"
-#include "afsincludes.h"
-
-
-/*
- * declare all the functions so they can be used to init the table
- */
-/* creation/naming/deletion */
-int afs_gn_link();
-int afs_gn_mkdir();
-int afs_gn_mknod();
-int afs_gn_remove();
-int afs_gn_rename();
-int afs_gn_rmdir();
-/* lookup, file handle stuff */
-int afs_gn_lookup();
-int afs_gn_fid();
-/* access to files */
-int afs_gn_open();
-int afs_gn_create();
-int afs_gn_hold();
-int afs_gn_rele();
-int afs_gn_close();
-int afs_gn_map();
-int afs_gn_unmap();
-/* manipulate attributes of files */
-int afs_gn_access();
-int afs_gn_getattr();
-int afs_gn_setattr();
-/* data update operations */
-int afs_gn_fclear();
-int afs_gn_fsync();
-int afs_gn_ftrunc();
-int afs_gn_rdwr();
-int afs_gn_lockctl();
-/* extensions */
-int afs_gn_ioctl();
-int afs_gn_readlink();
-int afs_gn_select();
-int afs_gn_symlink();
-int afs_gn_readdir();
-/* buffer ops */
-int afs_gn_strategy();
-/* security things */
-int afs_gn_revoke();
-int afs_gn_getacl();
-int afs_gn_setacl();
-int afs_gn_getpcl();
-int afs_gn_setpcl();
-int afs_gn_enosys();
-
-
-/*
- * declare a struct vnodeops and initialize it with ptrs to all functions
- */
-struct vnodeops afs_gn_vnodeops = {
- /* creation/naming/deletion */
- afs_gn_link,
- afs_gn_mkdir,
- afs_gn_mknod,
- afs_gn_remove,
- afs_gn_rename,
- afs_gn_rmdir,
- /* lookup, file handle stuff */
- afs_gn_lookup,
- afs_gn_fid,
- /* access to files */
- afs_gn_open,
- afs_gn_create,
- afs_gn_hold,
- afs_gn_rele,
- afs_gn_close,
- afs_gn_map,
- afs_gn_unmap,
- /* manipulate attributes of files */
- afs_gn_access,
- afs_gn_getattr,
- afs_gn_setattr,
- /* data update operations */
- afs_gn_fclear,
- afs_gn_fsync,
- afs_gn_ftrunc,
- afs_gn_rdwr,
- afs_gn_lockctl,
- /* extensions */
- afs_gn_ioctl,
- afs_gn_readlink,
- afs_gn_select,
- afs_gn_symlink,
- afs_gn_readdir,
- /* buffer ops */
- afs_gn_strategy,
- /* security things */
- afs_gn_revoke,
- afs_gn_getacl,
- afs_gn_setacl,
- afs_gn_getpcl,
- afs_gn_setpcl,
- afs_gn_enosys, /* vn_seek */
- afs_gn_enosys, /* vn_fsync_range */
- afs_gn_enosys, /* vn_create_attr */
- afs_gn_enosys, /* vn_finfo */
- afs_gn_enosys, /* vn_map_lloff */
- afs_gn_enosys, /* vn_readdir_eofp */
- afs_gn_enosys, /* vn_rdwr_attr */
- afs_gn_enosys, /* vn_memcntl */
- afs_gn_enosys, /* vn_spare7 */
- afs_gn_enosys, /* vn_spare8 */
- afs_gn_enosys, /* vn_spare9 */
- afs_gn_enosys, /* vn_spareA */
- afs_gn_enosys, /* vn_spareB */
- afs_gn_enosys, /* vn_spareC */
- afs_gn_enosys, /* vn_spareD */
- afs_gn_enosys, /* vn_spareE */
- afs_gn_enosys /* vn_spareF */
-#ifdef AFS_AIX51_ENV
- , afs_gn_enosys, /* pagerBackRange */
- afs_gn_enosys, /* pagerGetFileSize */
- afs_gn_enosys, /* pagerReadAhead */
- afs_gn_enosys, /* pagerWriteBehind */
- afs_gn_enosys /* pagerEndCopy */
-#endif
-};
-struct vnodeops *afs_ops = &afs_gn_vnodeops;
-
-
-int
-afs_gn_link(vp, dp, name, cred)
- struct vnode *vp;
- struct vnode *dp;
- char *name;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_link);
- error = afs_link(vp, dp, name, cred);
- afs_Trace3(afs_iclSetp, CM_TRACE_GNLINK, ICL_TYPE_POINTER, vp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_mkdir(dp, name, Mode, cred)
- struct vnode *dp;
- char *name;
-#ifdef AFS_AIX51_ENV
- int32long64_t Mode;
-#else
- int Mode;
-#endif
- struct ucred *cred;
-{
- struct vattr va;
- struct vnode *vp;
- int error;
- int mode = Mode;
-
- AFS_STATCNT(afs_gn_mkdir);
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = (mode & 07777) & ~get_umask();
- error = afs_mkdir(dp, name, &va, &vp, cred);
- if (!error) {
- AFS_RELE(vp);
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_GMKDIR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
- error);
- return (error);
-}
-
-
-int
-afs_gn_mknod(dp, name, Mode, dev, cred)
- struct vnode *dp;
- char *name;
-#ifdef AFS_AIX51_ENV
- int Mode;
-#else
- int Mode;
-#endif
- dev_t dev;
- struct ucred *cred;
-{
- struct vattr va;
- struct vnode *vp;
- int error;
- int mode = Mode;
-
- AFS_STATCNT(afs_gn_mknod);
- VATTR_NULL(&va);
- va.va_type = IFTOVT(mode);
- va.va_mode = (mode & 07777) & ~get_umask();
-
-/**** I'm not sure if suser() should stay here since it makes no sense in AFS; however the documentation says that one "should be super-user unless making a FIFO file. Others systems such as SUN do this checking in the early stages of mknod (before the abstraction), so it's equivalently the same! *****/
- if (va.va_type != VFIFO && !suser(&error))
- return (EPERM);
- switch (va.va_type) {
- case VDIR:
- error = afs_mkdir(dp, name, &va, &vp, cred);
- break;
- case VNON:
- error = EINVAL;
- break;
- case VBAD:
- case VCHR:
- case VBLK:
- va.va_rdev = dev;
- default:
- error = afs_create(dp, name, &va, NONEXCL, mode, &vp, cred);
- }
- if (!error) {
- AFS_RELE(vp);
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_GMKNOD, ICL_TYPE_POINTER, (afs_int32) vp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
- error);
- return (error);
-}
-
-
-int
-afs_gn_remove(vp, dp, name, cred)
- struct vnode *vp; /* Ignored in AFS */
- struct vnode *dp;
- char *name;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_remove);
- error = afs_remove(dp, name, cred);
- afs_Trace3(afs_iclSetp, CM_TRACE_GREMOVE, ICL_TYPE_POINTER, dp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_rename(vp, dp, name, tp, tdp, tname, cred)
- struct vnode *dp;
- char *name;
- struct vnode *vp; /* Ignored in AFS */
- struct vnode *tp; /* Ignored in AFS */
- struct vnode *tdp;
- char *tname;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_rename);
- error = afs_rename(dp, name, tdp, tname, cred);
- afs_Trace4(afs_iclSetp, CM_TRACE_GRENAME, ICL_TYPE_POINTER, dp,
- ICL_TYPE_STRING, name, ICL_TYPE_STRING, tname, ICL_TYPE_LONG,
- error);
- return (error);
-}
-
-
-int
-afs_gn_rmdir(vp, dp, name, cred)
- struct vnode *vp; /* Ignored in AFS */
- struct vnode *dp;
- char *name;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_rmdir);
- error = afs_rmdir(dp, name, cred);
- if (error) {
- if (error == 66 /* 4.3's ENOTEMPTY */ )
- error = EEXIST; /* AIX returns EEXIST where 4.3 used ENOTEMPTY */
- }
- afs_Trace3(afs_iclSetp, CM_TRACE_GRMDIR, ICL_TYPE_POINTER, dp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_lookup(dp, vpp, name, Flags, vattrp, cred)
- struct vattr *vattrp;
- struct vnode *dp;
- struct vnode **vpp;
- char *name;
-#ifdef AFS_AIX51_ENV
- int32long64_t Flags; /* includes FOLLOW... */
-#else
- afs_uint32 Flags; /* includes FOLLOW... */
-#endif
- struct ucred *cred;
-{
- int error;
- int flags = Flags;
-
- AFS_STATCNT(afs_gn_lookup);
- error = afs_lookup(dp, name, vpp, cred);
- afs_Trace3(afs_iclSetp, CM_TRACE_GLOOKUP, ICL_TYPE_POINTER, dp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, error);
- if (vattrp != NULL && error == 0)
- afs_gn_getattr(*vpp, vattrp, cred);
- return (error);
-}
-
-
-int
-afs_gn_fid(vp, fidp, cred)
- struct vnode *vp;
- struct fid *fidp;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_fid);
- error = afs_fid(vp, fidp);
- afs_Trace3(afs_iclSetp, CM_TRACE_GFID, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, (afs_int32) fidp, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_open(vp, Flags, ext, vinfop, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t Flags;
- ext_t ext; /* Ignored in AFS */
-#else
- int Flags;
- int ext; /* Ignored in AFS */
-#endif
- struct ucred **vinfop; /* return ptr for fp->f_vinfo, used as fp->f_cred */
- struct ucred *cred;
-{
- int error;
- struct vattr va;
- struct vcache *tvp = VTOAFS(vp);
- afs_int32 modes;
- int flags = Flags;
-
- AFS_STATCNT(afs_gn_open);
- modes = 0;
- if ((flags & FREAD))
- modes |= R_ACC;
- if ((flags & FEXEC))
- modes |= X_ACC;
- if ((flags & FWRITE) || (flags & FTRUNC))
- modes |= W_ACC;
-
- while ((flags & FNSHARE) && tvp->opens) {
- if (!(flags & FDELAY)) {
- error = ETXTBSY;
- goto abort;
- }
- afs_osi_Sleep(&tvp->opens);
- }
-
- error = afs_access(vp, modes, cred);
- if (error) {
- goto abort;
- }
-
- error = afs_open(&vp, flags, cred);
- if (!error) {
- if (flags & FTRUNC) {
- VATTR_NULL(&va);
- va.va_size = 0;
- error = afs_setattr(vp, &va, cred);
- }
-
- if (flags & FNSHARE)
- tvp->states |= CNSHARE;
-
- if (!error) {
- *vinfop = cred; /* fp->f_vinfo is like fp->f_cred in suns */
- } else {
- /* an error occurred; we've told CM that the file
- * is open, so close it now so that open and
- * writer counts are correct. Ignore error code,
- * as it is likely to fail (the setattr just did).
- */
- afs_close(vp, flags, cred);
- }
- }
-
- abort:
- afs_Trace3(afs_iclSetp, CM_TRACE_GOPEN, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_create(dp, vpp, Flags, name, Mode, vinfop, cred)
- struct vnode *dp;
- struct vnode **vpp;
- char *name;
-#ifdef AFS_AIX51_ENV
- int32long64_t Flags;
- int32long64_t Mode;
-#else
- int Flags;
- int Mode;
-#endif
- struct ucred **vinfop; /* return ptr for fp->f_vinfo, used as fp->f_cred */
- struct ucred *cred;
-{
- struct vattr va;
- enum vcexcl exclusive;
- int error, modes = 0;
- int flags = Flags;
- int mode = Mode;
-
- AFS_STATCNT(afs_gn_create);
- if ((flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
- exclusive = EXCL;
- else
- exclusive = NONEXCL;
- VATTR_NULL(&va);
- va.va_type = VREG;
- va.va_mode = (mode & 07777) & ~get_umask();
- if ((flags & FREAD))
- modes |= R_ACC;
- if ((flags & FEXEC))
- modes |= X_ACC;
- if ((flags & FWRITE) || (flags & FTRUNC))
- modes |= W_ACC;
- error = afs_create(dp, name, &va, exclusive, modes, vpp, cred);
- if (error) {
- return error;
- }
- /* 'cr_luid' is a flag (when it comes thru the NFS server it's set to
- * RMTUSER_REQ) that determines if we should call afs_open(). We shouldn't
- * call it when this NFS traffic since the close will never happen thus
- * we'd never flush the files out to the server! Gross but the simplest
- * solution we came out with */
- if (cred->cr_luid != RMTUSER_REQ) {
- while ((flags & FNSHARE) && VTOAFS(*vpp)->opens) {
- if (!(flags & FDELAY))
- return ETXTBSY;
- afs_osi_Sleep(&VTOAFS(*vpp)->opens);
- }
- /* Since in the standard copen() for bsd vnode kernels they do an
- * vop_open after the vop_create, we must do the open here since there
- * are stuff in afs_open that we need. For example advance the
- * execsOrWriters flag (else we'll be treated as the sun's "core"
- * case). */
- *vinfop = cred; /* save user creds in fp->f_vinfo */
- error = afs_open(vpp, flags, cred);
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_GCREATE, ICL_TYPE_POINTER, dp,
- ICL_TYPE_STRING, name, ICL_TYPE_LONG, mode, ICL_TYPE_LONG,
- error);
- return error;
-}
-
-
-int
-afs_gn_hold(vp)
- struct vnode *vp;
-{
- AFS_STATCNT(afs_gn_hold);
- ++(vp->v_count);
- return (0);
-}
-
-int vmPageHog = 0;
-
-int
-afs_gn_rele(vp)
- struct vnode *vp;
-{
- struct vcache *vcp = VTOAFS(vp);
- int error = 0;
-
- AFS_STATCNT(afs_gn_rele);
- if (vp->v_count == 0)
- osi_Panic("afs_rele: zero v_count");
- if (--(vp->v_count) == 0) {
- if (vcp->states & CPageHog) {
- vmPageHog--;
- vcp->states &= ~CPageHog;
- }
- error = afs_inactive(vp, 0);
- }
- return (error);
-}
-
-
-int
-afs_gn_close(vp, Flags, vinfo, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t Flags;
-#else
- int Flags;
-#endif
- caddr_t vinfo; /* Ignored in AFS */
- struct ucred *cred;
-{
- int error;
- struct vcache *tvp = VTOAFS(vp);
- int flags = Flags;
-
- AFS_STATCNT(afs_gn_close);
-
- if (flags & FNSHARE) {
- tvp->states &= ~CNSHARE;
- afs_osi_Wakeup(&tvp->opens);
- }
-
- error = afs_close(vp, flags, cred);
- afs_Trace3(afs_iclSetp, CM_TRACE_GCLOSE, ICL_TYPE_POINTER, (afs_int32) vp,
- ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_map(vp, addr, Len, Off, Flag, cred)
- struct vnode *vp;
- caddr_t addr;
-#ifdef AFS_AIX51_ENV
- uint32long64_t Len, Off, Flag;
-#else
- u_int Len, Off, Flag;
-#endif
- struct ucred *cred;
-{
- struct vcache *vcp = VTOAFS(vp);
- struct vrequest treq;
- afs_int32 error;
- afs_int32 len = Len;
- afs_int32 off = Off;
- afs_int32 flag = Flag;
-
- AFS_STATCNT(afs_gn_map);
-#ifdef notdef
- if (error = afs_InitReq(&treq, cred))
- return error;
- error = afs_VerifyVCache(vcp, &treq);
- if (error)
- return afs_CheckCode(error, &treq, 49);
-#endif
- osi_FlushPages(vcp, cred); /* XXX ensure old pages are gone XXX */
- ObtainWriteLock(&vcp->lock, 401);
- vcp->states |= CMAPPED; /* flag cleared at afs_inactive */
- /*
- * We map the segment into our address space using the handle returned by vm_create.
- */
- if (!vcp->segid) {
- afs_uint32 tlen = vcp->m.Length;
-#ifdef AFS_64BIT_CLIENT
- if (vcp->m.Length > afs_vmMappingEnd)
- tlen = afs_vmMappingEnd;
-#endif
- /* Consider V_INTRSEG too for interrupts */
- if (error =
- vms_create(&vcp->segid, V_CLIENT, vcp->v.v_gnode, tlen, 0, 0)) {
- ReleaseWriteLock(&vcp->lock);
- return (EOPNOTSUPP);
- }
-#ifdef AFS_64BIT_KERNEL
- vcp->vmh = vm_handle(vcp->segid, (int32long64_t) 0);
-#else
- vcp->vmh = SRVAL(vcp->segid, 0, 0);
-#endif
- }
- vcp->v.v_gnode->gn_seg = vcp->segid; /* XXX Important XXX */
- if (flag & SHM_RDONLY) {
- vp->v_gnode->gn_mrdcnt++;
- } else {
- vp->v_gnode->gn_mwrcnt++;
- }
- /*
- * We keep the caller's credentials since an async daemon will handle the
- * request at some point. We assume that the same credentials will be used.
- */
- if (!vcp->credp || (vcp->credp != cred)) {
- crhold(cred);
- if (vcp->credp) {
- struct ucred *crp = vcp->credp;
- vcp->credp = NULL;
- crfree(crp);
- }
- vcp->credp = cred;
- }
- ReleaseWriteLock(&vcp->lock);
- VN_HOLD(vp);
- afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, addr, ICL_TYPE_LONG, len, ICL_TYPE_LONG, off);
- return (0);
-}
-
-
-int
-afs_gn_unmap(vp, flag, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t flag;
-#else
- int flag;
-#endif
- struct ucred *cred;
-{
- struct vcache *vcp = VTOAFS(vp);
- AFS_STATCNT(afs_gn_unmap);
- ObtainWriteLock(&vcp->lock, 402);
- if (flag & SHM_RDONLY) {
- vp->v_gnode->gn_mrdcnt--;
- if (vp->v_gnode->gn_mrdcnt <= 0)
- vp->v_gnode->gn_mrdcnt = 0;
- } else {
- vp->v_gnode->gn_mwrcnt--;
- if (vp->v_gnode->gn_mwrcnt <= 0)
- vp->v_gnode->gn_mwrcnt = 0;
- }
- ReleaseWriteLock(&vcp->lock);
-
- AFS_RELE(vp);
- return 0;
-}
-
-
-int
-afs_gn_access(vp, Mode, Who, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t Mode;
- int32long64_t Who;
-#else
- int Mode;
- int Who;
-#endif
- struct ucred *cred;
-{
- int error;
- struct vattr vattr;
- int mode = Mode;
- int who = Who;
-
- AFS_STATCNT(afs_gn_access);
- if (mode & ~0x7) {
- error = EINVAL;
- goto out;
- }
-
- error = afs_access(vp, mode, cred);
- if (!error) {
- /* Additional testing */
- if (who == ACC_OTHERS || who == ACC_ANY) {
- error = afs_getattr(vp, &vattr, cred);
- if (!error) {
- if (who == ACC_ANY) {
- if (((vattr.va_mode >> 6) & mode) == mode) {
- error = 0;
- goto out;
- }
- }
- if (((vattr.va_mode >> 3) & mode) == mode)
- error = 0;
- else
- error = EACCES;
- }
- } else if (who == ACC_ALL) {
- error = afs_getattr(vp, &vattr, cred);
- if (!error) {
- if ((!((vattr.va_mode >> 6) & mode))
- || (!((vattr.va_mode >> 3) & mode))
- || (!(vattr.va_mode & mode)))
- error = EACCES;
- else
- error = 0;
- }
- }
-
- }
- out:
- afs_Trace3(afs_iclSetp, CM_TRACE_GACCESS, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, mode, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_getattr(vp, vattrp, cred)
- struct vnode *vp;
- struct vattr *vattrp;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_getattr);
- error = afs_getattr(vp, vattrp, cred);
- afs_Trace2(afs_iclSetp, CM_TRACE_GGETATTR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_setattr(vp, op, arg1, arg2, arg3, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t op;
- int32long64_t arg1;
- int32long64_t arg2;
- int32long64_t arg3;
-#else
- int op;
- int arg1;
- int arg2;
- int arg3;
-#endif
- struct ucred *cred;
-{
- struct vattr va;
- int error = 0;
-
- AFS_STATCNT(afs_gn_setattr);
- VATTR_NULL(&va);
- switch (op) {
- /* change mode */
- case V_MODE:
- va.va_mode = arg1;
- break;
- case V_OWN:
- if ((arg1 & T_OWNER_AS_IS) == 0)
- va.va_uid = arg2;
- if ((arg1 & T_GROUP_AS_IS) == 0)
- va.va_gid = arg3;
- break;
- case V_UTIME:
-#ifdef notdef
- error = afs_access(vp, VWRITE, cred);
- if (error)
- goto out;
-#endif
- if (arg1 & T_SETTIME) {
- va.va_atime.tv_sec = time;
- va.va_mtime.tv_sec = time;
- } else {
- va.va_atime = *(struct timestruc_t *)arg2;
- va.va_mtime = *(struct timestruc_t *)arg3;
- }
- break;
- default:
- error = EINVAL;
- goto out;
- }
-
- error = afs_setattr(vp, &va, cred);
- out:
- afs_Trace2(afs_iclSetp, CM_TRACE_GSETATTR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-char zero_buffer[PAGESIZE];
-int
-afs_gn_fclear(vp, flags, offset, length, vinfo, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t flags;
-#else
- int flags;
-#endif
- offset_t offset;
- offset_t length;
- caddr_t vinfo;
- struct ucred *cred;
-{
- int i, len, error = 0;
- struct iovec iov;
- struct uio uio;
- static int fclear_init = 0;
- register struct vcache *avc = VTOAFS(vp);
-
- AFS_STATCNT(afs_gn_fclear);
- if (!fclear_init) {
- memset(zero_buffer, 0, PAGESIZE);
- fclear_init = 1;
- }
- /*
- * Don't clear past ulimit
- */
- if (offset + length > get_ulimit())
- return (EFBIG);
-
- /* Flush all pages first */
- if (avc->segid) {
- AFS_GUNLOCK();
- vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
- vms_iowait(avc->segid);
- AFS_GLOCK();
- }
- uio.afsio_offset = offset;
- for (i = offset; i < offset + length; i = uio.afsio_offset) {
- len = offset + length - i;
- iov.iov_len = (len > PAGESIZE) ? PAGESIZE : len;
- iov.iov_base = zero_buffer;
- uio.afsio_iov = &iov;
- uio.afsio_iovcnt = 1;
- uio.afsio_seg = AFS_UIOSYS;
- uio.afsio_resid = iov.iov_len;
- if (error = afs_rdwr(vp, &uio, UIO_WRITE, 0, cred))
- break;
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_GFCLEAR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, offset, ICL_TYPE_LONG, length, ICL_TYPE_LONG,
- error);
- return (error);
-}
-
-
-int
-afs_gn_fsync(vp, flags, vinfo, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t flags; /* Not used by AFS */
- int32long64_t vinfo; /* Not used by AFS */
-#else
- int flags; /* Not used by AFS */
- caddr_t vinfo; /* Not used by AFS */
-#endif
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_fsync);
- error = afs_fsync(vp, cred);
- afs_Trace3(afs_iclSetp, CM_TRACE_GFSYNC, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, flags, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_ftrunc(vp, flags, length, vinfo, cred)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t flags; /* Ignored in AFS */
-#else
- int flags; /* Ignored in AFS */
-#endif
- offset_t length;
- caddr_t vinfo; /* Ignored in AFS */
- struct ucred *cred;
-{
- struct vattr va;
- int error;
-
- AFS_STATCNT(afs_gn_ftrunc);
- VATTR_NULL(&va);
- va.va_size = length;
- error = afs_setattr(vp, &va, cred);
- afs_Trace4(afs_iclSetp, CM_TRACE_GFTRUNC, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, flags, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(length), ICL_TYPE_LONG, error);
- return (error);
-}
-
-/* Min size of a file which is dumping core before we declare it a page hog. */
-#define MIN_PAGE_HOG_SIZE 8388608
-
-int
-afs_gn_rdwr(vp, op, Flags, ubuf, ext, vinfo, vattrp, cred)
- struct vnode *vp;
- enum uio_rw op;
-#ifdef AFS_AIX51_ENV
- int32long64_t Flags;
- ext_t ext; /* Ignored in AFS */
-#else
- int Flags;
- int ext; /* Ignored in AFS */
-#endif
- struct uio *ubuf;
- caddr_t vinfo; /* Ignored in AFS */
- struct vattr *vattrp;
- struct ucred *cred;
-{
- register struct vcache *vcp = VTOAFS(vp);
- struct vrequest treq;
- int error = 0;
- int free_cred = 0;
- int flags = Flags;
-
- AFS_STATCNT(afs_gn_rdwr);
-
- if (vcp->vc_error) {
- if (op == UIO_WRITE) {
- afs_Trace2(afs_iclSetp, CM_TRACE_GRDWR1, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, vcp->vc_error);
- return vcp->vc_error;
- } else
- return EIO;
- }
-
- ObtainSharedLock(&vcp->lock, 507);
- /*
- * We keep the caller's credentials since an async daemon will handle the
- * request at some point. We assume that the same credentials will be used.
- * If this is being called from an NFS server thread, then dupe the
- * cred and only use that copy in calls and for the stach.
- */
- if (!vcp->credp || (vcp->credp != cred)) {
-#ifdef AFS_AIX_IAUTH_ENV
- if (AFS_NFSXLATORREQ(cred)) {
- /* Must be able to use cred later, so dupe it so that nfs server
- * doesn't overwrite it's contents.
- */
- cred = crdup(cred);
- free_cred = 1;
- }
-#endif
- crhold(cred); /* Bump refcount for reference in vcache */
-
- if (vcp->credp) {
- struct ucred *crp;
- UpgradeSToWLock(&vcp->lock, 508);
- crp = vcp->credp;
- vcp->credp = NULL;
- ConvertWToSLock(&vcp->lock);
- crfree(crp);
- }
- vcp->credp = cred;
- }
- ReleaseSharedLock(&vcp->lock);
-
- /*
- * XXX Is the following really required?? XXX
- */
- if (error = afs_InitReq(&treq, cred))
- return error;
- if (error = afs_VerifyVCache(vcp, &treq))
- return afs_CheckCode(error, &treq, 50);
- osi_FlushPages(vcp, cred); /* Flush old pages */
-
- if (AFS_NFSXLATORREQ(cred)) {
- if (flags & FSYNC)
- flags &= ~FSYNC;
- if (op == UIO_READ) {
- if (!afs_AccessOK
- (vcp, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- if (free_cred)
- crfree(cred);
- return EACCES;
- }
- }
- }
-
- /*
- * We have to bump the open/exwriters field here courtesy of the nfs xlator
- * because there're no open/close nfs rpcs to call our afs_open/close.
- * We do a similar thing on the afs_read/write interface.
- */
- if (op == UIO_WRITE) {
-#ifdef AFS_64BIT_CLIENT
- if (ubuf->afsio_offset < afs_vmMappingEnd) {
-#endif /* AFS_64BIT_ENV */
- ObtainWriteLock(&vcp->lock, 240);
- vcp->states |= CDirty; /* Set the dirty bit */
- afs_FakeOpen(vcp);
- ReleaseWriteLock(&vcp->lock);
-#ifdef AFS_64BIT_CLIENT
- }
-#endif /* AFS_64BIT_ENV */
- }
-
- error = afs_vm_rdwr(vp, ubuf, op, flags, cred);
-
- if (op == UIO_WRITE) {
-#ifdef AFS_64BIT_CLIENT
- if (ubuf->afsio_offset < afs_vmMappingEnd) {
-#endif /* AFS_64BIT_ENV */
- ObtainWriteLock(&vcp->lock, 241);
- afs_FakeClose(vcp, cred); /* XXXX For nfs trans and cores XXXX */
- ReleaseWriteLock(&vcp->lock);
-#ifdef AFS_64BIT_CLIENT
- }
-#endif /* AFS_64BIT_ENV */
- }
- if (vattrp != NULL && error == 0)
- afs_gn_getattr(vp, vattrp, cred);
-
- afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, flags, ICL_TYPE_LONG, op, ICL_TYPE_LONG, error);
-
- if (free_cred)
- crfree(cred);
- return (error);
-}
-
-#define AFS_MAX_VM_CHUNKS 10
-afs_vm_rdwr(vp, uiop, rw, ioflag, credp)
- register struct vnode *vp;
- struct uio *uiop;
- enum uio_rw rw;
- int ioflag;
- struct ucred *credp;
-{
- register afs_int32 code = 0;
- register int i;
- afs_int32 blockSize;
- afs_size_t fileSize, xfrOffset, offset, old_offset, xfrSize;
- vmsize_t txfrSize;
-#ifdef AFS_64BIT_CLIENT
- afs_size_t finalOffset;
- off_t toffset;
- int mixed = 0;
- afs_size_t add2resid = 0;
-#endif /* AFS_64BIT_CLIENT */
- register struct vcache *vcp = VTOAFS(vp);
- struct dcache *tdc;
- afs_size_t start_offset;
- afs_int32 save_resid = uiop->afsio_resid;
- int first_page, last_page, pages;
- int count, len;
- int counter = 0;
- struct vrequest treq;
-
- if (code = afs_InitReq(&treq, credp))
- return code;
-
- /* special case easy transfer; apparently a lot are done */
- if ((xfrSize = uiop->afsio_resid) == 0)
- return 0;
-
- ObtainReadLock(&vcp->lock);
- fileSize = vcp->m.Length;
- if (rw == UIO_WRITE && (ioflag & IO_APPEND)) { /* handle IO_APPEND mode */
- uiop->afsio_offset = fileSize;
- }
- /* compute xfrOffset now, and do some checks */
- xfrOffset = uiop->afsio_offset;
- if (xfrOffset < 0 || xfrOffset + xfrSize < 0) {
- code = EINVAL;
- goto fail;
- }
-#ifndef AFS_64BIT_CLIENT
- /* check for "file too big" error, which should really be done above us */
- if (rw == UIO_WRITE && xfrSize + fileSize > get_ulimit()) {
- code = EFBIG;
- goto fail;
- }
-#endif /* AFS_64BIT_CLIENT */
-
-#ifdef AFS_64BIT_CLIENT
- if (xfrOffset + xfrSize > afs_vmMappingEnd) {
- if (rw == UIO_READ) {
- /* don't read past EOF */
- if (xfrSize+xfrOffset > fileSize) {
- add2resid = xfrSize + xfrOffset - fileSize;
- xfrSize = fileSize - xfrOffset;
- if (xfrSize <= 0) goto fail;
- txfrSize = xfrSize;
- afsio_trim(uiop, txfrSize);
- }
- }
- if (xfrOffset < afs_vmMappingEnd) {
- /* special case of a buffer crossing the VM mapping line */
- struct uio tuio;
- struct iovec tvec[16]; /* Should have access to #define */
- afs_int32 tsize;
-
- mixed = 1;
- finalOffset = xfrOffset + xfrSize;
- tsize = (afs_size_t) (xfrOffset + xfrSize - afs_vmMappingEnd);
- txfrSize = xfrSize;
- afsio_copy(uiop, &tuio, tvec);
- afsio_skip(&tuio, txfrSize - tsize);
- afsio_trim(&tuio, tsize);
- tuio.afsio_offset = afs_vmMappingEnd;
- ReleaseReadLock(&vcp->lock);
- ObtainWriteLock(&vcp->lock, 243);
- afs_FakeClose(vcp, credp); /* XXXX For nfs trans and cores XXXX */
- ReleaseWriteLock(&vcp->lock);
- code = afs_direct_rdwr(vp, &tuio, rw, ioflag, credp);
- ObtainWriteLock(&vcp->lock, 244);
- afs_FakeOpen(vcp); /* XXXX For nfs trans and cores XXXX */
- ReleaseWriteLock(&vcp->lock);
- ObtainReadLock(&vcp->lock);
- if (code)
- goto fail;
- xfrSize = afs_vmMappingEnd - xfrOffset;
- txfrSize = xfrSize;
- afsio_trim(uiop, txfrSize);
- } else {
- ReleaseReadLock(&vcp->lock);
- code = afs_direct_rdwr(vp, uiop, rw, ioflag, credp);
- uiop->uio_resid += add2resid;
- return code;
- }
- }
-#endif /* AFS_64BIT_CLIENT */
-
- if (!vcp->segid) {
- afs_uint32 tlen = vcp->m.Length;
-#ifdef AFS_64BIT_CLIENT
- if (vcp->m.Length > afs_vmMappingEnd)
- tlen = afs_vmMappingEnd;
-#endif
- /* Consider V_INTRSEG too for interrupts */
- if (code =
- vms_create(&vcp->segid, V_CLIENT, vcp->v.v_gnode, tlen, 0, 0)) {
- goto fail;
- }
-#ifdef AFS_64BIT_KERNEL
- vcp->vmh = vm_handle(vcp->segid, (int32long64_t) 0);
-#else
- vcp->vmh = SRVAL(vcp->segid, 0, 0);
-#endif
- }
- vcp->v.v_gnode->gn_seg = vcp->segid;
- if (rw == UIO_READ) {
- /* don't read past EOF */
- if (xfrSize + xfrOffset > fileSize)
- xfrSize = fileSize - xfrOffset;
- if (xfrSize <= 0)
- goto fail;
- ReleaseReadLock(&vcp->lock);
-#ifdef AFS_64BIT_CLIENT
- toffset = xfrOffset;
- uiop->afsio_offset = xfrOffset;
- afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrOffset),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrSize));
- AFS_GUNLOCK();
- txfrSize = xfrSize;
- code = vm_move(vcp->segid, toffset, txfrSize, rw, uiop);
-#else /* AFS_64BIT_CLIENT */
- AFS_GUNLOCK();
- code = vm_move(vcp->segid, xfrOffset, xfrSize, rw, uiop);
-#endif /* AFS_64BIT_CLIENT */
- AFS_GLOCK();
- /*
- * If at a chunk boundary and staying within chunk,
- * start prefetch of next chunk.
- */
- if (counter == 0 || AFS_CHUNKOFFSET(xfrOffset) == 0
- && xfrSize <= AFS_CHUNKSIZE(xfrOffset)) {
- ObtainWriteLock(&vcp->lock, 407);
- tdc = afs_FindDCache(vcp, xfrOffset);
- if (tdc) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(vcp, tdc, credp, &treq);
- afs_PutDCache(tdc);
- }
- ReleaseWriteLock(&vcp->lock);
- }
-#ifdef AFS_64BIT_CLIENT
- if (mixed) {
- uiop->afsio_offset = finalOffset;
- }
- uiop->uio_resid += add2resid;
-#endif /* AFS_64BIT_CLIENT */
- return code;
- }
-
- /* UIO_WRITE */
- start_offset = uiop->afsio_offset;
- afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(start_offset),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xfrSize));
- ReleaseReadLock(&vcp->lock);
- ObtainWriteLock(&vcp->lock, 400);
- vcp->m.Date = osi_Time(); /* Set file date (for ranlib) */
- /* extend file */
- /* un-protect last page. */
- last_page = vcp->m.Length / PAGESIZE;
-#ifdef AFS_64BIT_CLIENT
- if (vcp->m.Length > afs_vmMappingEnd)
- last_page = afs_vmMappingEnd / PAGESIZE;
-#endif
- vm_protectp(vcp->segid, last_page, 1, FILEKEY);
- if (xfrSize + xfrOffset > fileSize) {
- vcp->m.Length = xfrSize + xfrOffset;
- }
- if ((!(vcp->states & CPageHog)) && (xfrSize >= MIN_PAGE_HOG_SIZE)) {
- vmPageHog++;
- vcp->states |= CPageHog;
- }
- ReleaseWriteLock(&vcp->lock);
-
- /* If the write will fit into a single chunk we'll write all of it
- * at once. Otherwise, we'll write one chunk at a time, flushing
- * some of it to disk.
- */
- count = 0;
-
- /* Only create a page to avoid excess VM access if we're writing a
- * small file which is either new or completely overwrites the
- * existing file.
- */
- if ((xfrOffset == 0) && (xfrSize < PAGESIZE) && (xfrSize >= fileSize)
- && (vcp->v.v_gnode->gn_mwrcnt == 0)
- && (vcp->v.v_gnode->gn_mrdcnt == 0)) {
- (void)vm_makep(vcp->segid, 0);
- }
-
- while (xfrSize > 0) {
- offset = AFS_CHUNKBASE(xfrOffset);
- len = xfrSize;
-
- if (AFS_CHUNKSIZE(xfrOffset) <= len)
- len =
- (afs_size_t) AFS_CHUNKSIZE(xfrOffset) - (xfrOffset - offset);
-
- if (len == xfrSize) {
- /* All data goes to this one chunk. */
- AFS_GUNLOCK();
- old_offset = uiop->afsio_offset;
-#ifdef AFS_64BIT_CLIENT
- uiop->afsio_offset = xfrOffset;
- toffset = xfrOffset;
- txfrSize = xfrSize;
- code = vm_move(vcp->segid, toffset, txfrSize, rw, uiop);
-#else /* AFS_64BIT_CLIENT */
- code = vm_move(vcp->segid, xfrOffset, xfrSize, rw, uiop);
-#endif /* AFS_64BIT_CLIENT */
- AFS_GLOCK();
- xfrOffset += len;
- xfrSize = 0;
- } else {
- /* Write just one chunk's worth of data. */
- struct uio tuio;
- struct iovec tvec[16]; /* Should have access to #define */
-
- /* 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 (counter > 0 && code == 0 && xfrOffset == offset) {
- ObtainWriteLock(&vcp->lock, 403);
- if (xfrOffset > vcp->m.Length)
- vcp->m.Length = xfrOffset;
- code = afs_DoPartialWrite(vcp, &treq);
- vcp->states |= CDirty;
- ReleaseWriteLock(&vcp->lock);
- }
- counter++;
-
- afsio_copy(uiop, &tuio, tvec);
- afsio_trim(&tuio, len);
- tuio.afsio_offset = xfrOffset;
-
- AFS_GUNLOCK();
- old_offset = uiop->afsio_offset;
-#ifdef AFS_64BIT_CLIENT
- toffset = xfrOffset;
- code = vm_move(vcp->segid, toffset, len, rw, &tuio);
-#else /* AFS_64BIT_CLIENT */
- code = vm_move(vcp->segid, xfrOffset, len, rw, &tuio);
-#endif /* AFS_64BIT_CLIENT */
- AFS_GLOCK();
- len -= tuio.afsio_resid;
- afsio_skip(uiop, len);
- xfrSize -= len;
- xfrOffset += len;
- }
-
- first_page = (afs_size_t) old_offset >> PGSHIFT;
- pages =
- 1 + (((afs_size_t) old_offset + (len - 1)) >> PGSHIFT) -
- first_page;
- afs_Trace3(afs_iclSetp, CM_TRACE_VMWRITE2, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_INT32, first_page, ICL_TYPE_INT32, pages);
- AFS_GUNLOCK();
- code = vm_writep(vcp->segid, first_page, pages);
- if (++count > AFS_MAX_VM_CHUNKS) {
- count = 0;
- vms_iowait(vcp->segid);
- }
- AFS_GLOCK();
-
- }
-
- if (count) {
- AFS_GUNLOCK();
- vms_iowait(vcp->segid);
- AFS_GLOCK();
- }
-
- ObtainWriteLock(&vcp->lock, 242);
- if (code == 0 && (vcp->states & CDirty)) {
- code = afs_DoPartialWrite(vcp, &treq);
- }
- vm_protectp(vcp->segid, last_page, 1, RDONLY);
- ReleaseWriteLock(&vcp->lock);
-
- /* If requested, fsync the file after every write */
- if (ioflag & FSYNC)
- afs_fsync(vp, credp);
-
- ObtainReadLock(&vcp->lock);
- if (vcp->vc_error) {
- /* Pretend we didn't write anything. We need to get the error back to
- * the user. If we don't it's possible for a quota error for this
- * write to succeed and the file to be closed without the user ever
- * having seen the store error. And AIX syscall clears the error if
- * anything was written.
- */
- code = vcp->vc_error;
- if (code == EDQUOT || code == ENOSPC)
- uiop->afsio_resid = save_resid;
- }
-#ifdef AFS_64BIT_CLIENT
- if (mixed) {
- uiop->afsio_offset = finalOffset;
- }
-#endif /* AFS_64BIT_CLIENT */
-
- fail:
- ReleaseReadLock(&vcp->lock);
- afs_Trace2(afs_iclSetp, CM_TRACE_VMWRITE3, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_INT32, code);
- return code;
-}
-
-
-afs_direct_rdwr(vp, uiop, rw, ioflag, credp)
- register struct vnode *vp;
- struct uio *uiop;
- enum uio_rw rw;
- int ioflag;
- struct ucred *credp;
-{
- register afs_int32 code = 0;
- afs_size_t fileSize, xfrOffset, offset, old_offset, xfrSize;
- struct vcache *vcp = VTOAFS(vp);
- afs_int32 save_resid = uiop->afsio_resid;
- struct vrequest treq;
-
- if (code = afs_InitReq(&treq, credp))
- return code;
-
- /* special case easy transfer; apparently a lot are done */
- if ((xfrSize = uiop->afsio_resid) == 0)
- return 0;
-
- ObtainReadLock(&vcp->lock);
- fileSize = vcp->m.Length;
- if (rw == UIO_WRITE && (ioflag & IO_APPEND)) { /* handle IO_APPEND mode */
- uiop->afsio_offset = fileSize;
- }
- /* compute xfrOffset now, and do some checks */
- xfrOffset = uiop->afsio_offset;
- if (xfrOffset < 0 || xfrOffset + xfrSize < 0) {
- code = EINVAL;
- ReleaseReadLock(&vcp->lock);
- goto fail;
- }
-
- /* check for "file too big" error, which should really be done above us */
-#ifdef notdef
- if (rw == UIO_WRITE && xfrSize + fileSize > get_ulimit()) {
- code = EFBIG;
- ReleaseReadLock(&vcp->lock);
- goto fail;
- }
-#endif
- ReleaseReadLock(&vcp->lock);
- if (rw == UIO_WRITE) {
- ObtainWriteLock(&vcp->lock, 400);
- vcp->m.Date = osi_Time(); /* Set file date (for ranlib) */
- /* extend file */
- if (xfrSize + xfrOffset > fileSize)
- vcp->m.Length = xfrSize + xfrOffset;
- ReleaseWriteLock(&vcp->lock);
- }
- afs_Trace3(afs_iclSetp, CM_TRACE_DIRECTRDWR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(uiop->afsio_offset),
- ICL_TYPE_LONG, uiop->afsio_resid);
- code = afs_rdwr(vp, uiop, rw, ioflag, credp);
- if (code != 0) {
- uiop->afsio_resid = save_resid;
- } else {
- uiop->afsio_offset = xfrOffset + xfrSize;
- if (uiop->afsio_resid > 0) {
- /* should zero here the remaining buffer */
- uiop->afsio_resid = 0;
- }
- /* 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 (AFS_CHUNKBASE(uiop->afsio_offset) != AFS_CHUNKBASE(xfrOffset)) {
- ObtainWriteLock(&vcp->lock, 402);
- code = afs_DoPartialWrite(vcp, &treq);
- vcp->states |= CDirty;
- ReleaseWriteLock(&vcp->lock);
- }
- }
-
- fail:
- return code;
-}
-
-
-static int
-lock_normalize(vp, lckdat, offset, cred)
- struct vnode *vp;
- struct eflock *lckdat;
- offset_t offset;
- struct ucred *cred;
-{
- struct vattr vattr;
- int code;
-
- switch (lckdat->l_whence) {
- case 0:
- return 0;
- case 1:
- lckdat->l_start += (off_t) offset;
- break;
- case 2:
- code = afs_getattr(vp, &vattr, cred);
- if (code != 0)
- return code;
- lckdat->l_start += (off_t) vattr.va_size;
- break;
- default:
- return EINVAL;
- }
- lckdat->l_whence = 0;
- return 0;
-}
-
-
-
-afs_gn_lockctl(vp, offset, lckdat, cmd, ignored_fcn, ignored_id, cred)
- void (*ignored_fcn) ();
- void *ignored_id;
- struct vnode *vp;
- offset_t offset;
- struct eflock *lckdat;
- struct ucred *cred;
-#ifdef AFS_AIX51_ENV
- int32long64_t cmd;
-#else
- int cmd;
-#endif
-{
- int error, ncmd = 0;
- struct flock flkd;
- struct vattr *attrs;
-
- AFS_STATCNT(afs_gn_lockctl);
- /* Convert from AIX's cmd to standard lockctl lock types... */
- if (cmd == 0)
- ncmd = F_GETLK;
- else if (cmd & SETFLCK) {
- ncmd = F_SETLK;
- if (cmd & SLPFLCK)
- ncmd = F_SETLKW;
- }
- flkd.l_type = lckdat->l_type;
- flkd.l_whence = lckdat->l_whence;
- flkd.l_start = lckdat->l_start;
- flkd.l_len = lckdat->l_len;
- flkd.l_pid = lckdat->l_pid;
- flkd.l_sysid = lckdat->l_sysid;
-
- if (flkd.l_start != lckdat->l_start || flkd.l_len != lckdat->l_len)
- return EINVAL;
- if (error = lock_normalize(vp, &flkd, offset, cred))
- return (error);
- error = afs_lockctl(vp, &flkd, ncmd, cred);
- lckdat->l_type = flkd.l_type;
- lckdat->l_whence = flkd.l_whence;
- lckdat->l_start = flkd.l_start;
- lckdat->l_len = flkd.l_len;
- lckdat->l_pid = flkd.l_pid;
- lckdat->l_sysid = flkd.l_sysid;
- afs_Trace3(afs_iclSetp, CM_TRACE_GLOCKCTL, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, ncmd, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-/* NOTE: In the nfs glue routine (nfs_gn2sun.c) the order was wrong (vp, flags, cmd, arg, ext); was that another typo? */
-int
-afs_gn_ioctl(vp, Cmd, arg, flags, channel, ext)
- struct vnode *vp;
-#ifdef AFS_AIX51_ENV
- int32long64_t Cmd;
-#else
- int Cmd;
-#endif
- int arg;
- int flags; /* Ignored in AFS */
- int channel; /* Ignored in AFS */
- int ext; /* Ignored in AFS */
-{
- int error;
- int cmd = Cmd;
-
- AFS_STATCNT(afs_gn_ioctl);
- /* This seems to be a perfect fit for our ioctl redirection (afs_xioctl hack); thus the ioctl(2) entry in sysent.c is unaffected in the aix/afs port. */
- error = afs_ioctl(vp, cmd, arg);
- afs_Trace3(afs_iclSetp, CM_TRACE_GIOCTL, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, cmd, ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_readlink(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_readlink);
- error = afs_readlink(vp, uiop, cred);
- afs_Trace2(afs_iclSetp, CM_TRACE_GREADLINK, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-int
-afs_gn_select(vp, which, vinfo, mpx)
- struct vnode *vp;
- int which;
- caddr_t *vinfo;
- caddr_t *mpx;
-{
- AFS_STATCNT(afs_gn_select);
- /* NO SUPPORT for this in afs YET! */
- return (EOPNOTSUPP);
-}
-
-
-int
-afs_gn_symlink(vp, link, target, cred)
- struct vnode *vp;
- char *target;
- char *link;
- struct ucred *cred;
-{
- struct vattr va;
- int error;
-
- AFS_STATCNT(afs_gn_symlink);
- VATTR_NULL(&va);
- va.va_mode = 0777;
- error = afs_symlink(vp, link, &va, target, cred);
- afs_Trace4(afs_iclSetp, CM_TRACE_GSYMLINK, ICL_TYPE_POINTER, vp,
- ICL_TYPE_STRING, link, ICL_TYPE_STRING, target, ICL_TYPE_LONG,
- error);
- return (error);
-}
-
-
-int
-afs_gn_readdir(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- int error;
-
- AFS_STATCNT(afs_gn_readdir);
- error = afs_readdir(vp, uiop, cred);
- afs_Trace2(afs_iclSetp, CM_TRACE_GREADDIR, ICL_TYPE_POINTER, vp,
- ICL_TYPE_LONG, error);
- return (error);
-}
-
-
-extern Simple_lock afs_asyncbuf_lock;
-/*
- * Buffers are ranked by age. A buffer's age is the value of afs_biotime
- * when the buffer is processed by naix_vmstrategy. afs_biotime is
- * incremented for each buffer. A buffer's age is kept in its av_back field.
- * The age ranking is used by the daemons, which favor older buffers.
- */
-afs_int32 afs_biotime = 0;
-
-extern struct buf *afs_asyncbuf;
-extern int afs_asyncbuf_cv;
-/* This function is called with a list of buffers, threaded through
- * the av_forw field. Our goal is to copy the list of buffers into the
- * afs_asyncbuf list, sorting buffers into sublists linked by the b_work field.
- * Within buffers within the same work group, the guy with the lowest address
- * has to be located at the head of the queue; his b_bcount field will also
- * be increased to cover all of the buffers in the b_work queue.
- */
-#define AIX_VM_BLKSIZE 8192
-afs_gn_strategy(abp, cred)
- struct ucred *cred;
- register struct buf *abp;
-{
- register struct buf **lbp, *tbp;
-#ifdef AFS_64BIT_KERNEL
- afs_int64 *lwbp; /* last quy in work chain */
-#else
- int *lwbp; /* last guy in work chain */
-#endif
- struct buf *nbp, *qbp, *qnbp, *firstComparable;
- int doMerge;
- int oldPriority;
-
-#define EFS_COMPARABLE(x,y) ((x)->b_vp == (y)->b_vp \
- && (x)->b_xmemd.subspace_id == (y)->b_xmemd.subspace_id \
- && (x)->b_flags == (y)->b_flags \
- && !((x)->b_flags & B_PFPROT) \
- && !((y)->b_flags & B_PFPROT))
-
- oldPriority = disable_lock(INTMAX, &afs_asyncbuf_lock);
- for (tbp = abp; tbp; tbp = nbp) {
- nbp = tbp->av_forw; /* remember for later */
- tbp->b_work = 0;
- tbp->av_back = (struct buf *)afs_biotime++;
-
- /* first insert the buffer into the afs_async queue. Insert buffer
- * sorted within its disk position within a set of comparable buffers.
- * Ensure that all comparable buffers are grouped contiguously.
- * Later on, we'll merge adjacent buffers into a single request.
- */
- firstComparable = NULL;
- lbp = &afs_asyncbuf;
- for (qbp = *lbp; qbp; lbp = &qbp->av_forw, qbp = *lbp) {
- if (EFS_COMPARABLE(tbp, qbp)) {
- if (!firstComparable)
- firstComparable = qbp;
- /* this buffer is comparable, so see if the next buffer
- * is farther in the file; if it is insert before next buffer.
- */
- if (tbp->b_blkno < qbp->b_blkno) {
- break;
- }
- } else {
- /* If we're at the end of a block of comparable buffers, we
- * insert the buffer here to keep all comparable buffers
- * contiguous.
- */
- if (firstComparable)
- break;
- }
- }
- /* do the insert before qbp now */
- tbp->av_forw = *lbp;
- *lbp = tbp;
- if (firstComparable == NULL) {
- /* next we're going to do all sorts of buffer merging tricks, but
- * here we know we're the only COMPARABLE block in the
- * afs_asyncbuf list, so we just skip that and continue with
- * the next input buffer.
- */
- continue;
- }
- /* we may have actually added the "new" firstComparable */
- if (tbp->av_forw == firstComparable)
- firstComparable = tbp;
- /*
- * when we get here, firstComparable points to the first dude in the
- * same vnode and subspace that we (tbp) are in. We go through the
- * area of this list with COMPARABLE buffers (a contiguous region) and
- * repeated merge buffers that are contiguous and in the same block or
- * buffers that are contiguous and are both integral numbers of blocks.
- * Note that our end goal is to have as big blocks as we can, but we
- * must minimize the transfers that are not integral #s of blocks on
- * block boundaries, since Episode will do those smaller and/or
- * unaligned I/Os synchronously.
- *
- * A useful example to consider has the async queue with this in it:
- * [8K block, 2 pages] [4K block, 1 page] [4K hole] [8K block, 2 pages]
- * If we get a request that fills the 4K hole, we want to merge this
- * whole mess into a 24K, 6 page transfer. If we don't, however, we
- * don't want to do any merging since adding the 4K transfer to the 8K
- * transfer makes the 8K transfer synchronous.
- *
- * Note that if there are any blocks whose size is a multiple of
- * the file system block size, then we know that such blocks are also
- * on block boundaries.
- */
-
- doMerge = 1; /* start the loop */
- while (doMerge) { /* loop until an iteration doesn't
- * make any more changes */
- doMerge = 0;
- for (qbp = firstComparable;; qbp = qnbp) {
- qnbp = qbp->av_forw;
- if (!qnbp)
- break; /* we're done */
- if (!EFS_COMPARABLE(qbp, qnbp))
- break;
-
- /* try to merge qbp and qnbp */
-
- /* first check if both not adjacent go on to next region */
- if ((dbtob(qbp->b_blkno) + qbp->b_bcount) !=
- dbtob(qnbp->b_blkno))
- continue;
-
- /* note if both in the same block, the first byte of leftmost guy
- * and last byte of rightmost guy are in the same block.
- */
- if ((dbtob(qbp->b_blkno) & ~(AIX_VM_BLKSIZE - 1)) ==
- ((dbtob(qnbp->b_blkno) + qnbp->b_bcount -
- 1) & ~(AIX_VM_BLKSIZE - 1))) {
- doMerge = 1; /* both in same block */
- } else if ((qbp->b_bcount & (AIX_VM_BLKSIZE - 1)) == 0
- && (qnbp->b_bcount & (AIX_VM_BLKSIZE - 1)) == 0) {
- doMerge = 1; /* both integral #s of blocks */
- }
- if (doMerge) {
- register struct buf *xbp;
-
- /* merge both of these blocks together */
- /* first set age to the older of the two */
-#ifdef AFS_64BIT_KERNEL
- if ((afs_int64) qnbp->av_back - (afs_int64) qbp->av_back <
- 0)
-#else
- if ((int)qnbp->av_back - (int)qbp->av_back < 0)
-#endif
- qbp->av_back = qnbp->av_back;
- lwbp = &qbp->b_work;
- /* find end of qbp's work queue */
- for (xbp = (struct buf *)(*lwbp); xbp;
- lwbp = &xbp->b_work, xbp = (struct buf *)(*lwbp));
- /*
- * now setting *lwbp will change the last ptr in the qbp's
- * work chain
- */
- qbp->av_forw = qnbp->av_forw; /* splice out qnbp */
- qbp->b_bcount += qnbp->b_bcount; /* fix count */
-#ifdef AFS_64BIT_KERNEL
- *lwbp = (afs_int64) qnbp; /* append qnbp to end */
-#else
- *lwbp = (int)qnbp; /* append qnbp to end */
-#endif
- /*
- * note that qnbp is bogus, but it doesn't matter because
- * we're going to restart the for loop now.
- */
- break; /* out of the for loop */
- }
- }
- }
- } /* for loop for all interrupt data */
- /* at this point, all I/O has been queued. Wakeup the daemon */
- e_wakeup_one((int *)&afs_asyncbuf_cv);
- unlock_enable(oldPriority, &afs_asyncbuf_lock);
- return 0;
-}
-
-
-afs_inactive(avc, acred)
- register struct vcache *avc;
- struct AFS_UCRED *acred;
-{
- afs_InactiveVCache(avc, acred);
-}
-
-int
-afs_gn_revoke(vp)
- struct vnode *vp;
-{
- AFS_STATCNT(afs_gn_revoke);
- /* NO SUPPORT for this in afs YET! */
- return (EOPNOTSUPP);
-}
-
-int
-afs_gn_getacl(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- return ENOSYS;
-};
-
-
-int
-afs_gn_setacl(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- return ENOSYS;
-};
-
-
-int
-afs_gn_getpcl(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- return ENOSYS;
-};
-
-
-int
-afs_gn_setpcl(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- return ENOSYS;
-};
-int
-afs_gn_enosys()
-{
- return ENOSYS;
-}
-
-extern struct vfsops Afs_vfsops;
-extern struct vnodeops afs_gn_vnodeops;
-extern int Afs_init();
-
-#define AFS_CALLOUT_TBL_SIZE 256
-
-/*
- * the following additional layer of gorp is due to the fact that the
- * filesystem layer no longer obtains the kernel lock for me. I was relying
- * on this behavior to avoid having to think about locking.
- */
-
-static
-vfs_mount(struct vfs *a, struct ucred *b)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_mount) (a, b);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_unmount(struct vfs *a, int b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_unmount) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_root(struct vfs *a, struct vnode **b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_root) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_statfs(struct vfs *a, struct statfs *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_statfs) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_sync(struct gfs *a)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_sync) (a);
- if (!glockOwner)
- AFS_GUNLOCK();
- return ret;
-}
-
-static
-vfs_vget(struct vfs *a, struct vnode **b, struct fileid *c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_vget) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_cntl(struct vfs *a, int b, caddr_t c, size_t d, struct ucred *e)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_cntl) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vfs_quotactl(struct vfs *a, int b, uid_t c, caddr_t d, struct ucred *e)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_quotactl) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-#ifdef AFS_AIX51_ENV
-static
-vfs_syncvfs(struct gfs *a, struct vfs *b, int c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*Afs_vfsops.vfs_syncvfs) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-#endif
-
-
-struct vfsops locked_Afs_vfsops = {
- vfs_mount,
- vfs_unmount,
- vfs_root,
- vfs_statfs,
- vfs_sync,
- vfs_vget,
- vfs_cntl,
- vfs_quotactl,
-#ifdef AFS_AIX51_ENV
- vfs_syncvfs
-#endif
-};
-
-static
-vn_link(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_link) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_mkdir(struct vnode *a, char *b, int32long64_t c, struct ucred *d)
-{
-#else
-vn_mkdir(struct vnode *a, char *b, int c, struct ucred *d)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_mkdir) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_mknod(struct vnode *a, caddr_t b, int32long64_t c, dev_t d,
- struct ucred *e)
-{
-#else
-vn_mknod(struct vnode *a, caddr_t b, int c, dev_t d, struct ucred *e)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_mknod) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_remove(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_remove) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_rename(struct vnode *a, struct vnode *b, caddr_t c, struct vnode *d,
- struct vnode *e, caddr_t f, struct ucred *g)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_rename) (a, b, c, d, e, f, g);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_rmdir(struct vnode *a, struct vnode *b, char *c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_rmdir) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
- vn_lookup(struct vnode *a, struct vnode **b, char *c, int32long64_t d,
-#else
-vn_lookup(struct vnode *a, struct vnode **b, char *c, int d,
-#endif
- struct vattr *v, struct ucred *e)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_lookup) (a, b, c, d, v, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_fid(struct vnode *a, struct fileid *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_fid) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_open(struct vnode *a, int b, int c, caddr_t * d, struct ucred *e)
-{
-#else
-vn_open(struct vnode *a, int32long64_t b, ext_t c, caddr_t * d,
- struct ucred *e)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_open) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_create(struct vnode *a, struct vnode **b, int32long64_t c, caddr_t d,
- int32long64_t e, caddr_t * f, struct ucred *g)
-{
-#else
-vn_create(struct vnode *a, struct vnode **b, int c, caddr_t d, int e,
- caddr_t * f, struct ucred *g)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_create) (a, b, c, d, e, f, g);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_hold(struct vnode *a)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_hold) (a);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_rele(struct vnode *a)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_rele) (a);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_close(struct vnode *a, int32long64_t b, caddr_t c, struct ucred *d)
-{
-#else
-vn_close(struct vnode *a, int b, caddr_t c, struct ucred *d)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_close) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_map(struct vnode *a, caddr_t b, uint32long64_t c, uint32long64_t d,
- uint32long64_t e, struct ucred *f)
-{
-#else
-vn_map(struct vnode *a, caddr_t b, uint c, uint d, uint e, struct ucred *f)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_map) (a, b, c, d, e, f);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_unmap(struct vnode *a, int32long64_t b, struct ucred *c)
-{
-#else
-vn_unmap(struct vnode *a, int b, struct ucred *c)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_unmap) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_access(struct vnode *a, int32long64_t b, int32long64_t c, struct ucred *d)
-{
-#else
-vn_access(struct vnode *a, int b, int c, struct ucred *d)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_access) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_getattr(struct vnode *a, struct vattr *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_getattr) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_setattr(struct vnode *a, int32long64_t b, int32long64_t c, int32long64_t d,
- int32long64_t e, struct ucred *f)
-{
-#else
-vn_setattr(struct vnode *a, int b, int c, int d, int e, struct ucred *f)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_setattr) (a, b, c, d, e, f);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
- vn_fclear(struct vnode *a, int32long64_t b, offset_t c, offset_t d
-#else
-vn_fclear(struct vnode *a, int b, offset_t c, offset_t d
-#endif
- , caddr_t e, struct ucred *f)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_fclear) (a, b, c, d, e, f);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_fsync(struct vnode *a, int32long64_t b, int32long64_t c, struct ucred *d)
-{
-#else
-vn_fsync(struct vnode *a, int b, int c, struct ucred *d)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_fsync) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_ftrunc(struct vnode *a, int32long64_t b, offset_t c, caddr_t d,
- struct ucred *e)
-{
-#else
-vn_ftrunc(struct vnode *a, int b, offset_t c, caddr_t d, struct ucred *e)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_ftrunc) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_rdwr(struct vnode *a, enum uio_rw b, int32long64_t c, struct uio *d,
- ext_t e, caddr_t f, struct vattr *v, struct ucred *g)
-{
-#else
-vn_rdwr(struct vnode *a, enum uio_rw b, int c, struct uio *d, int e,
- caddr_t f, struct vattr *v, struct ucred *g)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_rdwr) (a, b, c, d, e, f, v, g);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_lockctl(struct vnode *a, offset_t b, struct eflock *c, int32long64_t d,
- int (*e) (), ulong32int64_t * f, struct ucred *g)
-{
-#else
-vn_lockctl(struct vnode *a, offset_t b, struct eflock *c, int d, int (*e) (),
- ulong * f, struct ucred *g)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_lockctl) (a, b, c, d, e, f, g);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_ioctl(struct vnode *a, int32long64_t b, caddr_t c, size_t d, ext_t e,
- struct ucred *f)
-{
-#else
-vn_ioctl(struct vnode *a, int b, caddr_t c, size_t d, int e, struct ucred *f)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_ioctl) (a, b, c, d, e, f);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_readlink(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_readlink) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
- vn_select(struct vnode *a, int32long64_t b, ushort c, ushort * d,
- void (*e) ()
-#else
-vn_select(struct vnode *a, int b, ushort c, ushort * d, void (*e) ()
-#endif
- , caddr_t f, struct ucred *g)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_select) (a, b, c, d, e, f, g);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_symlink(struct vnode *a, char *b, char *c, struct ucred *d)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_symlink) (a, b, c, d);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_readdir(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_readdir) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-#ifdef AFS_AIX51_ENV
-vn_revoke(struct vnode *a, int32long64_t b, int32long64_t c, struct vattr *d,
- struct ucred *e)
-{
-#else
-vn_revoke(struct vnode *a, int b, int c, struct vattr *d, struct ucred *e)
-{
-#endif
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_revoke) (a, b, c, d, e);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_getacl(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_getacl) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_setacl(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_setacl) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_getpcl(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_getpcl) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-static
-vn_setpcl(struct vnode *a, struct uio *b, struct ucred *c)
-{
- register glockOwner, ret;
-
- glockOwner = ISAFS_GLOCK();
- if (!glockOwner)
- AFS_GLOCK();
- ret = (*afs_gn_vnodeops.vn_setpcl) (a, b, c);
- if (!glockOwner)
- AFS_GUNLOCK();
-
- return ret;
-}
-
-extern int afs_gn_strategy();
-
-struct vnodeops locked_afs_gn_vnodeops = {
- vn_link,
- vn_mkdir,
- vn_mknod,
- vn_remove,
- vn_rename,
- vn_rmdir,
- vn_lookup,
- vn_fid,
- vn_open,
- vn_create,
- vn_hold,
- vn_rele,
- vn_close,
- vn_map,
- vn_unmap,
- vn_access,
- vn_getattr,
- vn_setattr,
- vn_fclear,
- vn_fsync,
- vn_ftrunc,
- vn_rdwr,
- vn_lockctl,
- vn_ioctl,
- vn_readlink,
- vn_select,
- vn_symlink,
- vn_readdir,
- afs_gn_strategy, /* no locking!!! (discovered the hard way) */
- vn_revoke,
- vn_getacl,
- vn_setacl,
- vn_getpcl,
- vn_setpcl,
- afs_gn_enosys, /* vn_seek */
- afs_gn_enosys, /* vn_fsync_range */
- afs_gn_enosys, /* vn_create_attr */
- afs_gn_enosys, /* vn_finfo */
- afs_gn_enosys, /* vn_map_lloff */
- afs_gn_enosys, /* vn_readdir_eofp */
- afs_gn_enosys, /* vn_rdwr_attr */
- afs_gn_enosys, /* vn_memcntl */
- afs_gn_enosys, /* vn_spare7 */
- afs_gn_enosys, /* vn_spare8 */
- afs_gn_enosys, /* vn_spare9 */
- afs_gn_enosys, /* vn_spareA */
- afs_gn_enosys, /* vn_spareB */
- afs_gn_enosys, /* vn_spareC */
- afs_gn_enosys, /* vn_spareD */
- afs_gn_enosys, /* vn_spareE */
- afs_gn_enosys /* vn_spareF */
-#ifdef AFS_AIX51_ENV
- , afs_gn_enosys, /* pagerBackRange */
- afs_gn_enosys, /* pagerGetFileSize */
- afs_gn_enosys, /* pagerReadAhead */
- afs_gn_enosys, /* pagerWriteBehind */
- afs_gn_enosys /* pagerEndCopy */
-#endif
-};
-
-struct gfs afs_gfs = {
- &locked_Afs_vfsops,
- &locked_afs_gn_vnodeops,
- AFS_MOUNT_AFS,
- "afs",
- Afs_init,
- GFS_VERSION4 | GFS_REMOTE,
- NULL
-};
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_file.c,v 1.8 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/osi_inode.h"
-
-
-int afs_osicred_initialized = 0;
-struct AFS_UCRED afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct mount *afs_cacheVfsp;
-int afs_CacheFSType = -1;
-
-/* Initialize the cache operations. Called while initializing cache files. */
-void
-afs_InitDualFSCacheOps(struct vnode *vp)
-{
- int code;
- static int inited = 0;
-
- if (inited)
- return;
- inited = 1;
-
- if (vp == NULL)
- return;
- if (strncmp("hfs", vp->v_mount->mnt_vfc->vfc_name, 3) == 0)
- afs_CacheFSType = AFS_APPL_HFS_CACHE;
- else if (strncmp("ufs", vp->v_mount->mnt_vfc->vfc_name, 3) == 0)
- afs_CacheFSType = AFS_APPL_UFS_CACHE;
- else
- osi_Panic("Unknown cache vnode type\n");
-}
-
-ino_t
-VnodeToIno(vnode_t * avp)
-{
- unsigned long ret;
-
- if (afs_CacheFSType == AFS_APPL_UFS_CACHE) {
- struct inode *ip = VTOI(avp);
- ret = ip->i_number;
- } else if (afs_CacheFSType == AFS_APPL_HFS_CACHE) {
-#ifndef VTOH
- struct vattr va;
- if (VOP_GETATTR(avp, &va, &afs_osi_cred, current_proc()))
- osi_Panic("VOP_GETATTR failed in VnodeToIno\n");
- ret = va.va_fileid;
-#else
- struct hfsnode *hp = VTOH(avp);
- ret = H_FILEID(hp);
-#endif
- } else
- osi_Panic("VnodeToIno called before cacheops initialized\n");
- return ret;
-}
-
-
-dev_t
-VnodeToDev(vnode_t * avp)
-{
-
-
- if (afs_CacheFSType == AFS_APPL_UFS_CACHE) {
- struct inode *ip = VTOI(avp);
- return ip->i_dev;
- } else if (afs_CacheFSType == AFS_APPL_HFS_CACHE) {
-#ifndef VTOH /* slow, but works */
- struct vattr va;
- if (VOP_GETATTR(avp, &va, &afs_osi_cred, current_proc()))
- osi_Panic("VOP_GETATTR failed in VnodeToDev\n");
- return va.va_fsid; /* XXX they say it's the dev.... */
-#else
- struct hfsnode *hp = VTOH(avp);
- return H_DEV(hp);
-#endif
- } else
- osi_Panic("VnodeToDev called before cacheops initialized\n");
-}
-
-void *
-osi_UFSOpen(afs_int32 ainode)
-{
- struct vnode *vp;
- struct vattr va;
- 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");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- afs_osi_cred.cr_ref++;
- afs_osi_cred.cr_ngroups = 1;
- afs_osicred_initialized = 1;
- }
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- if (afs_CacheFSType == AFS_APPL_HFS_CACHE)
- code = igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, &ainode, &vp, &va, &dummy); /* XXX hfs is broken */
- else if (afs_CacheFSType == AFS_APPL_UFS_CACHE)
- code =
- igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t) ainode,
- &vp, &va, &dummy);
- else
- panic("osi_UFSOpen called before cacheops initialized\n");
- AFS_GLOCK();
- if (code) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UFSOpen: igetinode failed");
- }
- afile->vnode = vp;
- afile->size = va.va_size;
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, current_proc());
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&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)
-{
- struct AFS_UCRED *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;
- MObtainWriteLock(&afs_xosi, 321);
- VATTR_NULL(&tvattr);
- tvattr.va_size = asize;
- AFS_GUNLOCK();
- code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, current_proc());
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
-
-
- if (afs_CacheFSType == AFS_APPL_UFS_CACHE) {
- struct inode *ip = VTOI(avp);
- ip->i_flag &= ~IN_ACCESS;
- }
-#ifdef VTOH /* can't do this without internals */
- else if (afs_CacheFSType == AFS_APPL_HFS_CACHE) {
- struct hfsnode *hp = VTOH(avp);
- hp->h_nodeflags &= ~IN_ACCESS;
- }
-#endif
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- unsigned int resid;
- register afs_int32 code;
- 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_cred, &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)
-{
- struct AFS_UCRED *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;
- {
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, IO_UNIT, &afs_osi_cred,
- &resid);
- AFS_GLOCK();
- }
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } else {
- code = -1;
- }
- if (afile->proc) {
- (*afile->proc) (afile, code);
- }
- return code;
-}
-
-
-
-
-
-void
-shutdown_osifile(void)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-/*
- * osi_groups.c
- *
- * Implements:
- * Afs_xsetgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_groups.c,v 1.5 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-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;
- struct ucred *cr;
-
- pcred_readlock(p);
- cr = crdup(p->p_cred->pc_ucred);
- pcred_unlock(p);
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
-
- code = afs_InitReq(&treq, cr);
- AFS_GUNLOCK();
- crfree(cr);
- if (code)
- return setgroups(p, args, retval); /* afs has shut down */
-
- 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.
- */
- pcred_readlock(p);
- cr = crdup(p->p_cred->pc_ucred);
- pcred_unlock(p);
-
- if (PagInCred(cr) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- AddPag(p, treq.uid, &cr);
- AFS_GUNLOCK();
- }
- }
- crfree(cr);
- 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[1], gidset[2]) == NOPAG) {
- /* We will have to shift grouplist to make room for pag */
- if (ngroups + 2 > NGROUPS) {
- return (E2BIG);
- }
- for (j = ngroups - 1; j >= 1; j--) {
- gidset[j + 2] = gidset[j];
- }
- ngroups += 2;
- }
- *newpag = (pagvalue == -1 ? genpag() : pagvalue);
- afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
- 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 *oldcr, *cr;
-
- AFS_STATCNT(afs_setgroups);
- /*
- * The real setgroups() call does this, so maybe we should too.
- *
- */
- if (ngroups > NGROUPS)
- return EINVAL;
- cr = *cred;
- cr->cr_ngroups = ngroups;
- gp = cr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- if (change_parent) {
- crhold(cr);
- pcred_writelock(proc->p_pptr);
- oldcr = proc->p_pptr->p_cred->pc_ucred;
- proc->p_pptr->p_cred->pc_ucred = cr;
- pcred_unlock(proc->p_pptr);
- crfree(oldcr);
- }
- crhold(cr);
- pcred_writelock(proc);
- oldcr = proc->p_cred->pc_ucred;
- proc->p_cred->pc_ucred = cr;
- pcred_unlock(proc);
- crfree(oldcr);
- 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
- */
-/*
- * MACOS inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_inode.c,v 1.6 2003/07/15 23:14:17 shadow Exp $");
-
-#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 <ufs/ufs/ufsmount.h>
-extern struct ucred afs_osi_cred;
-
-getinode(fs, dev, inode, vpp, perror)
- struct mount *fs;
- struct vnode **vpp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct vnode *vp;
- int code;
-
- *vpp = 0;
- *perror = 0;
- if (!fs) {
- register struct ufsmount *ump;
-#ifdef VFSTOHFS
- register struct hfsmount *hmp;
-#endif
- register struct vnode *vp;
- register struct mount *mp;
- extern struct mount *rootfs;
- if (mp = rootfs)
- do {
- /*
- * XXX Also do the test for MFS
- */
- if (!strcmp(mp->mnt_vfc->vfc_name, "ufs")) {
- ump = VFSTOUFS(mp);
- if (ump->um_fs == NULL)
- break;
- if (ump->um_dev == dev) {
- fs = ump->um_mountp;
- }
- }
-#ifdef VFSTOHFS
- if (!strcmp(mp->mnt_vfc->vfc_name, "hfs")) {
- hmp = VFSTOHFS(mp);
-#if 0
- if (hmp->hfs_mp == NULL)
- break;
-#endif
- if (hmp->hfs_raw_dev == dev) {
- fs = hmp->hfs_mp;
- }
- }
-#endif
-
- mp = CIRCLEQ_NEXT(mp, mnt_list);
- } while (mp != rootfs);
- if (!fs)
- return (ENXIO);
- }
- code = VFS_VGET(fs, (void *)inode, &vp);
- if (code) {
- *perror = BAD_IGET;
- return code;
- } else {
- *vpp = vp;
- return (0);
- }
-}
-extern int afs_CacheFSType;
-igetinode(vfsp, dev, inode, vpp, va, perror)
- struct vnode **vpp;
- struct mount *vfsp;
- dev_t dev;
- ino_t inode;
- struct vattr *va;
- int *perror;
-{
- struct vnode *pvp, *vp;
- extern struct osi_dev cacheDev;
- register int code = 0;
-
- *perror = 0;
-
- AFS_STATCNT(igetinode);
- if ((code = getinode(vfsp, dev, inode, &vp, perror)) != 0) {
- return (code);
- }
- if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
- printf("igetinode: bad type %d\n", vp->v_type);
- iforget(vp);
- return (ENOENT);
- }
- VOP_GETATTR(vp, va, &afs_osi_cred, current_proc());
- if (va->va_mode == 0) {
- /* Not an allocated inode */
- iforget(vp);
- return (ENOENT);
- }
- if (vfsp && afs_CacheFSType == AFS_APPL_HFS_CACHE && va->va_nlink == 0) {
- printf("igetinode: hfs nlink 0\n");
- }
- if (va->va_nlink == 0) {
- vput(vp);
- return (ENOENT);
- }
-
- VOP_UNLOCK(vp, 0, current_proc());
- *vpp = vp;
- return (0);
-}
-
-iforget(vp)
- struct vnode *vp;
-{
-
- AFS_STATCNT(iforget);
- /* XXX could sleep */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, current_proc());
- /* this whole thing is too wierd. Why??? XXX */
- if (vp->v_usecount == 1) {
- vp->v_usecount = 0;
- VOP_UNLOCK(vp, 0, current_proc());
-#if 0
- simple_lock(&vnode_free_list_slock);
- TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
- freevnodes++;
- simple_unlock(&vnode_free_list_slock);
-#else
- printf("iforget: leaking vnode\n");
-#endif
- } else {
- vput(vp);
- }
-}
-
-#if 0
-/*
- * 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())
- 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())
- return (EPERM);
-
- code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
- if (code) {
- return (code);
- }
- if ((code = falloc(&fp, &fd)) != 0) {
- iput(ip);
- return (code);
- }
- IN_UNLOCK(ip);
-
- FP_LOCK(fp);
- fp->f_flag = (usrmod - FOPEN) & FMASK;
- fp->f_type = DTYPE_VNODE;
- fp->f_ops = &vnops;
- fp->f_data = (caddr_t) ITOV(ip);
-
- FP_UNLOCK(fp);
- U_FD_SET(fd, fp, &u.u_file_state);
- *retval = fd;
- 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())
- 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);
-}
-#else
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
- long *retval;
- long dev, near_inode, param1, param2, param3, param4;
-{
- return EOPNOTSUPP;
-}
-
-afs_syscall_iopen(dev, inode, usrmod, retval)
- long *retval;
- int dev, inode, usrmod;
-{
- return EOPNOTSUPP;
-}
-
-afs_syscall_iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- return EOPNOTSUPP;
-}
-#endif
+++ /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 MACOS servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0x84fa1cb6
-
-#define DI_VICEP3(p) ((p)->di_vicep3)
-#define I_VICEP3(p) ((p)->i_vicep3)
-
-#define i_vicemagic i_din.di_flags
-#define i_vicep1 i_din.di_gen
-#define i_vicep2 i_din.di_uid
-#define i_vicep3 i_din.di_gid
-#define i_vicep4 i_din.di_spare[0] /* not used */
-
-#define di_vicemagic di_flags
-#define di_vicep1 di_gen
-#define di_vicep2 di_uid
-#define di_vicep3 di_gid
-#define di_vicep4 di_spare[0] /* not used */
-
-#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
- */
-/*
- *
- * MACOS 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_
-
-#ifdef XAFS_DARWIN_ENV
-#ifndef _MACH_ETAP_H_
-#define _MACH_ETAP_H_
-typedef unsigned short etap_event_t;
-#endif
-#endif
-
-#include <sys/lock.h>
-#include <kern/thread.h>
-#include <sys/user.h>
-
-#define getpid() current_proc()->p_pid
-#define getppid() current_proc()->p_pptr->p_pid
-#undef gop_lookupname
-#define gop_lookupname osi_lookupname
-
-#define FTRUNC 0
-
-/* vcexcl - used only by afs_create */
-enum vcexcl { EXCL, NONEXCL };
-
-/*
- * Time related macros
- */
-#ifndef AFS_DARWIN60_ENV
-extern struct timeval time;
-#endif
-#define osi_Time() (time.tv_sec)
-#define afs_hz hz
-
-#define PAGESIZE 8192
-
-#define AFS_UCRED ucred
-
-#define AFS_PROC struct proc
-
-#define osi_vnhold(avc,r) do { \
- if ((avc)->vrefCount) { VN_HOLD(&((avc)->v)); } \
- else (avc)->vrefCount = 1; } 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),current_proc())
-
-#undef afs_suser
-
-#ifdef KERNEL
-extern thread_t afs_global_owner;
-/* simple locks cannot be used since sleep can happen at any time */
-/* Should probably use mach locks rather than bsd locks, since we use the
- mach thread control api's elsewhere (mach locks not used for consistency
- with rx, since rx needs lock_write_try() in order to use mach locks
- */
-extern struct lock__bsd__ afs_global_lock;
-#define AFS_GLOCK() \
- do { \
- lockmgr(&afs_global_lock, LK_EXCLUSIVE, 0, current_proc()); \
- osi_Assert(afs_global_owner == 0); \
- afs_global_owner = current_thread(); \
- } while (0)
-#define AFS_GUNLOCK() \
- do { \
- osi_Assert(afs_global_owner == current_thread()); \
- afs_global_owner = 0; \
- lockmgr(&afs_global_lock, LK_RELEASE, 0, current_proc()); \
- } while(0)
-#define ISAFS_GLOCK() (afs_global_owner == current_thread())
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-
-#define SPLVAR
-#define NETPRI
-#define USERPRI
-#if 0
-#undef SPLVAR
-#define SPLVAR int x;
-#undef NETPRI
-#define NETPRI x=splnet();
-#undef USERPRI
-#define USERPRI splx(x);
-#endif
-
-#define AFS_APPL_UFS_CACHE 1
-#define AFS_APPL_HFS_CACHE 2
-
-extern ino_t VnodeToIno(vnode_t * vp);
-extern dev_t VnodeToDev(vnode_t * vp);
-
-#endif /* KERNEL */
-
-#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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_misc.c,v 1.5 2003/07/15 23:14:17 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include <sys/namei.h>
-
-int
-osi_lookupname(char *aname, enum uio_seg seg, int followlink,
- struct vnode **dirvpp, struct vnode **vpp)
-{
- struct nameidata n;
- int flags, error;
- flags = 0;
- flags = LOCKLEAF;
- if (followlink)
- flags |= FOLLOW;
- else
- flags |= NOFOLLOW;
- /* if (dirvpp) flags|=WANTPARENT; *//* XXX LOCKPARENT? */
- NDINIT(&n, LOOKUP, flags, seg, aname, current_proc());
- if (error = namei(&n))
- return error;
- *vpp = n.ni_vp;
-/*
- if (dirvpp)
- *dirvpp = n.ni_dvp;
-#/
- /* should we do this? */
- VOP_UNLOCK(n.ni_vp, 0, current_proc());
- return 0;
-}
-
-/*
- * afs_suser() returns true if the caller is superuser, false otherwise.
- *
- * Note that it must NOT set errno.
- */
-
-afs_suser()
-{
- int error;
- struct proc *p = current_proc();
-
- if ((error = suser(p->p_ucred, &p->p_acflag)) == 0) {
- return (1);
- }
- return (0);
-}
+++ /dev/null
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_module.c,v 1.10 2003/07/15 23:14:18 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#ifdef AFS_DARWIN60_ENV /* not in Kernel.framework anymore !?! */
-#include <sys/syscall.h>
-#else
-#include "sys/syscall.h"
-#endif
-#include <mach/kmod.h>
-
-struct vfsconf afs_vfsconf;
-extern struct vfsops afs_vfsops;
-extern struct mount *afs_globalVFS;
-extern int Afs_xsetgroups();
-extern int afs_xioctl();
-extern int afs3_syscall();
-
-extern int ioctl();
-extern int setgroups();
-extern int maxvfsconf;
-kern_return_t
-afs_modload(struct kmod_info *ki, void *data)
-{
- if (sysent[AFS_SYSCALL].sy_call != nosys) {
- printf("AFS_SYSCALL in use. aborting\n");
- return KERN_FAILURE;
- }
- memset(&afs_vfsconf, 0, sizeof(struct vfsconf));
- strcpy(afs_vfsconf.vfc_name, "afs");
- afs_vfsconf.vfc_vfsops = &afs_vfsops;
- afs_vfsconf.vfc_typenum = maxvfsconf++; /* oddly not VT_AFS */
- afs_vfsconf.vfc_flags = MNT_NODEV;
- if (vfsconf_add(&afs_vfsconf)) {
- printf("AFS: vfsconf_add failed. aborting\n");
- return KERN_FAILURE;
- }
- sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
- sysent[SYS_ioctl].sy_call = afs_xioctl;
- sysent[AFS_SYSCALL].sy_call = afs3_syscall;
- sysent[AFS_SYSCALL].sy_narg = 5;
- sysent[AFS_SYSCALL].sy_parallel = 0;
-#ifdef KERNEL_FUNNEL
- sysent[AFS_SYSCALL].sy_funnel = KERNEL_FUNNEL;
-#endif
- return KERN_SUCCESS;
-}
-
-kern_return_t
-afs_modunload(struct kmod_info * ki, void *data)
-{
- if (afs_globalVFS)
- return KERN_FAILURE;
- if (vfsconf_del("afs"))
- return KERN_FAILURE;
- /* give up syscall entries for ioctl & setgroups, which we've stolen */
- sysent[SYS_ioctl].sy_call = ioctl;
- sysent[SYS_setgroups].sy_call = setgroups;
- /* give up the stolen syscall entry */
- sysent[AFS_SYSCALL].sy_narg = 0;
- sysent[AFS_SYSCALL].sy_call = nosys;
- return KERN_SUCCESS;
-}
-
-KMOD_EXPLICIT_DECL(org.openafs.filesystems.afs, VERSION, afs_modload,
- afs_modunload)
+++ /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_prototypes.h
- *
- * Exported macos support routines.
- */
-#ifndef _OSI_PROTO_H_
-#define _OSI_PROTO_H_
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-
-/* osi_misc.c */
-extern int osi_lookupname(char *aname, enum uio_seg seg, int followlink,
- struct vnode **dirvpp, struct vnode **vpp);
-/* osi_vm.c */
-extern void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size);
-extern int osi_VM_Setup(struct vcache *avc, int force);
-#endif /* _OSI_PROTO_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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_sleep.c,v 1.9 2003/07/15 23:14:18 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-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;
- struct proc *p = current_proc();
-
- AFS_STATCNT(osi_Wait);
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) p;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = 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 */
-} 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();
- AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
- /* this is probably safe for all versions, but testing is hard */
- sleep(event, PVFS);
-#else
- assert_wait((event_t) event, 0);
- thread_block(0);
-#endif
- AFS_GLOCK();
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-/* 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.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- int ticks, seq;
- int prio;
-
- ticks = (ams * afs_hz) / 1000;
-
-
- evp = afs_getevent(event);
- seq = evp->seq;
- AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
- /* this is probably safe for all versions, but testing is hard. */
- /* using tsleep instead of assert_wait/thread_set_timer/thread_block
- * allows shutdown to work in 1.4 */
- /* lack of PCATCH does *not* prevent signal delivery, neither does
- * a low priority. We would need to deal with ERESTART here if we
- * wanted to mess with p->p_sigmask, and messing with p_sigignore is
- * not the way to go.... (someone correct me if I'm wrong)
- */
- if (aintok)
- prio = PCATCH | PPAUSE;
- else
- prio = PVFS;
- code = tsleep(event, prio, "afs_osi_TimedSleep", ticks);
-#else
- assert_wait((event_t) event, aintok ? THREAD_ABORTSAFE : THREAD_UNINT);
- thread_set_timer(ticks, NSEC_PER_SEC / hz);
- thread_block(0);
- code = 0;
-#endif
- AFS_GLOCK();
- if (seq == evp->seq)
- code = EINTR;
-
- relevent(evp);
- return code;
-}
-
-
-int
-afs_osi_Wakeup(void *event)
-{
- struct afs_event *evp;
- int ret = 1;
-
- evp = afs_getevent(event);
- if (evp->refcount > 1) {
- evp->seq++;
-#ifdef AFS_DARWIN14_ENV
- /* this is probably safe for all versions, but testing is hard. */
- wakeup(event);
-#else
- thread_wakeup((event_t) event);
-#endif
- ret = 0;
- }
- relevent(evp);
- return ret;
-}
+++ /dev/null
-/*
- * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
- */
-#include <afsconfig.h>
-#include <afs/param.h>
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v 1.11 2003/10/24 06:26:01 shadow Exp $");
-
-#include <afs/sysincludes.h> /* Standard vendor system headers */
-#include <afsincludes.h> /* Afs-based standard headers */
-#include <afs/afs_stats.h> /* statistics */
-#include <sys/malloc.h>
-#include <sys/namei.h>
-#include <sys/conf.h>
-#include <sys/syscall.h>
-#include <sys/sysctl.h>
-#include "../afs/sysctl.h"
-
-struct vcache *afs_globalVp = 0;
-struct mount *afs_globalVFS = 0;
-
-int
-afs_quotactl()
-{
- return EOPNOTSUPP;
-}
-
-int
-afs_fhtovp(mp, fhp, vpp)
- struct mount *mp;
- struct fid *fhp;
- struct vnode **vpp;
-{
-
- return (EINVAL);
-}
-
-int
-afs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EINVAL);
-}
-
-int
-afs_start(mp, flags, p)
- struct mount *mp;
- int flags;
- struct proc *p;
-{
- return (0); /* nothing to do. ? */
-}
-
-int
-afs_mount(mp, path, data, ndp, p)
- register struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- /* ndp contains the mounted-from device. Just ignore it.
- * we also don't care about our proc struct. */
- size_t size;
- int error;
-
- if (mp->mnt_flag & MNT_UPDATE)
- return EINVAL;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_mount);
-
- if (data == NULL && afs_globalVFS) { /* Don't allow remounts. */
- AFS_GUNLOCK();
- return (EBUSY);
- }
-
- afs_globalVFS = mp;
- mp->vfs_bsize = 8192;
- vfs_getnewfsid(mp);
- mp->mnt_stat.f_iosize = 8192;
-
- (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
- memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
- memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-
- if (data == NULL) {
- strcpy(mp->mnt_stat.f_mntfromname, "AFS");
- /* null terminated string "AFS" will fit, just leave it be. */
- mp->mnt_data = (qaddr_t) NULL;
- } else {
- struct VenusFid *rootFid = NULL;
- struct volume *tvp;
- char volName[MNAMELEN];
-
- (void)copyinstr((char *)data, volName, MNAMELEN - 1, &size);
- memset(volName + size, 0, MNAMELEN - size);
-
- if (volName[0] == 0) {
- strcpy(mp->mnt_stat.f_mntfromname, "AFS");
- mp->mnt_data = (qaddr_t) & afs_rootFid;
- } else {
- struct cell *localcell = afs_GetPrimaryCell(READ_LOCK);
- if (localcell == NULL) {
- AFS_GUNLOCK();
- return ENODEV;
- }
-
- /* Set the volume identifier to "AFS:volume.name" */
- snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN - 1, "AFS:%s",
- volName);
- tvp =
- afs_GetVolumeByName(volName, localcell->cellNum, 1,
- (struct vrequest *)0, READ_LOCK);
-
- if (tvp) {
- int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
- MALLOC(rootFid, struct VenusFid *, sizeof(*rootFid), M_UFSMNT,
- M_WAITOK);
- rootFid->Cell = localcell->cellNum;
- rootFid->Fid.Volume = volid;
- rootFid->Fid.Vnode = 1;
- rootFid->Fid.Unique = 1;
- } else {
- AFS_GUNLOCK();
- return ENODEV;
- }
-
- mp->mnt_data = (qaddr_t) rootFid;
- }
- }
- strcpy(mp->mnt_stat.f_fstypename, "afs");
- AFS_GUNLOCK();
- (void)afs_statfs(mp, &mp->mnt_stat, p);
- return 0;
-}
-
-int
-afs_unmount(mp, flags, p)
- struct mount *mp;
- int flags;
- struct proc *p;
-{
-
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
-
- if (mp->mnt_data != (qaddr_t) - 1) {
- if (mp->mnt_data != NULL) {
- FREE(mp->mnt_data, M_UFSMNT);
- mp->mnt_data = (qaddr_t) - 1;
- } else {
- if (flags & MNT_FORCE) {
- afs_globalVFS = 0;
- afs_shutdown();
- } else {
- AFS_GUNLOCK();
- return EBUSY;
- }
- }
- mp->mnt_flag &= ~MNT_LOCAL;
- }
-
- AFS_GUNLOCK();
-
- return 0;
-}
-
-int
-afs_root(struct mount *mp, struct vnode **vpp)
-{
- int error;
- struct vrequest treq;
- register struct vcache *tvp = 0;
- struct proc *p = current_proc();
- struct ucred cr;
-
- pcred_readlock(p);
- cr = *p->p_cred->pc_ucred;
- pcred_unlock(p);
- AFS_GLOCK();
- AFS_STATCNT(afs_root);
- if (mp->mnt_data == NULL && afs_globalVp
- && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- error = 0;
- } else if (mp->mnt_data == (qaddr_t) - 1) {
- error = ENOENT;
- } else {
- struct VenusFid *rootFid = (mp->mnt_data == NULL)
- ? &afs_rootFid : (struct VenusFid *)mp->mnt_data;
-
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(error = afs_InitReq(&treq, &cr)) && !(error = afs_CheckInit())) {
- tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
- /* we really want this to stay around */
- if (tvp) {
- if (mp->mnt_data == NULL)
- afs_globalVp = tvp;
- } else
- error = ENOENT;
- }
- }
- if (tvp) {
- osi_vnhold(tvp, 0);
- AFS_GUNLOCK();
- vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
- AFS_GLOCK();
- if (mp->mnt_data == NULL) {
- afs_globalVFS = mp;
- }
- *vpp = AFSTOV(tvp);
- AFSTOV(tvp)->v_flag |= VROOT;
- AFSTOV(tvp)->v_vfsp = mp;
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
- ICL_TYPE_INT32, error);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vget(mp, lfl, vp)
- struct mount *mp;
- struct vnode *vp;
- int lfl;
-{
- int error;
- printf("vget called. help!\n");
- if (vp->v_usecount < 0) {
- vprint("bad usecount", vp);
- panic("afs_vget");
- }
- error = vget(vp, lfl, current_proc());
- if (!error)
- insmntque(vp, mp); /* take off free list */
- return error;
-}
-
-int
-afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_statfs);
-
-#if 0
- abp->f_type = MOUNT_AFS;
-#endif
- abp->f_bsize = mp->vfs_bsize;
- abp->f_iosize = mp->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_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
- abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
- if (abp != &mp->mnt_stat) {
- abp->f_type = mp->mnt_vfc->vfc_typenum;
- memcpy((caddr_t) & abp->f_mntonname[0],
- (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
- memcpy((caddr_t) & abp->f_mntfromname[0],
- (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
- }
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct prioc *p;
-{
- return 0;
-}
-
-u_int32_t afs_darwin_realmodes = 0;
-
-int afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen, struct proc *p)
-{
- int error;
-
- switch (name[0]) {
- case AFS_SC_ALL:
- /* nothing defined */
- break;
- case AFS_SC_DARWIN:
- if (namelen < 3)
- return ENOENT;
- switch (name[1]) {
- case AFS_SC_DARWIN_ALL:
- switch (name[2]) {
- case AFS_SC_DARWIN_ALL_REALMODES:
- return sysctl_int(oldp, oldlenp, newp, newlen,
- &afs_darwin_realmodes);
- }
- break;
- /* darwin version specific sysctl's goes here */
- }
- break;
- }
- return EOPNOTSUPP;
-}
-
-typedef (*PFI) ();
-extern int vfs_opv_numops; /* The total number of defined vnode operations */
-extern struct vnodeopv_desc afs_vnodeop_opv_desc;
-int
-afs_init(struct vfsconf *vfc)
-{
- int j;
- int (**opv_desc_vector) ();
- struct vnodeopv_entry_desc *opve_descp;
-
-
-
- MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
- M_WAITOK);
-
- memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
-
- opv_desc_vector = afs_vnodeop_p;
- for (j = 0; afs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
- opve_descp = &(afs_vnodeop_opv_desc.opv_desc_ops[j]);
-
- /*
- * Sanity check: is this operation listed
- * in the list of operations? We check this
- * by seeing if its offest is zero. Since
- * the default routine should always be listed
- * first, it should be the only one with a zero
- * offset. Any other operation with a zero
- * offset is probably not listed in
- * vfs_op_descs, and so is probably an error.
- *
- * A panic here means the layer programmer
- * has committed the all-too common bug
- * of adding a new operation to the layer's
- * list of vnode operations but
- * not adding the operation to the system-wide
- * list of supported operations.
- */
- if (opve_descp->opve_op->vdesc_offset == 0
- && opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
- printf("afs_init: operation %s not listed in %s.\n",
- opve_descp->opve_op->vdesc_name, "vfs_op_descs");
- panic("load_afs: bad operation");
- }
- /*
- * Fill in this entry.
- */
- opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
- opve_descp->opve_impl;
- }
-
- /*
- * Finally, go back and replace unfilled routines
- * with their default. (Sigh, an O(n^3) algorithm. I
- * could make it better, but that'd be work, and n is small.)
- */
-
- /*
- * Force every operations vector to have a default routine.
- */
- opv_desc_vector = afs_vnodeop_p;
- if (opv_desc_vector[VOFFSET(vop_default)] == NULL) {
- panic("afs_init: operation vector without default routine.");
- }
- for (j = 0; j < vfs_opv_numops; j++)
- if (opv_desc_vector[j] == NULL)
- opv_desc_vector[j] = opv_desc_vector[VOFFSET(vop_default)];
-}
-
-struct vfsops afs_vfsops = {
- afs_mount,
- afs_start,
- afs_unmount,
- afs_root,
- afs_quotactl,
- afs_statfs,
- afs_sync,
- afs_vget,
- afs_fhtovp,
- afs_vptofh,
- afs_init,
- afs_sysctl
-};
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vm.c,v 1.11 2003/07/15 23:14:18 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include <sys/ubc.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)
-{
- struct vnode *vp = AFSTOV(avc);
-#ifdef AFS_DARWIN14_ENV
- if (UBCINFOEXISTS(vp))
- return EBUSY;
-#endif
- if (avc->vrefCount)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* if a lock is held, give up */
- if (CheckLock(&avc->lock) || afs_CheckBozonLock(&avc->pvnLock))
- return EBUSY;
-
- AFS_GUNLOCK();
- cache_purge(vp);
-#ifndef AFS_DARWIN14_ENV
- if (UBCINFOEXISTS(vp)) {
- ubc_clean(vp, 1);
- ubc_uncache(vp);
- ubc_release(vp);
- ubc_info_free(vp);
- }
-#endif
-
- AFS_GLOCK();
-
- return 0;
-}
-
-
-/* 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)
-{
- struct vnode *vp = AFSTOV(avc);
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- if (UBCINFOEXISTS(vp)) {
- ubc_pushdirty(vp);
- }
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 94);
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- struct vnode *vp = AFSTOV(avc);
- void *object;
- kern_return_t kret;
- off_t size, lastpg;
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- if (UBCINFOEXISTS(vp)) {
- size = ubc_getsize(vp);
- kret = ubc_invalidate(vp, 0, size);
- if (kret != 1) /* should be KERN_SUCCESS */
- printf("TryToSmush: invalidate failed (error = %d)\n", kret);
- }
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 59);
-}
-
-/* Purge VM for a file when its callback is revoked.
- *
- * Locking: No lock is held, not even the global lock.
- */
-/* XXX this seems to not be referenced anywhere. *somebody* ought to be calling
- this, and also making sure that ubc's idea of the filesize is right more
- often */
-void
-osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
-{
- struct vnode *vp = AFSTOV(avc);
- void *object;
- kern_return_t kret;
- off_t size;
- if (UBCINFOEXISTS(vp)) {
- size = ubc_getsize(vp);
- kret = ubc_invalidate(vp, 0, size);
- if (kret != 1) /* Should be KERN_SUCCESS */
- printf("VMFlushPages: invalidate failed (error = %d)\n", kret);
- /* XXX what about when not CStatd */
- if (avc->states & CStatd && size != avc->m.Length)
- ubc_setsize(vp, avc->m.Length);
- }
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- struct vnode *vp = AFSTOV(avc);
- if (UBCINFOEXISTS(vp)) {
- ubc_setsize(vp, alen);
- }
-}
-
-/* vnreclaim and vinactive are probably not aggressive enough to keep
- enough afs vcaches free, so we try to do some of it ourselves */
-/* XXX there's probably not nearly enough locking here */
-void
-osi_VM_TryReclaim(struct vcache *avc, int *slept)
-{
- struct proc *p = current_proc();
- struct vnode *vp = AFSTOV(avc);
- void *obj;
-
- if (slept)
- *slept = 0;
- VN_HOLD(vp); /* remove from inactive list */
- if (!simple_lock_try(&vp->v_interlock)) {
- AFS_RELE(vp);
- return;
- }
- if (!UBCINFOEXISTS(vp) || vp->v_count != 2) {
- simple_unlock(&vp->v_interlock);
- AFS_RELE(vp);
- return;
- }
-#ifdef AFS_DARWIN14_ENV
- if (vp->v_ubcinfo->ui_refcount > 1 || vp->v_ubcinfo->ui_mapped) {
- simple_unlock(&vp->v_interlock);
- AFS_RELE(vp);
- return;
- }
-#else
- if (vp->v_ubcinfo->ui_holdcnt) {
- simple_unlock(&vp->v_interlock);
- AFS_RELE(vp);
- return;
- }
-#endif
- if (slept && ubc_issetflags(vp, UI_WASMAPPED)) {
- /* We can't possibly release this in time for this NewVCache to get it */
- simple_unlock(&vp->v_interlock);
- AFS_RELE(vp);
- return;
- }
-
- vp->v_usecount--; /* we want the usecount to be 1 */
-
- if (slept) {
- ReleaseWriteLock(&afs_xvcache);
- *slept = 1;
- } else
- ReleaseReadLock(&afs_xvcache);
- AFS_GUNLOCK();
- obj = 0;
- if (ubc_issetflags(vp, UI_WASMAPPED)) {
- simple_unlock(&vp->v_interlock);
-#ifdef AFS_DARWIN14_ENV
- ubc_release_named(vp);
-#else
- ubc_release(vp);
-#endif
- if (ubc_issetflags(vp, UI_HASOBJREF))
- printf("ubc_release didn't release the reference?!\n");
- } else if (!vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, current_proc())) {
-#ifdef AFS_DARWIN14_ENV
- obj = ubc_getobject(vp, UBC_HOLDOBJECT);
-#else
-#ifdef AFS_DARWIN13_ENV
- obj = ubc_getobject(vp, (UBC_NOREACTIVATE | UBC_HOLDOBJECT));
-#else
- obj = ubc_getobject(vp);
-#endif
-#endif
- (void)ubc_clean(vp, 1);
- vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0);
- if (vp->v_usecount == 1)
- VOP_INACTIVE(vp, p);
- else
- VOP_UNLOCK(vp, 0, p);
- if (obj) {
- if (ISSET(vp->v_flag, VTERMINATE))
- panic("afs_vnreclaim: already teminating");
- SET(vp->v_flag, VTERMINATE);
- memory_object_destroy(obj, 0);
- while (ISSET(vp->v_flag, VTERMINATE)) {
- SET(vp->v_flag, VTERMWANT);
- tsleep((caddr_t) & vp->v_ubcinfo, PINOD, "afs_vnreclaim", 0);
- }
- }
- } else {
- if (simple_lock_try(&vp->v_interlock))
- panic("afs_vnreclaim: slept, but did no work :(");
- if (UBCINFOEXISTS(vp) && vp->v_count == 1) {
- vp->v_usecount++;
- simple_unlock(&vp->v_interlock);
- VN_RELE(vp);
- } else
- simple_unlock(&vp->v_interlock);
- }
- AFS_GLOCK();
- if (slept)
- ObtainWriteLock(&afs_xvcache, 175);
- else
- ObtainReadLock(&afs_xvcache);
-}
-
-void
-osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size)
-{
- void *object;
- struct vcache *avc = VTOAFS(vp);
-
-#ifdef AFS_DARWIN14_ENV
- offset = trunc_page(offset);
- size = round_page(size + 1);
- while (size) {
- ubc_page_op(vp, (vm_offset_t) offset,
- UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0, 0);
- size -= PAGE_SIZE;
- offset += PAGE_SIZE;
- }
-#else
- object = NULL;
-#ifdef AFS_DARWIN13_ENV
- if (UBCINFOEXISTS(vp))
- object = ubc_getobject(vp, UBC_NOREACTIVATE);
-#else
- if (UBCINFOEXISTS(vp))
- object = ubc_getobject(vp);
-#endif
- if (!object)
- return;
-
- offset = trunc_page(offset);
- size = round_page(size + 1);
-
-#ifdef AFS_DARWIN13_ENV
- while (size) {
- memory_object_page_op(object, (vm_offset_t) offset,
- UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0,
- 0);
- size -= PAGE_SIZE;
- offset += PAGE_SIZE;
- }
-#else
- /* This is all we can do, and it's not enough. sucks to be us */
- ubc_setsize(vp, offset);
- size = (offset + size > avc->m.Length) ? offset + size : avc->m.Length;
- ubc_setsize(vp, size);
-#endif
-#endif
-}
-
-int
-osi_VM_Setup(struct vcache *avc, int force)
-{
- int error;
- struct vnode *vp = AFSTOV(avc);
-
- if (UBCISVALID(vp) && ((avc->states & CStatd) || force)) {
- if (!UBCINFOEXISTS(vp) && !ISSET(vp->v_flag, VTERMINATE)) {
- osi_vnhold(avc, 0);
- avc->states |= CUBCinit;
- AFS_GUNLOCK();
- if ((error = ubc_info_init(&avc->v))) {
- AFS_GLOCK();
- avc->states &= ~CUBCinit;
- AFS_RELE(avc);
- return error;
- }
-#ifndef AFS_DARWIN14_ENV
- simple_lock(&avc->v.v_interlock);
- if (!ubc_issetflags(&avc->v, UI_HASOBJREF))
-#ifdef AFS_DARWIN13_ENV
- if (ubc_getobject
- (&avc->v, (UBC_NOREACTIVATE | UBC_HOLDOBJECT)))
- panic("VM_Setup: null object");
-#else
- (void)_ubc_getobject(&avc->v, 1); /* return value not used */
-#endif
- simple_unlock(&avc->v.v_interlock);
-#endif
- AFS_GLOCK();
- avc->states &= ~CUBCinit;
- AFS_RELE(avc);
- }
- if (UBCINFOEXISTS(&avc->v))
- ubc_setsize(&avc->v, avc->m.Length);
- }
- return 0;
-}
+++ /dev/null
-/*
- * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
- */
-#include <afsconfig.h>
-#include <afs/param.h>
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DARWIN/osi_vnodeops.c,v 1.16 2004/04/05 06:21:33 shadow Exp $");
-
-#include <afs/sysincludes.h> /* Standard vendor system headers */
-#include <afsincludes.h> /* Afs-based standard headers */
-#include <afs/afs_stats.h> /* statistics */
-#include <sys/malloc.h>
-#include <sys/namei.h>
-#include <sys/ubc.h>
-#if defined(AFS_DARWIN70_ENV)
-#include <vfs/vfs_support.h>
-#endif /* defined(AFS_DARWIN70_ENV) */
-
-int afs_vop_lookup(struct vop_lookup_args *);
-int afs_vop_create(struct vop_create_args *);
-int afs_vop_mknod(struct vop_mknod_args *);
-int afs_vop_open(struct vop_open_args *);
-int afs_vop_close(struct vop_close_args *);
-int afs_vop_access(struct vop_access_args *);
-int afs_vop_getattr(struct vop_getattr_args *);
-int afs_vop_setattr(struct vop_setattr_args *);
-int afs_vop_read(struct vop_read_args *);
-int afs_vop_write(struct vop_write_args *);
-int afs_vop_pagein(struct vop_pagein_args *);
-int afs_vop_pageout(struct vop_pageout_args *);
-int afs_vop_ioctl(struct vop_ioctl_args *);
-int afs_vop_select(struct vop_select_args *);
-int afs_vop_mmap(struct vop_mmap_args *);
-int afs_vop_fsync(struct vop_fsync_args *);
-int afs_vop_seek(struct vop_seek_args *);
-int afs_vop_remove(struct vop_remove_args *);
-int afs_vop_link(struct vop_link_args *);
-int afs_vop_rename(struct vop_rename_args *);
-int afs_vop_mkdir(struct vop_mkdir_args *);
-int afs_vop_rmdir(struct vop_rmdir_args *);
-int afs_vop_symlink(struct vop_symlink_args *);
-int afs_vop_readdir(struct vop_readdir_args *);
-int afs_vop_readlink(struct vop_readlink_args *);
-#if !defined(AFS_DARWIN70_ENV)
-extern int ufs_abortop(struct vop_abortop_args *);
-#endif /* !defined(AFS_DARWIN70_ENV) */
-int afs_vop_inactive(struct vop_inactive_args *);
-int afs_vop_reclaim(struct vop_reclaim_args *);
-int afs_vop_lock(struct vop_lock_args *);
-int afs_vop_unlock(struct vop_unlock_args *);
-int afs_vop_bmap(struct vop_bmap_args *);
-int afs_vop_strategy(struct vop_strategy_args *);
-int afs_vop_print(struct vop_print_args *);
-int afs_vop_islocked(struct vop_islocked_args *);
-int afs_vop_pathconf(struct vop_pathconf_args *);
-int afs_vop_advlock(struct vop_advlock_args *);
-int afs_vop_truncate(struct vop_truncate_args *);
-int afs_vop_update(struct vop_update_args *);
-int afs_vop_blktooff __P((struct vop_blktooff_args *));
-int afs_vop_offtoblk __P((struct vop_offtoblk_args *));
-int afs_vop_cmap __P((struct vop_cmap_args *));
-
-
-#define afs_vop_opnotsupp \
- ((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
-#define afs_vop_valloc afs_vop_opnotsupp
-#define afs_vop_vfree afs_vop_opnotsupp
-#define afs_vop_blkatoff afs_vop_opnotsupp
-#define afs_vop_reallocblks afs_vop_opnotsupp
-
-/* Global vfs data structures for AFS. */
-int (**afs_vnodeop_p) ();
-struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
- {&vop_default_desc, vn_default_error},
- {&vop_lookup_desc, afs_vop_lookup}, /* lookup */
- {&vop_create_desc, afs_vop_create}, /* create */
- {&vop_mknod_desc, afs_vop_mknod}, /* mknod */
- {&vop_open_desc, afs_vop_open}, /* open */
- {&vop_close_desc, afs_vop_close}, /* close */
- {&vop_access_desc, afs_vop_access}, /* access */
- {&vop_getattr_desc, afs_vop_getattr}, /* getattr */
- {&vop_setattr_desc, afs_vop_setattr}, /* setattr */
- {&vop_read_desc, afs_vop_read}, /* read */
- {&vop_write_desc, afs_vop_write}, /* write */
- {&vop_pagein_desc, afs_vop_pagein}, /* read */
- {&vop_pageout_desc, afs_vop_pageout}, /* write */
- {&vop_ioctl_desc, afs_vop_ioctl}, /* XXX ioctl */
- {&vop_select_desc, afs_vop_select}, /* select */
- {&vop_mmap_desc, afs_vop_mmap}, /* mmap */
- {&vop_fsync_desc, afs_vop_fsync}, /* fsync */
- {&vop_seek_desc, afs_vop_seek}, /* seek */
- {&vop_remove_desc, afs_vop_remove}, /* remove */
- {&vop_link_desc, afs_vop_link}, /* link */
- {&vop_rename_desc, afs_vop_rename}, /* rename */
- {&vop_mkdir_desc, afs_vop_mkdir}, /* mkdir */
- {&vop_rmdir_desc, afs_vop_rmdir}, /* rmdir */
- {&vop_symlink_desc, afs_vop_symlink}, /* symlink */
- {&vop_readdir_desc, afs_vop_readdir}, /* readdir */
- {&vop_readlink_desc, afs_vop_readlink}, /* readlink */
-#if defined(AFS_DARWIN70_ENV)
- { &vop_abortop_desc, nop_abortop }, /* abortop */
-#else /* ! defined(AFS_DARWIN70_ENV) */
- /* Yes, we use the ufs_abortop call. It just releases the namei
- * buffer stuff */
- {&vop_abortop_desc, ufs_abortop}, /* abortop */
-#endif /* defined(AFS_DARWIN70_ENV) */
- {&vop_inactive_desc, afs_vop_inactive}, /* inactive */
- {&vop_reclaim_desc, afs_vop_reclaim}, /* reclaim */
- {&vop_lock_desc, afs_vop_lock}, /* lock */
- {&vop_unlock_desc, afs_vop_unlock}, /* unlock */
- {&vop_bmap_desc, afs_vop_bmap}, /* bmap */
- {&vop_strategy_desc, afs_vop_strategy}, /* strategy */
- {&vop_print_desc, afs_vop_print}, /* print */
- {&vop_islocked_desc, afs_vop_islocked}, /* islocked */
- {&vop_pathconf_desc, afs_vop_pathconf}, /* pathconf */
- {&vop_advlock_desc, afs_vop_advlock}, /* advlock */
- {&vop_blkatoff_desc, afs_vop_blkatoff}, /* blkatoff */
- {&vop_valloc_desc, afs_vop_valloc}, /* valloc */
- {&vop_reallocblks_desc, afs_vop_reallocblks}, /* reallocblks */
- {&vop_vfree_desc, afs_vop_vfree}, /* vfree */
- {&vop_truncate_desc, afs_vop_truncate}, /* truncate */
- {&vop_update_desc, afs_vop_update}, /* update */
- {&vop_blktooff_desc, afs_vop_blktooff}, /* blktooff */
- {&vop_offtoblk_desc, afs_vop_offtoblk}, /* offtoblk */
- {&vop_cmap_desc, afs_vop_cmap}, /* cmap */
- {&vop_bwrite_desc, vn_bwrite},
- {(struct vnodeop_desc *)NULL, (int (*)())NULL}
-};
-struct vnodeopv_desc afs_vnodeop_opv_desc =
- { &afs_vnodeop_p, afs_vnodeop_entries };
-
-#define GETNAME() \
- struct componentname *cnp = ap->a_cnp; \
- char *name; \
- MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
- memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
- name[cnp->cn_namelen] = '\0'
-
-#define DROPNAME() FREE(name, M_TEMP)
-
-
-
-int
-afs_vop_lookup(ap)
- struct vop_lookup_args /* {
- * struct vnodeop_desc * a_desc;
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error;
- struct vcache *vcp;
- struct vnode *vp, *dvp;
- register int flags = ap->a_cnp->cn_flags;
- int lockparent; /* 1 => lockparent flag is set */
- int wantparent; /* 1 => wantparent or lockparent flag */
- struct proc *p;
- GETNAME();
- p = cnp->cn_proc;
- lockparent = flags & LOCKPARENT;
- wantparent = flags & (LOCKPARENT | WANTPARENT);
-
- if (ap->a_dvp->v_type != VDIR) {
- *ap->a_vpp = 0;
- DROPNAME();
- return ENOTDIR;
- }
- dvp = ap->a_dvp;
- if (flags & ISDOTDOT)
- VOP_UNLOCK(dvp, 0, p);
- AFS_GLOCK();
- error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- if (flags & ISDOTDOT)
- VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
- && (flags & ISLASTCN) && error == ENOENT)
- error = EJUSTRETURN;
- if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
- cnp->cn_flags |= SAVENAME;
- DROPNAME();
- *ap->a_vpp = 0;
- return (error);
- }
- vp = AFSTOV(vcp); /* always get a node if no error */
- vp->v_vfsp = dvp->v_vfsp;
-
- /* The parent directory comes in locked. We unlock it on return
- * unless the caller wants it left locked.
- * we also always return the vnode locked. */
-
- if (flags & ISDOTDOT) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
- if (lockparent && (flags & ISLASTCN)
- && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
- vput(vp);
- DROPNAME();
- return (error);
- }
- } else if (vp == dvp) {
- /* they're the same; afs_lookup() already ref'ed the leaf.
- * It came in locked, so we don't need to ref OR lock it */
- } else {
- if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp, 0, p); /* done with parent. */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
- }
- *ap->a_vpp = vp;
-
- if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
- || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
- cnp->cn_flags |= SAVENAME;
-
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_create(ap)
- struct vop_create_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- int error = 0;
- struct vcache *vcp;
- register struct vnode *dvp = ap->a_dvp;
- struct proc *p;
- GETNAME();
- p = cnp->cn_proc;
-
- /* vnode layer handles excl/nonexcl */
- AFS_GLOCK();
- error =
- afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
- &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- VOP_ABORTOP(dvp, cnp);
- vput(dvp);
- DROPNAME();
- return (error);
- }
-
- if (vcp) {
- *ap->a_vpp = AFSTOV(vcp);
- (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
- vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
- if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp))
- ubc_info_init(*ap->a_vpp);
- } else
- *ap->a_vpp = 0;
-
- if ((cnp->cn_flags & SAVESTART) == 0)
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- vput(dvp);
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_mknod(ap)
- struct vop_mknod_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
- vput(ap->a_dvp);
- return (ENODEV);
-}
-
-int
-afs_vop_open(ap)
- struct vop_open_args /* {
- * struct vnode *a_vp;
- * int a_mode;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int error;
- struct vnode *vp = ap->a_vp;
- struct vcache *vc = VTOAFS(vp);
-#ifdef AFS_DARWIN14_ENV
- int didhold = 0;
- /*----------------------------------------------------------------
- * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
- * can later be passed to vn_open(), which will skip the call to
- * ubc_hold(), and when the ubcinfo is later added, the ui_refcount
- * will be off. So we compensate by calling ubc_hold() ourselves
- * when ui_refcount is less than 2. If an error occurs in afs_open()
- * we must call ubc_rele(), which is what vn_open() would do if it
- * was able to call ubc_hold() in the first place.
- *----------------------------------------------------------------*/
- if (vp->v_type == VREG && !(vp->v_flag & VSYSTEM)
- && vp->v_ubcinfo->ui_refcount < 2)
- didhold = ubc_hold(vp);
-#endif /* AFS_DARWIN14_ENV */
- AFS_GLOCK();
- error = afs_open(&vc, ap->a_mode, ap->a_cred);
-#ifdef DIAGNOSTIC
- if (AFSTOV(vc) != vp)
- panic("AFS open changed vnode!");
-#endif
- afs_BozonLock(&vc->pvnLock, vc);
- osi_FlushPages(vc, ap->a_cred);
- afs_BozonUnlock(&vc->pvnLock, vc);
- AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
- if (error && didhold)
- ubc_rele(vp);
-#endif /* AFS_DARWIN14_ENV */
- return error;
-}
-
-int
-afs_vop_close(ap)
- struct vop_close_args /* {
- * struct vnode *a_vp;
- * int a_fflag;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- struct vcache *avc = ap->a_vp;
- AFS_GLOCK();
- if (ap->a_cred)
- code = afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p);
- else
- code = afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p);
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
- if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
- ubc_hold(ap->a_vp);
- if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
- printf("afs: Imminent ui_refcount panic\n");
- } else {
- printf("afs: WARNING: ui_refcount panic averted\n");
- }
- }
-#endif
-
- return code;
-}
-
-int
-afs_vop_access(ap)
- struct vop_access_args /* {
- * struct vnode *a_vp;
- * int a_mode;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_getattr(ap)
- struct vop_getattr_args /* {
- * struct vnode *a_vp;
- * struct vattr *a_vap;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_setattr(ap)
- struct vop_setattr_args /* {
- * struct vnode *a_vp;
- * struct vattr *a_vap;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_read(ap)
- struct vop_read_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * int a_ioflag;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- int code;
- struct vcache *avc = VTOAFS(ap->a_vp);
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_pagein(ap)
- struct vop_pagein_args /* {
- * struct vnode *a_vp;
- * upl_t a_pl;
- * vm_offset_t a_pl_offset;
- * off_t a_f_offset;
- * size_t a_size;
- * struct ucred *a_cred;
- * int a_flags;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- upl_t pl = ap->a_pl;
- size_t size = ap->a_size;
- off_t f_offset = ap->a_f_offset;
- vm_offset_t pl_offset = ap->a_pl_offset;
- int flags = ap->a_flags;
- struct ucred *cred;
- vm_offset_t ioaddr;
- struct uio auio;
- struct iovec aiov;
- struct uio *uio = &auio;
- int nocommit = flags & UPL_NOCOMMIT;
-
- int code;
- struct vcache *tvc = VTOAFS(vp);
-
- if (UBCINVALID(vp)) {
-#if DIAGNOSTIC
- panic("afs_vop_pagein: invalid vp");
-#endif /* DIAGNOSTIC */
- return (EPERM);
- }
-
- UBCINFOCHECK("afs_vop_pagein", vp);
- if (pl == (upl_t) NULL) {
- panic("afs_vop_pagein: no upl");
- }
-
- cred = ubc_getcred(vp);
- if (cred == NOCRED)
- cred = ap->a_cred;
-
- if (size == 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- return (0);
- }
- if (f_offset < 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
- }
- if (f_offset & PAGE_MASK)
- panic("afs_vop_pagein: offset not page aligned");
-
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = f_offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_procp = NULL;
- kernel_upl_map(kernel_map, pl, &ioaddr);
- ioaddr += pl_offset;
- auio.uio_resid = aiov.iov_len = size;
- aiov.iov_base = (caddr_t) ioaddr;
- AFS_GLOCK();
- afs_BozonLock(&tvc->pvnLock, tvc);
- osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- code = afs_read(tvc, uio, cred, 0, 0, 0);
- if (code == 0) {
- ObtainWriteLock(&tvc->lock, 2);
- tvc->states |= CMAPPED;
- ReleaseWriteLock(&tvc->lock);
- }
- afs_BozonUnlock(&tvc->pvnLock, tvc);
- AFS_GUNLOCK();
-
- /* Zero out rest of last page if there wasn't enough data in the file */
- if (code == 0 && auio.uio_resid > 0)
- memset(aiov.iov_base, 0, auio.uio_resid);
-
- kernel_upl_unmap(kernel_map, pl);
- if (!nocommit) {
- if (code)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
- else
- kernel_upl_commit_range(pl, pl_offset, size,
- UPL_COMMIT_CLEAR_DIRTY |
- UPL_COMMIT_FREE_ON_EMPTY,
- UPL_GET_INTERNAL_PAGE_LIST(pl),
- MAX_UPL_TRANSFER);
- }
- return code;
-}
-
-int
-afs_vop_write(ap)
- struct vop_write_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * int a_ioflag;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- int code;
- struct vcache *avc = VTOAFS(ap->a_vp);
- void *object;
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- if (UBCINFOEXISTS(ap->a_vp))
- ubc_clean(ap->a_vp, 1);
- if (UBCINFOEXISTS(ap->a_vp))
- osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset,
- ap->a_uio->uio_resid);
- code =
- afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_pageout(ap)
- struct vop_pageout_args /* {
- * struct vnode *a_vp;
- * upl_t a_pl,
- * vm_offset_t a_pl_offset,
- * off_t a_f_offset,
- * size_t a_size,
- * struct ucred *a_cred,
- * int a_flags
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- upl_t pl = ap->a_pl;
- size_t size = ap->a_size;
- off_t f_offset = ap->a_f_offset;
- vm_offset_t pl_offset = ap->a_pl_offset;
- int flags = ap->a_flags;
- struct ucred *cred;
- vm_offset_t ioaddr;
- struct uio auio;
- struct iovec aiov;
- struct uio *uio = &auio;
- int nocommit = flags & UPL_NOCOMMIT;
- int iosize;
-
- int code;
- struct vcache *tvc = VTOAFS(vp);
-
- if (UBCINVALID(vp)) {
-#if DIAGNOSTIC
- panic("afs_vop_pageout: invalid vp");
-#endif /* DIAGNOSTIC */
- return (EPERM);
- }
-
- UBCINFOCHECK("afs_vop_pageout", vp);
- if (pl == (upl_t) NULL) {
- panic("afs_vop_pageout: no upl");
- }
-#if 1
- {
- int lbn, s;
- struct buf *bp;
- int biosize = DEV_BSIZE;
-
- lbn = f_offset / DEV_BSIZE;
-
- for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
-
- s = splbio();
- if (bp = incore(vp, lbn)) {
- if (ISSET(bp->b_flags, B_BUSY))
- panic("nfs_pageout: found BUSY buffer incore\n");
-
- bremfree(bp);
- SET(bp->b_flags, (B_BUSY | B_INVAL));
- brelse(bp);
- }
- splx(s);
- }
- }
-#endif
- cred = ubc_getcred(vp);
- if (cred == NOCRED)
- cred = ap->a_cred;
-
- if (size == 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (0);
- }
- if (flags & (IO_APPEND | IO_SYNC))
- panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
- if (f_offset < 0) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
- }
- if (f_offset >= tvc->m.Length) {
- if (!nocommit)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- return (EINVAL);
- }
-
- if (f_offset & PAGE_MASK)
- panic("afs_vop_pageout: offset not page aligned");
-
- /* size will always be a multiple of PAGE_SIZE */
- /* pageout isn't supposed to extend files */
- if (f_offset + size > tvc->m.Length)
- iosize = tvc->m.Length - f_offset;
- else
- iosize = size;
-
- if (size > (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK && !nocommit) {
- int iosize_rnd=(iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
- kernel_upl_abort_range(pl, pl_offset + iosize_rnd,
- size - iosize_rnd,
- UPL_ABORT_FREE_ON_EMPTY);
- }
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = f_offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_procp = NULL;
- kernel_upl_map(kernel_map, pl, &ioaddr);
- ioaddr += pl_offset;
- auio.uio_resid = aiov.iov_len = iosize;
- aiov.iov_base = (caddr_t) ioaddr;
-#if 1 /* USV [ */
- {
- /*
- * check for partial page and clear the
- * contents past end of the file before
- * releasing it in the VM page cache
- */
- if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
- size_t io = tvc->m.Length - f_offset;
-
- memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
- }
- }
-#endif /* ] USV */
-
- AFS_GLOCK();
- afs_BozonLock(&tvc->pvnLock, tvc);
- osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- ObtainWriteLock(&tvc->lock, 1);
- afs_FakeOpen(tvc);
- ReleaseWriteLock(&tvc->lock);
-
- code = afs_write(tvc, uio, flags, cred, 0);
-
- ObtainWriteLock(&tvc->lock, 1);
- afs_FakeClose(tvc, cred);
- ReleaseWriteLock(&tvc->lock);
- afs_BozonUnlock(&tvc->pvnLock, tvc);
- AFS_GUNLOCK();
- kernel_upl_unmap(kernel_map, pl);
- if (!nocommit) {
- if (code)
- kernel_upl_abort_range(pl, pl_offset, size,
- UPL_ABORT_FREE_ON_EMPTY);
- else
- kernel_upl_commit_range(pl, pl_offset, size,
- UPL_COMMIT_CLEAR_DIRTY |
- UPL_COMMIT_FREE_ON_EMPTY,
- UPL_GET_INTERNAL_PAGE_LIST(pl),
- MAX_UPL_TRANSFER);
- }
-
- return code;
-}
-
-int
-afs_vop_ioctl(ap)
- struct vop_ioctl_args /* {
- * struct vnode *a_vp;
- * int a_command;
- * caddr_t a_data;
- * int a_fflag;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- struct vcache *tvc = VTOAFS(ap->a_vp);
- struct afs_ioctl data;
- int error = 0;
-
- /* in case we ever get in here... */
-
- AFS_STATCNT(afs_ioctl);
- if (((ap->a_command >> 8) & 0xff) == 'V') {
- /* This is a VICEIOCTL call */
- AFS_GLOCK();
- error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
- ap->a_command, ap->a_data);
- AFS_GUNLOCK();
- return (error);
- } else {
- /* No-op call; just return. */
- return (ENOTTY);
- }
-}
-
-/* ARGSUSED */
-int
-afs_vop_select(ap)
- struct vop_select_args /* {
- * struct vnode *a_vp;
- * int a_which;
- * int a_fflags;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- /*
- * We should really check to see if I/O is possible.
- */
- return (1);
-}
-
-/*
- * Mmap a file
- *
- * NB Currently unsupported.
- */
-/* ARGSUSED */
-int
-afs_vop_mmap(ap)
- struct vop_mmap_args /* {
- * struct vnode *a_vp;
- * int a_fflags;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- return (EINVAL);
-}
-
-int
-afs_vop_fsync(ap)
- struct vop_fsync_args /* {
- * struct vnode *a_vp;
- * struct ucred *a_cred;
- * int a_waitfor;
- * struct proc *a_p;
- * } */ *ap;
-{
- int wait = ap->a_waitfor == MNT_WAIT;
- int error;
- register struct vnode *vp = ap->a_vp;
-
- AFS_GLOCK();
- /*vflushbuf(vp, wait); */
- if (ap->a_cred)
- error = afs_fsync(VTOAFS(vp), ap->a_cred);
- else
- error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_seek(ap)
- struct vop_seek_args /* {
- * struct vnode *a_vp;
- * off_t a_oldoff;
- * off_t a_newoff;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- if (ap->a_newoff > ULONG_MAX) /* AFS doesn't support 64-bit offsets */
- return EINVAL;
- return (0);
-}
-
-int
-afs_vop_remove(ap)
- struct vop_remove_args /* {
- * struct vnode *a_dvp;
- * struct vnode *a_vp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
-
- GETNAME();
- AFS_GLOCK();
- error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- cache_purge(vp);
- if (!error && UBCINFOEXISTS(vp)) {
-#ifdef AFS_DARWIN14_ENV
- (void)ubc_uncache(vp);
-#else
- int wasmapped = ubc_issetflags(vp, UI_WASMAPPED);
- int hasobjref = ubc_issetflags(vp, UI_HASOBJREF);
- if (wasmapped)
- (void)ubc_uncache(vp);
- if (hasobjref)
- ubc_release(vp);
- /* WARNING vp may not be valid after this */
-#endif
- }
- if (dvp == vp)
- vrele(vp);
- else
- vput(vp);
- vput(dvp);
-
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_link(ap)
- struct vop_link_args /* {
- * struct vnode *a_vp;
- * struct vnode *a_tdvp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *dvp = ap->a_tdvp;
- register struct vnode *vp = ap->a_vp;
- struct proc *p;
-
- GETNAME();
- p = cnp->cn_proc;
- if (vp->v_type == VDIR) {
- VOP_ABORTOP(vp, cnp);
- error = EISDIR;
- goto out;
- }
- if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
- VOP_ABORTOP(dvp, cnp);
- goto out;
- }
- AFS_GLOCK();
- error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- if (dvp != vp)
- VOP_UNLOCK(vp, 0, p);
- out:
- vput(dvp);
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_rename(ap)
- struct vop_rename_args /* {
- * struct vnode *a_fdvp;
- * struct vnode *a_fvp;
- * struct componentname *a_fcnp;
- * struct vnode *a_tdvp;
- * struct vnode *a_tvp;
- * struct componentname *a_tcnp;
- * } */ *ap;
-{
- int error = 0;
- struct componentname *fcnp = ap->a_fcnp;
- char *fname;
- struct componentname *tcnp = ap->a_tcnp;
- char *tname;
- struct vnode *tvp = ap->a_tvp;
- register struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- register struct vnode *fdvp = ap->a_fdvp;
- struct proc *p = fcnp->cn_proc;
-
- /* Check for cross-device rename.
- * For AFS, this means anything not in AFS-space
- */
- if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
- (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
- error = EXDEV;
- goto abortit;
- }
-
- /*
- * if fvp == tvp, we're just removing one name of a pair of
- * directory entries for the same element. convert call into rename.
- ( (pinched from NetBSD 1.0's ufs_rename())
- */
- if (fvp == tvp) {
- if (fvp->v_type == VDIR) {
- error = EINVAL;
- abortit:
- VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
-
- /* Release destination completely. */
- VOP_ABORTOP(tdvp, tcnp);
- vput(tdvp);
- vput(tvp);
-
- /* Delete source. */
- vrele(fdvp);
- vrele(fvp);
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- if ((fcnp->cn_flags & SAVESTART) == 0)
- panic("afs_rename: lost from startdir");
- fcnp->cn_nameiop = DELETE;
- (void)relookup(fdvp, &fvp, fcnp);
- return (VOP_REMOVE(fdvp, fvp, fcnp));
- }
- if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
- goto abortit;
-
- MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
- memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
- fname[fcnp->cn_namelen] = '\0';
- MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
- memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
- tname[tcnp->cn_namelen] = '\0';
-
-
- AFS_GLOCK();
- /* XXX use "from" or "to" creds? NFS uses "to" creds */
- error =
- afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
- AFS_GUNLOCK();
-
- VOP_UNLOCK(fvp, 0, p);
- FREE(fname, M_TEMP);
- FREE(tname, M_TEMP);
- if (error)
- goto abortit; /* XXX */
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return error;
-}
-
-int
-afs_vop_mkdir(ap)
- struct vop_mkdir_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- int error = 0;
- struct vcache *vcp;
- struct proc *p;
-
- GETNAME();
- p = cnp->cn_proc;
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("afs_vop_mkdir: no name");
-#endif
- AFS_GLOCK();
- error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- VOP_ABORTOP(dvp, cnp);
- vput(dvp);
- DROPNAME();
- return (error);
- }
- if (vcp) {
- *ap->a_vpp = AFSTOV(vcp);
- (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
- vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
- } else
- *ap->a_vpp = 0;
- DROPNAME();
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- vput(dvp);
- return error;
-}
-
-int
-afs_vop_rmdir(ap)
- struct vop_rmdir_args /* {
- * struct vnode *a_dvp;
- * struct vnode *a_vp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
-
- GETNAME();
- if (dvp == vp) {
- vrele(dvp);
- vput(vp);
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- DROPNAME();
- return (EINVAL);
- }
-
- AFS_GLOCK();
- error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- DROPNAME();
- vput(dvp);
- vput(vp);
- return error;
-}
-
-int
-afs_vop_symlink(ap)
- struct vop_symlink_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * char *a_target;
- * } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- int error = 0;
- /* NFS ignores a_vpp; so do we. */
-
- GETNAME();
- AFS_GLOCK();
- error =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
- AFS_GUNLOCK();
- DROPNAME();
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- vput(dvp);
- return error;
-}
-
-int
-afs_vop_readdir(ap)
- struct vop_readdir_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * struct ucred *a_cred;
- * int *a_eofflag;
- * u_long *a_cookies;
- * int ncookies;
- * } */ *ap;
-{
- int error;
- off_t off;
-/* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
- ap->a_ncookies); */
- off = ap->a_uio->uio_offset;
- AFS_GLOCK();
- error =
- afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
- AFS_GUNLOCK();
- if (!error && ap->a_ncookies != NULL) {
- struct uio *uio = ap->a_uio;
- const struct dirent *dp, *dp_start, *dp_end;
- int ncookies;
- u_long *cookies, *cookiep;
-
- if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
- panic("afs_readdir: burned cookies");
- dp = (const struct dirent *)
- ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
-
- dp_end = (const struct dirent *)uio->uio_iov->iov_base;
- for (dp_start = dp, ncookies = 0; dp < dp_end;
- dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
- ncookies++;
-
- MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
- M_WAITOK);
- for (dp = dp_start, cookiep = cookies; dp < dp_end;
- dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
- off += dp->d_reclen;
- *cookiep++ = off;
- }
- *ap->a_cookies = cookies;
- *ap->a_ncookies = ncookies;
- }
-
- return error;
-}
-
-int
-afs_vop_readlink(ap)
- struct vop_readlink_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- int error;
-/* printf("readlink %x\n", ap->a_vp);*/
- AFS_GLOCK();
- error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
- AFS_GUNLOCK();
- return error;
-}
-
-extern int prtactive;
-
-int
-afs_vop_inactive(ap)
- struct vop_inactive_args /* {
- * struct vnode *a_vp;
- * struct proc *a_p;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
-
- if (prtactive && vp->v_usecount != 0)
- vprint("afs_vop_inactive(): pushing active", vp);
-
- AFS_GLOCK();
- afs_InactiveVCache(VTOAFS(vp), 0); /* decrs ref counts */
- AFS_GUNLOCK();
- VOP_UNLOCK(vp, 0, ap->a_p);
- return 0;
-}
-
-int
-afs_vop_reclaim(ap)
- struct vop_reclaim_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- int error;
- int sl;
- register struct vnode *vp = ap->a_vp;
-
- cache_purge(vp); /* just in case... */
-
-#if 0
- AFS_GLOCK();
- error = afs_FlushVCache(VTOAFS(vp), &sl); /* tosses our stuff from vnode */
- AFS_GUNLOCK();
- ubc_unlink(vp);
- if (!error && vp->v_data)
- panic("afs_reclaim: vnode not cleaned");
- return error;
-#else
- if (vp->v_usecount == 2) {
- vprint("reclaim count==2", vp);
- } else if (vp->v_usecount == 1) {
- vprint("reclaim count==1", vp);
- } else
- vprint("reclaim bad count", vp);
-
- return 0;
-#endif
-}
-
-int
-afs_vop_lock(ap)
- struct vop_lock_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vcache *avc = VTOAFS(vp);
-
- if (vp->v_tag == VT_NON)
- return (ENOENT);
- return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
-}
-
-int
-afs_vop_unlock(ap)
- struct vop_unlock_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vcache *avc = VTOAFS(vp);
- return (lockmgr
- (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
- ap->a_p));
-
-}
-
-int
-afs_vop_bmap(ap)
- struct vop_bmap_args /* {
- * struct vnode *a_vp;
- * daddr_t a_bn;
- * struct vnode **a_vpp;
- * daddr_t *a_bnp;
- * int *a_runp;
- * int *a_runb;
- * } */ *ap;
-{
- struct vcache *vcp;
- int error;
- if (ap->a_bnp) {
- *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
- }
- if (ap->a_vpp) {
- *ap->a_vpp = ap->a_vp;
- }
- if (ap->a_runp != NULL)
- *ap->a_runp = 0;
-#ifdef notyet
- if (ap->a_runb != NULL)
- *ap->a_runb = 0;
-#endif
-
- return 0;
-}
-
-int
-afs_vop_strategy(ap)
- struct vop_strategy_args /* {
- * struct buf *a_bp;
- * } */ *ap;
-{
- int error;
- AFS_GLOCK();
- error = afs_ustrategy(ap->a_bp);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_print(ap)
- struct vop_print_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vcache *vc = VTOAFS(ap->a_vp);
- int s = vc->states;
- printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
- vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
- vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
- printf("\n states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
- (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
- (s & CMAPPED) ? " mapped" : "",
- (s & CVFlushed) ? " flush in progress" : "");
- if (UBCISVALID(vp)) {
- printf("\n UBC: ");
- if (UBCINFOEXISTS(vp)) {
- printf("exists, ");
-#ifdef AFS_DARWIN14_ENV
- printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
- ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
- ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
-#else
- printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
-#endif
- } else
- printf("does not exist");
- }
- printf("\n");
- return 0;
-}
-
-int
-afs_vop_islocked(ap)
- struct vop_islocked_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- struct vcache *vc = VTOAFS(ap->a_vp);
- return lockstatus(&vc->rwlock);
-}
-
-/*
- * Return POSIX pathconf information applicable to ufs filesystems.
- */
-afs_vop_pathconf(ap)
- struct vop_pathconf_args /* {
- * struct vnode *a_vp;
- * int a_name;
- * int *a_retval;
- * } */ *ap;
-{
- AFS_STATCNT(afs_cntl);
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *ap->a_retval = NAME_MAX;
- break;
- case _PC_PATH_MAX:
- *ap->a_retval = PATH_MAX;
- break;
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- break;
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- break;
- case _PC_PIPE_BUF:
- return EINVAL;
- break;
-#if defined(AFS_DARWIN70_ENV)
- case _PC_NAME_CHARS_MAX:
- *ap->a_retval = NAME_MAX;
- break;
- case _PC_CASE_SENSITIVE:
- *ap->a_retval = 1;
- break;
- case _PC_CASE_PRESERVING:
- *ap->a_retval = 1;
- break;
-#endif /* defined(AFS_DARWIN70_ENV) */
- default:
- return EINVAL;
- }
- return 0;
-}
-
-/*
- * Advisory record locking support (fcntl() POSIX style)
- */
-int
-afs_vop_advlock(ap)
- struct vop_advlock_args /* {
- * struct vnode *a_vp;
- * caddr_t a_id;
- * int a_op;
- * struct flock *a_fl;
- * int a_flags;
- * } */ *ap;
-{
- int error;
- struct proc *p = current_proc();
- struct ucred cr;
- pcred_readlock(p);
- cr = *p->p_cred->pc_ucred;
- pcred_unlock(p);
- AFS_GLOCK();
- error =
- afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_truncate(ap)
- struct vop_truncate_args /* {
- * struct vnode *a_vp;
- * off_t a_length;
- * int a_flags;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- printf("stray afs_vop_truncate\n");
- return EOPNOTSUPP;
-}
-
-int
-afs_vop_update(ap)
- struct vop_update_args /* {
- * struct vnode *a_vp;
- * struct timeval *a_access;
- * struct timeval *a_modify;
- * int a_waitfor;
- * } */ *ap;
-{
- printf("stray afs_vop_update\n");
- return EOPNOTSUPP;
-}
-
-int
-afs_vop_blktooff(ap)
- struct vop_blktooff_args /* {
- * struct vnode *a_vp;
- * daddr_t a_lblkno;
- * off_t *a_offset;
- * } */ *ap;
-{
- *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
- return 0;
-}
-
-int
-afs_vop_offtoblk(ap)
- struct vop_offtoblk_args /* {
- * struct vnode *a_vp;
- * off_t a_offset;
- * daddr_t *a_lblkno;
- * } */ *ap;
-{
- *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
-
- return (0);
-}
-
-int
-afs_vop_cmap(ap)
- struct vop_cmap_args /* {
- * struct vnode *a_vp;
- * off_t a_foffset;
- * size_t a_size;
- * daddr_t *a_bpn;
- * size_t *a_run;
- * void *a_poff;
- * } */ *ap;
-{
- *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
- *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
- 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
-
-Locking order (in order of locking) --
-
-1. PVN lock in cache entry. Locks out pvn operations on vnode from
-our own layer.
-
-2. VCache entries. Multiple ones can be locked, in which case
-they're locked in order of vnode within the same volume. afs_AccessOK
-is called before locking other entries.
-
-3. VCache entry vlock (Solaris only).
-
-4. DCache entries. Tentatively, multiple ones can be locked now.
-Locking order between dcache entries is in increasing offset order.
-However, if it turns out we never need to lock multiple dcache's,
-we should just say it's not allowed, and simplify things.
-
-5. afs_xdcache. Protects the dcache hash tables and afs_index* in
-afs_dcache.c. As with afs_xvcache below, a newly created dcache
-entries can be locked while holding afs_xdcache.
-
-Bugs: afs_xvcache locked before afs_xdcache in afs_remove, afs_symlink,
-etc in the file afs_vnodeops.c
-
-6. afs_xvcache. Must be able to load new cache entries while holding
-locks on others. Note this means you can't lock a cache entry while
-holding either of this lock, unless, as in afs_create, the cache entry
-is actually created while the afs_xvcache is held.
-
-7. afs_xvcb. Volume callback lock. Locked before afs_xserver in
-afs_RemoveVCB.
-
-8. afs_xvolume -- allows low-level server etc stuff to happen while
-creating a volume?
-
-9. afs_xuser -- afs_xuser is locked before afs_xserver and afs_xconn
-in PUnlog.
-
-10. afs_xcell -- afs_xcell locked before afs_xserver in afs_GetCell.
-
-11. afs_xserver -- locked before afs_xconn in afs_ResetUserConns.
-
-12. afs_xsrvAddr -- afs_xserver locked before afs_xsrvAddr in
-afs_CheckServers.
-
-13. afs_xconn -- see above
-
-14. Individual volume locks. Must be after afs_xvolume so we can
-iterate over all volumes without others being inserted/deleted. Same
-hack doesn't work for cache entry locks since we need to be able to
-lock multiple cache entries (but not multiple volumes) simultaneously.
-
-15. afs_xdnlc -- locked after afs_xvcache in afs_osidnlc.c. Shouldn't
-interact with any of the other locks.
-
-16. afs_xcbhash -- No code which holds xcbhash (all of it is in
-afs_cbqueue.c) (note: this doesn't seem to be true -- it's used
-elsewhere too) attempts to get any other locks, so it should always
-be obtained last. It is locked in afs_DequeueCallbacks which is
-called from afs_FlushVCache with afs_xvcache write-locked.
-
-17. afs_dynrootDirLock -- afs_GetDynroot returns the lock held,
-afs_PutDynroot releases it.
-
-18. Dcache entry mflock -- used to atomize accesses and updates to
-dcache mflags.
-
-19. DCache entry tlock -- used to make atomic reads or writes to
-the dcache refcount.
-
-***** RX_ENABLE_LOCKS
-
-Many fine grained locks are used by Rx on the AIX4.1 platform. These
-need to be explained.
-
-It is likely they could be used preference to the afs_rxglobal_lock on
-AFS_GLOBAL_SUNLOCK platforms.
-
-***** GLOBAL LOCKS
-
-98. afs_global_lock -- This lock provides a non-preemptive environment
-for the bulk of the AFS kernel code on platforms that require it.
-Presently this includes SunOS5 and SGI53 systems. This lock is dropped
-and reaquired frequently, especially around calls back to the OS that
-may reenter AFS such as vn_rele.
-
- Generally, this lock should not be used to explicitly avoid locking
-data structures that need synchronization. However, much existing code
-is deficient in this regard (e.g. afs_getevent).
-
-99. afs_rxglobal_lock -- This lock is obtained after the afs_global_lock
-at process level but is obtained independently during packet arrival
-"interrupts" and during fasttimo processing.
-
-***** OS LOCKS
-
-100. The vnode lock on SunOS and SGI53 protects the its reference count.
-
-101. NETPRI/USERPRI -- These are not really locks but provide mutual
-exclusion against packet and timer interrupts.
+++ /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
-
-AFS file reorganization
-
-Many files in the afs and rx directories were either moved or split up to
-facilitate readability and hence maintenance. As there is no DOC directory
-as yet in RX, it is included here. Also, MakefileProto was split into
-operating system specific MakefileProto.<os> files. The common elements are
-in Makefile.common, which is included by all the MakefileProto.<os>'s.
-In addition, the subdirectory where the objects are compiled and the libraries
-are compiled have been named either "STATIC" or "MODLOAD" depending on the
-type of the client. There are no more separate NFS and no-NFS directories. The
-NFS translator specific object files all have _nfs suffixes, for example,
-afs_call_nfs.o.
-
-RX
-The rx directory now has operating system specific directories. The Unix
-operating systems use these for kernel code only. Each presently has 2 files,
-rx_kmutex.h and rx_knet.c. rx_kmutex.h contains that operating system's
-locking macros for kernel RX that were in the now removed rx_machdep.h.
-rx_knet.c contains the system specific parts from rx_kernel.c. This includes
-a separate rxk_input for each system. In the afs directory, afs_osinet.c was
-also split up. osi_NetSend was moved to these rx_knet.c directories.
-
-RX Summary:
-rx_machdep.h -> rx_lwp.h (user space parts)
- -> <os>/rx_kmutex.h (kernel parts)
-rx_kernel.c -> <os>/rx_knet.c
-osi_NetSend -> <os>/rx_knet.c
-
-AFS
-Files in the afs directory were broken up either because of the messy #ifdef's
-or because of the size of the file, and in particular, the RCS version of
-the file. For example, RCS/afs_vnodeops,v is nearly 10 Meg. Files in the
-operating system specific directories are all prefixed with osi_ (operating
-system interface). Each must have at least an osi_groups.c and an osi_machdep.h
-file. The first implements setgroups/getgroups and the latter implements the
-kernel locking macros for AFS.
-
-
-AFS Summary:
-afs_vnodeops.c -> VNOPS/*.c (one file per class of vnode op)
- afs_osi_pag.c
- afs_osi_uio.c
- <os>/osi_groups.c
-afs_cache.c -> afs_dcache.c and afs_vcache.c afs_segments.c
-afs_resource.c -> afs_analyze.c
- afs_cell.c
- afs_conn.c
- afs_user.c
- afs_server.c
- afs_volume.c
- afs_util.c
- afs_init.c
-
-afs_osinet.c -> rx_knet.c (osi_NetSend)
- afs_osi_alloc.c
- afs_osi_sleep.c
-osi.h -> afs_osi.h
- <os>/osi_machdep.h
-
-Several operating system interface files were moved to their appropritate
-osi directories:
-AIX: afs_aixops.c -> osi_vnodeops.c
- afs_aix_subr.c -> osi_misc.c
- afs_config.c -> osi_config.c osi_timeout.c
- aix_vfs.h -> osi_vfs.h
- misc.s -> osi_assem.s
-
-DUX: afs_vnodeops.c -> osi_vnodeops.c (DUX specific code)
-
-HPUX: afs_vnodeops.c -> osi_vnodeops.c (HPUX specific code)
- afs_hp_debug.c -> osi_debug.c
- hpux_proc_private.h -> osi_proc_private.h
- hpux_vfs.h -> osi_vfs.h
-
-IRIX: afs_sgiops.c -> osi_idbg.c osi_groups.c osi_misc.c osi_vnodeops.c
- sgi_vfs.h -> osi_vfs.h
-
-SOLARIS: afs_sun_subr.c -> osi_vnodeops.c
- osi_prototypes.h (new header file)
-
-afs_mariner.c is centralizes the mariner code, which was plucked from both
-afs_cache.c and afs_vnodeops.c
+++ /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
-
-Here's a quick guide to understanding the AFS 3 VM integration. This
-will help you do AFS 3 ports, since one of the trickiest parts of an
-AFS 3 port is the integration of the virtual memory system with the
-file system.
-
-The issues arise because in AFS, as in any network file system,
-changes may be made from any machine while references are being made
-to a file on your own machine. Data may be cached in your local
-machine's VM system, and when the data changes remotely, the cache
-manager must invalidate the old information in the VM system.
-
-Furthermore, in some systems, there are pages of virtual memory
-containing changes to the files that need to be written back to the
-server at some time. In these systems, it is important not to
-invalidate those pages before the data has made it to the file system.
-In addition, such systems often provide mapped file support, with read
-and write system calls affecting the same shared virtual memory as is
-used by the file should it be mapped.
-
-As you may have guessed from the above, there are two general styles
-of VM integration done in AFS 3: one for systems with limited VM
-system caching, and one for more modern systems where mapped files
-coexist with read and write system calls.
-
-For the older systems, the function osi_FlushText exists. Its goal is
-to invalidate, or try to invalidate, caches where VM pages might cache
-file information that's now obsolete. Even if the invalidation is
-impossible at the time the call is made, things should be setup so
-that the invalidation happens afterwards.
-
-I'm not going to say more about this type of system, since fewer and
-fewer exist, and since I'm low on time. If I get back to this paper
-later, I'll remove this paragraph. The rest of this note talks about
-the more modern mapped file systems.
-
-For mapped file systems, the function osi_FlushPages is called from
-various parts of the AFS cache manager. We assume that this function
-must be called without holding any vnode locks, since it may call back
-to the file system to do part of its work.
-
-The function osi_FlushPages has a relatively complex specification.
-If the file is open for writing, or if the data version of the pages
-that could be in memory (vp->mapDV) is the current data version number
-of the file, then this function has no work to do. The rationale is
-that if the file is open for writing, calling this function could
-destroy data written to the file but not flushed from the VM system to
-the cache file. If mapDV >= DataVersion, then flushing the VM
-system's pages won't change the fact that we can still only have pages
-from data version == mapDV in memory. That's because flushing all
-pages from the VM system results in a post condition that the only
-pages that might be in memory are from the current data version.
-
-If neither of the two conditions above occur, then we actually
-invalidate the pages, on a Sun by calling pvn_vptrunc. This discards
-the pages without writing any dirty pages to the cache file. We then
-set the mapDV field to the highest data version seen before we started
-the call to flush the pages. On systems that release the vnode lock
-while doing the page flush, the file's data version at the end of this
-procedure may be larger than the value we set mapDV to, but that's
-only conservative, since a new could have been created from the
-earlier version of the file.
-
-There are a few times that we must call osi_FlushPages. We should
-call it at the start of a read or open call, so that we raise mapDV to
-the current value, and get rid of any old data that might interfere
-with later reads. Raising mapDV to the current value is also
-important, since if we wrote data with mapDV < DataVersion, then a
-call to osi_FlushPages would discard this data if the pages were
-modified w/o having the file open for writing (e.g. using a mapped
-file). This is why we also call it in afs_map. We call it in
-afs_getattr, since afs_getattr is the only function guaranteed to be
-called between the time another client updates an executable, and the
-time that our own local client tries to exec this executable; if we
-fail to call osi_FlushPages here, we might use some pages from the
-previous version of the executable file.
-
-Also, note that we update mapDV after a store back to the server
-completes, if we're sure that no other versions were created during
-the file's storeback. The mapDV invariant (that no pages from earlier
-data versions exist in memory) remains true, since the only versions
-that existed between the old and new mapDV values all contained the
-same data.
-
-Finally, note a serious incompleteness in this system: we aren't
-really prepared to deal with mapped files correctly. In particular,
-there is no code to ensure that data stored in dirty VM pages ends up
-in a cache file, except as a side effect of the segmap_release call
-(on Sun 4s) that unmaps the data from the kernel map, and which,
-because of the SM_WRITE flag, also calls putpage synchronously to get
-rid of the data.
-
-This problem needs to be fixed for any system that uses mapped files
-seriously. Note that the NeXT port's generic write call uses mapped
-files, but that we've set a flag (close_flush) that ensures that all
-dirty pages get flushed after every write call. It is also something
-of a performance hit, since it would be better to write those pages to
-the cache asynchronously rather than after every write, as happens
-now.
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_file.c,v 1.9 2003/07/15 23:14:18 shadow Exp $");
-
-#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;
-struct AFS_UCRED 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_int32 ainode)
-{
- static struct vnode *tags_vnode = NULL;
- 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();
-
- switch (afs_cacheVfsp->m_stat.f_type) {
- case MOUNT_UFS:
- code =
- igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t) ainode,
- &ip, &dummy);
- 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 = NULL;
- afile->inum = ainode; /* for hint validity checking */
- break;
- case MOUNT_MSFS:{
- char path[1024];
- struct nameidata nd, *ndp = &nd;
- struct utask_nd utnd = { NULL, NULL };
- struct vattr attr;
-
- memset(&nd, 0, sizeof(nd));
- ndp->ni_utnd = &utnd;
- ndp->ni_nameiop = LOOKUP;
- ndp->ni_cred = &afs_osi_cred;
- ndp->ni_segflg = UIO_SYSSPACE;
-
- /* get hold of a vnode for the .tags directory, so we can
- * lookup files relative to it */
- if (tags_vnode == NULL) {
- ndp->ni_cdir = afs_cacheVfsp->m_vnodecovered;
- strcpy(path, afs_cacheVfsp->m_stat.f_mntonname);
- strcat(path, "/.tags");
- ndp->ni_dirp = path;
- if ((code = namei(ndp)))
- osi_Panic("failed to lookup %s (%d)", path, code);
- tags_vnode = ndp->ni_vp;
- }
- sprintf(path, "%d", ainode);
- ndp->ni_dirp = path;
- ndp->ni_cdir = tags_vnode;
- if ((code = namei(ndp)))
- osi_Panic("failed to lookup %s (%d)", path, code);
-
- /* XXX this sucks, chances are we're going to do this again right
- * away, but apparently we can't just set the size to 0 */
- VOP_GETATTR(ndp->ni_vp, &attr, &afs_osi_cred, code);
- if (code)
- osi_Panic("failed to stat %s (%d)", path, code);
-
- afile->vnode = ndp->ni_vp;
- afile->size = attr.va_size;
- afile->offset = 0;
- afile->proc = NULL;
- afile->inum = ainode; /* for hint validity checking */
- break;
- }
- default:
- osi_Panic("UFSOpen called for unknown cache-type (%d)",
- afs_cacheVfsp->m_stat.f_type);
- }
-
- AFS_GLOCK();
- return 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, code);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&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)
-{
- struct AFS_UCRED *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;
- MObtainWriteLock(&afs_xosi, 321);
- VATTR_NULL(&tvattr);
- /* note that this credential swapping stuff is only necessary because
- * of ufs's references directly to u.u_cred instead of to
- * credentials parameter. Probably should fix ufs some day. */
- oldCred = u.u_cred; /* remember old credentials pointer */
- u.u_cred = &afs_osi_cred; /* temporarily use superuser credentials */
- tvattr.va_size = asize;
- AFS_GUNLOCK();
- VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, code);
- AFS_GLOCK();
- u.u_cred = oldCred; /* restore */
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- struct inode *ip;
- assert(avp->v_tag == VT_UFS);
- 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)
-{
- struct AFS_UCRED *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_cred, &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)
-{
- struct AFS_UCRED *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 = u.u_cred;
- u.u_cred = &afs_osi_cred;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, IO_UNIT, &afs_osi_cred,
- &resid);
- AFS_GLOCK();
- u.u_cred = 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)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * Afs_xsetgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_groups.c,v 1.6 2003/07/15 23:14:18 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-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);
- 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(u.u_cred) == 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
- */
-
-/*
- * DUX inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_inode.c,v 1.12 2003/07/15 23:14:18 shadow Exp $");
-
-#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 <ufs/ufsmount.h>
-
-/* given a vnode, return the `inode number'; if it's a UFS vnode just
- return the i_number from the in kernel inode struct, if not stat
- the file to get the inumber from there */
-afs_uint32
-osi_vnodeToInumber(struct vnode *vnode)
-{
- int error;
- struct vattr attr;
-
- /* use faster version with UFS */
- if (vnode->v_tag == VT_UFS)
- return VTOI(vnode)->i_number;
- /* otherwise stat the file */
- VOP_GETATTR(vnode, &attr, NULL, error);
- if (error)
- osi_Panic("VOP_GETATTR = %d", error);
- return attr.va_fileid;
-}
-
-/* return the id of the device containing the file */
-afs_uint32
-osi_vnodeToDev(struct vnode * vnode)
-{
- int error;
- struct vattr attr;
-
- /* use faster version with UFS */
- if (vnode->v_tag == VT_UFS)
- return VTOI(vnode)->i_dev;
- /* otherwise stat the file */
- VOP_GETATTR(vnode, &attr, NULL, error);
- if (error)
- osi_Panic("VOP_GETATTR = %d", error);
- return attr.va_rdev;
-}
-
-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 = rootfs)
- do {
- /*
- * XXX Also do the test for MFS
- */
-#undef m_data
-#undef m_next
- if (mp->m_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();
- }
-#ifdef AFS_DUX50_ENV
-#define m_next m_nxt
-#endif
- mp = mp->m_next;
- } while (mp != rootfs);
- MOUNTLIST_UNLOCK();
- if (!fs)
- return (ENXIO);
- }
- vp = (struct vnode *)fake_vnode;
- fake_inode_init(vp, fs);
- assert(vp->v_tag == VT_UFS);
- 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())
- 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;
-#ifdef AFS_DUX50_ENV
- struct ufile_entry *fe;
-#endif
-
- AFS_STATCNT(afs_syscall_iopen);
-
- if (!afs_suser())
- return (EPERM);
-
- code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
- if (code) {
- return (code);
- }
-#ifdef AFS_DUX50_ENV
- if ((code = falloc(&fp, &fd, &fe)) != 0) {
- iput(ip);
- return (code);
- }
-#else
- if ((code = falloc(&fp, &fd)) != 0) {
- iput(ip);
- return (code);
- }
-#endif
- IN_UNLOCK(ip);
-
- FP_LOCK(fp);
- fp->f_flag = (usrmod - FOPEN) & FMASK;
- fp->f_type = DTYPE_VNODE;
- fp->f_ops = &vnops;
- fp->f_data = (caddr_t) ITOV(ip);
-
- FP_UNLOCK(fp);
-#ifdef AFS_DUX50_ENV
- u_set_fe(fd, fe, fp, &u.u_file_state);
-#else
- U_FD_SET(fd, fp, &u.u_file_state);
-#endif
- *retval = fd;
- 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())
- 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
- */
-
-/*
- * Inode information required for DUX 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 i_vicemagic i_din.di_proplb
-#define i_vicep1 i_din.di_uid
-#define i_vicep2 i_din.di_gid
-#define i_vicep3a i_din.di_bcuid
-#define i_vicep3b i_din.di_bcgid
-#define i_vicep4 i_din.di_spare[0] /* not used */
-
-#define di_vicemagic di_proplb
-#define di_vicep1 di_uid
-#define di_vicep2 di_gid
-#define di_vicep3a di_bcuid
-#define di_vicep3b di_bcgid
-#define di_vicep4 di_spare[0] /* not used */
-
-#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
- */
-
-/*
- * DUX 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 <kern/lock.h>
-#include <kern/sched_prim.h>
-#include <sys/unix_defs.h>
-
-#define getpid() u.u_procp->p_pid
-
-/*
- * Time related macros
- */
-extern struct timeval time;
-#define osi_Time() (time.tv_sec)
-#define afs_hz hz
-
-#define PAGESIZE 8192
-
-#define AFS_UCRED ucred
-#define AFS_PROC struct proc
-
-#define afs_bufferpages bufpages
-
-#define osi_vnhold(avc,r) do { \
- if ((avc)->vrefCount) { VN_HOLD(AFSTOV(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))
-
-#undef afs_suser
-
-#ifdef KERNEL
-extern simple_lock_data_t afs_global_lock;
-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())
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-
-#undef SPLVAR
-#define SPLVAR
-#undef NETPRI
-#define NETPRI
-#undef USERPRI
-#define USERPRI
-#endif /* KERNEL */
-
-#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
- */
-
-/*
- * Implements:
- * afs_suser
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_misc.c,v 1.6 2003/07/15 23:14:19 shadow Exp $");
-
-#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()
-{
- int error;
-
- if ((error = suser(u.u_cred, &u.u_acflag)) == 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_sleep.c,v 1.9 2003/07/15 23:14:19 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-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) u.u_procp;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = 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;
-}
-
-/* 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.
- */
-static int
-osi_TimedSleep(char *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 DUX
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_vfsops.c,v 1.15 2003/07/15 23:14:19 shadow Exp $");
-
-#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->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, u.u_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) {
- struct vnode *vp = AFSTOV(tvp);
- AFS_GUNLOCK();
- VN_HOLD(vp);
- VN_LOCK(vp);
- vp->v_flag |= VROOT; /* No-op on Ultrix 2.2 */
- VN_UNLOCK(vp);
- AFS_GLOCK();
-
- afs_globalVFS = afsp;
- *avpp = vp;
- }
-
- 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 = 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->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(AFSTOV(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,
-#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();
- ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_call = afs3_syscall;
-#ifdef SY_NARG
- ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_info = 6;
-#else
- ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_parallel = 0;
- ((struct sysent *)(&sysent[AFS_SYSCALL]))->sy_narg = 6;
-#endif
-
- ((struct sysent *)(&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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_vm.c,v 1.8 2003/07/15 23:14:19 shadow Exp $");
-
-#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 <values.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)
-{
- if (avc->vrefCount > 1)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* if a lock is held, give up */
- if (CheckLock(&avc->lock) || afs_CheckBozonLock(&avc->pvnLock))
- return EBUSY;
-
- AFS_GUNLOCK();
- ubc_invalidate(AFSTOV(avc)->v_object, 0, 0, B_INVAL);
- AFS_GLOCK();
-
- 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;
-
- 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);
-}
-
-/* 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)
-{
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_ubc_flush_dirty_and_wait(AFSTOV(avc), 0);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 94);
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_ubc_flush_dirty_and_wait(AFSTOV(avc), 0);
- ubc_invalidate(AFSTOV(avc)->v_object, 0, 0, B_INVAL);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 59);
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- ubc_flush_dirty(AFSTOV(avc)->v_object, 0);
- ubc_invalidate(AFSTOV(avc)->v_object, 0, 0, B_INVAL);
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- ubc_invalidate(AFSTOV(avc)->v_object, alen, MAXINT - alen, B_INVAL);
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/DUX/osi_vnodeops.c,v 1.11 2003/07/15 23:14:19 shadow Exp $");
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include <vm/vm_mmap.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();
-int mp_afs_ioctl();
-
-/* 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,
- mp_afs_ioctl, /* 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;
-
-/* 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,
-};
-
-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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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;
- struct AFS_UCRED *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->states);
- if (error) {
- error = EIO;
- } else if ((avc->states & CWired) == 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->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 */
- }
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, cred); /* 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->m.Length; /* write at EOF position */
- if (uio->uio_rw == UIO_WRITE) {
- avc->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->m.Length)
- avc->m.Length = size; /* file grew */
- avc->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->m.Length) {
- tsize = avc->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->states |= CDirty;
- }
-
- if (code) {
- break;
- }
-
- flags = 0;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
-#ifdef AFS_DUX50_ENV
- code =
- ubc_lookup(AFSTOV(avc)->v_object, pageBase, PAGE_SIZE, PAGE_SIZE,
- &page, &flags, NULL);
-#else
- code =
- ubc_lookup(AFSTOV(avc)->v_object, pageBase, PAGE_SIZE, PAGE_SIZE,
- &page, &flags);
-#endif
- 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->m.Length)))) {
- struct vnode *vp = AFSTOV(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 = AFSTOV(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 = ubc_load(page, pageOffset, page_size);
- 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(AFSTOV(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 = AFSTOV(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->states & CDirty)) {
- code = afs_DoPartialWrite(avc, &treq);
- }
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- if (DO_FLUSH || (!newpage && (cnt < 10))) {
- AFS_GUNLOCK();
- ubc_flush_dirty(AFSTOV(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;
-}
-
-int
-mp_afs_ioctl(struct vnode *vp, int com, caddr_t data, int fflag,
- struct ucred *cred, int *retval)
-{
- return ENOSYS;
-}
-
-/*
- * 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 = AFSTOV(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;
- }
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, cred); /* ensure old pages are gone */
- afs_BozonUnlock(&avc->pvnLock, avc);
- ObtainWriteLock(&avc->lock, 166);
- avc->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,
-#ifdef AFS_DUX50_ENV
- policy,
-#else
- mape, addr,
-#endif
- 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;
-#ifdef AFS_DUX50_ENV
- struct vm_policy *policy;
-#else
- vm_map_entry_t mape;
- vm_offset_t addr;
-#endif
- 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();
-
- afs_BozonLock(&avc->pvnLock, avc);
- 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();
-#ifdef AFS_DUX50_ENV
- code =
- ubc_lookup(AFSTOV(avc)->v_object, off, PAGE_SIZE, PAGE_SIZE,
- pagep, &flags, NULL);
-#else
- code =
- ubc_lookup(AFSTOV(avc)->v_object, off, PAGE_SIZE, PAGE_SIZE,
- pagep, &flags);
-#endif
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 168);
- if (code) {
- goto out;
- }
- if (flags & B_NOCACHE) { /* if (page) */
- if ((rw & B_WRITE) && (offset + len >= avc->m.Length)) {
- struct vnode *vp = AFSTOV(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 = AFSTOV(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();
-#ifdef AFS_DUX50_ENV
- ubc_page_dirty(pl[i], 0);
-#else
- ubc_page_dirty(pl[i]);
-#endif
- AFS_GLOCK();
- } else {
- if (protp && (flags & B_DIRTY) == 0) {
- protp[i] = VM_PROT_WRITE;
- }
- }
- }
- out:
- pl[i] = VM_PAGE_NULL;
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- 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 vnode *vp = vop->vu_vp;
- struct vcache *avc = VTOAFS(vp);
- 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 */
- afs_BozonLock(&avc->pvnLock, avc);
- 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 = AFSTOV(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_BozonUnlock(&avc->pvnLock, avc);
- afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_INT32, code,
- ICL_TYPE_INT32, avc->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;
-}
-
-#ifdef AFS_DUX50_ENV
-int
-mp_afs_objtovp(vm_ubc_object_t vop, struct vnode **vp)
-{
- *vp = vop->vu_vp;
- return 0;
-}
-
-int
-mp_afs_setpgstamp(vm_page_t pp, unsigned int tick)
-{
- pp->pg_stamp = tick;
- return 0;
-}
-#endif
-
-
-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 */
-#ifdef AFS_DUX50_ENV
- mp_afs_objtovp, /* get vnode pointer */
- mp_afs_setpgstamp /* set page stamp */
-#endif
-};
-
-
-/*
- * 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);
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_file.c,v 1.13 2004/03/10 23:01:51 rees Exp $");
-
-#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;
-struct AFS_UCRED 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_int32 ainode)
-{
- struct osi_file *afile;
- struct vnode *vp;
- extern int cacheDiskType;
- afs_int32 code;
-
- 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();
-#if defined(AFS_FBSD50_ENV)
- code = VFS_VGET(afs_cacheVfsp, (ino_t) ainode, LK_EXCLUSIVE, &vp);
-#else
- code = VFS_VGET(afs_cacheVfsp, (ino_t) ainode, &vp);
-#endif
- AFS_GLOCK();
- if (code == 0 && vp->v_type == VNON)
- code = ENOENT;
- if (code) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UFSOpen: igetinode failed");
- }
-#if defined(AFS_FBSD50_ENV)
- VOP_UNLOCK(vp, 0, curthread);
-#else
- VOP_UNLOCK(vp, 0, curproc);
-#endif
- afile->vnode = vp;
- afile->size = VTOI(vp)->i_size;
- afile->offset = 0;
- afile->proc = NULL;
- afile->inum = ainode; /* for hint validity checking */
- 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
-#if defined(AFS_FBSD50_ENV)
- vn_lock(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
- code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
- VOP_UNLOCK(afile->vnode, LK_EXCLUSIVE, curthread);
-#else
- code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc);
-#endif
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&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)
-{
- struct vattr tvattr;
- struct vnode *vp;
- register afs_int32 code;
- AFS_STATCNT(osi_Truncate);
-
- MObtainWriteLock(&afs_xosi, 321);
- vp = afile->vnode;
- /*
- * 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.
- */
- AFS_GUNLOCK();
-#if defined(AFS_FBSD50_ENV)
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
- code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread);
-#else
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
- code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc);
-#endif
- if (code != 0 || tvattr.va_size <= asize)
- goto out;
-
- VATTR_NULL(&tvattr);
- tvattr.va_size = asize;
-#if defined(AFS_FBSD50_ENV)
- code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curthread);
-#else
- code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curproc);
-#endif
-
-out:
-#if defined(AFS_FBSD50_ENV)
- VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
-#else
- VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
-#endif
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- struct inode *ip = VTOI(avp);
- ip->i_flag &= ~IN_ACCESS;
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- unsigned int resid;
- register afs_int32 code;
- 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)
-{
- 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;
- {
- 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();
- }
- 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)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-/*
- * osi_groups.c
- *
- * Implements:
- * Afs_xsetgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-#include <sys/param.h>
-#ifdef AFS_FBSD50_ENV
-#include <sys/sysproto.h>
-#endif
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_groups.c,v 1.8 2003/07/15 23:14:19 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-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);
-
-#ifdef AFS_FBSD50_ENV
-/*
- * This does nothing useful yet.
- * In 5.0, creds are associated not with a process, but with a thread.
- * Probably the right thing to do is replace struct proc with struct thread
- * everywhere, including setpag.
- * That will be a tedious undertaking.
- * For now, I'm just passing curproc to AddPag.
- * This is probably wrong and I don't know what the consequences might be.
- */
-
-int
-Afs_xsetgroups(struct thread *td, struct setgroups_args *uap)
-{
- int code = 0;
- struct vrequest treq;
- struct ucred *cr;
-
- cr = crdup(td->td_ucred);
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
-
- code = afs_InitReq(&treq, cr);
- AFS_GUNLOCK();
- crfree(cr);
- if (code)
- return setgroups(td, uap); /* afs has shut down */
-
- code = setgroups(td, uap);
- /* Note that if there is a pag already in the new groups we don't
- * overwrite it with the old pag.
- */
- cr = crdup(td->td_ucred);
-
- if (PagInCred(cr) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- AddPag(curproc, treq.uid, &cr);
- AFS_GUNLOCK();
- }
- }
- crfree(cr);
- return code;
-}
-#else /* FBSD50 */
-int
-Afs_xsetgroups(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
-{
- int code = 0;
- struct vrequest treq;
- struct ucred *cr;
-
- cr = crdup(p->p_cred->pc_ucred);
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
-
- code = afs_InitReq(&treq, cr);
- AFS_GUNLOCK();
- crfree(cr);
- if (code)
- return setgroups(p, args, retval); /* afs has shut down */
-
- 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.
- */
- cr = crdup(p->p_cred->pc_ucred);
-
- if (PagInCred(cr) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- AddPag(p, treq.uid, &cr);
- AFS_GUNLOCK();
- }
- }
- crfree(cr);
- return code;
-}
-#endif
-
-
-int
-setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
- afs_uint32 * newpag, int 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[1], gidset[2]) == NOPAG) {
- /* We will have to shift grouplist to make room for pag */
- if (ngroups + 2 > NGROUPS) {
- return (E2BIG);
- }
- for (j = ngroups - 1; j >= 1; j--) {
- gidset[j + 2] = gidset[j];
- }
- ngroups += 2;
- }
- *newpag = (pagvalue == -1 ? genpag() : pagvalue);
- afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
- 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)
-{
-#ifndef AFS_FBSD50_ENV
- int ngrps;
- int i;
- gid_t *gp;
- struct ucred *oldcr, *cr;
-
- AFS_STATCNT(afs_setgroups);
- /*
- * The real setgroups() call does this, so maybe we should too.
- *
- */
- if (ngroups > NGROUPS)
- return EINVAL;
- cr = *cred;
- cr->cr_ngroups = ngroups;
- gp = cr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- if (change_parent) {
- crhold(cr);
- oldcr = proc->p_pptr->p_cred->pc_ucred;
- proc->p_pptr->p_cred->pc_ucred = cr;
- crfree(oldcr);
- }
- crhold(cr);
- oldcr = proc->p_cred->pc_ucred;
- proc->p_cred->pc_ucred = cr;
- crfree(oldcr);
-#endif
- 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_inode.c,v 1.9 2004/03/10 23:01:51 rees Exp $");
-
-#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/ufs/dinode.h>
-#if defined(AFS_FBSD50_ENV)
-#include <ufs/ufs/extattr.h>
-#endif
-#include <ufs/ufsmount.h>
-
-int
-getinode(fs, dev, inode, ipp, perror)
- struct mount *fs;
- struct inode **ipp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct vnode *vp;
- int code;
-
- *ipp = 0;
- *perror = 0;
- if (!fs) {
- register struct ufsmount *ump;
- register struct mount *mp;
-
-#if defined(AFS_FBSD50_ENV)
- mtx_lock(&mountlist_mtx);
-#else
- simple_lock(&mountlist_slock);
-#endif
- if ((mp = TAILQ_FIRST(&mountlist)) != NULL)
- do {
- /*
- * XXX Also do the test for MFS
- */
-#undef m_data
-#undef m_next
- if (!strcmp(mp->mnt_stat.f_fstypename, MOUNT_UFS)) {
- ump = VFSTOUFS(mp);
- if (ump->um_fs == NULL)
- break;
- if (ump->um_dev == dev) {
- fs = ump->um_mountp;
- }
- }
- mp = TAILQ_NEXT(mp, mnt_list);
- } while (mp != TAILQ_FIRST(&mountlist));
-#if defined(AFS_FBSD50_ENV)
- mtx_unlock(&mountlist_mtx);
-#else
- simple_unlock(&mountlist_slock);
-#endif
- if (!fs)
- return (ENXIO);
- }
-#if defined(AFS_FBSD50_ENV)
- code = VFS_VGET(fs, inode, 0, &vp);
-#else
- code = VFS_VGET(fs, inode, &vp);
-#endif
- if (code != 0) {
- *perror = BAD_IGET;
- return code;
- } else {
- *ipp = VTOI(vp);
- return (0);
- }
-}
-
-int
-igetinode(vfsp, dev, inode, ipp, perror)
- struct inode **ipp;
- struct mount *vfsp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct inode *ip;
- 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 */
- vput(ITOV(ip));
- return (ENOENT);
- }
-
- if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
- vput(ITOV(ip));
- return (ENOENT);
- }
-
- *ipp = ip;
- return (0);
-}
-
-#if 0
-/*
- * 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())
- 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);
-}
-
-
-int
-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())
- 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.
- */
-int
-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())
- 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);
-}
-#else
-int
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
- long *retval;
- long dev, near_inode, param1, param2, param3, param4;
-{
- return EOPNOTSUPP;
-}
-
-int
-afs_syscall_iopen(dev, inode, usrmod, retval)
- long *retval;
- int dev, inode, usrmod;
-{
- return EOPNOTSUPP;
-}
-
-int
-afs_syscall_iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- return EOPNOTSUPP;
-}
-#endif
+++ /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 DUX 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
- */
-
-/*
- *
- * FBSD 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 <sys/time.h>
-#if defined(AFS_FBSD50_ENV)
-#include <sys/mutex.h>
-#endif
-
-extern struct simplelock afs_rxglobal_lock;
-
-/*
- * Time related macros
- */
-#define osi_Time() time_second
-#define afs_hz hz
-
-#define PAGESIZE 8192
-
-#define AFS_UCRED ucred
-#define AFS_PROC struct proc
-
-#define afs_bufferpages bufpages
-#ifndef iodone
-#define iodone biodone
-#endif
-
-#define osi_vnhold(avc,r) vref(AFSTOV(avc))
-#undef vSetVfsp
-#define vSetVfsp(vc, vfsp) AFSTOV(vc)->v_mount = (vfsp)
-#undef vSetType
-#define vSetType(vc, type) AFSTOV(vc)->v_type = (type)
-#undef vType
-#define vType(vc) AFSTOV(vc)->v_type
-
-#undef gop_lookupname
-#define gop_lookupname osi_lookupname
-
-#undef afs_suser
-
-#define afs_strcat(s1, s2) strcat((s1), (s2))
-
-#ifdef KERNEL
-
-#undef afs_osi_Alloc_NoSleep
-#define afs_osi_Alloc_NoSleep(size) osi_fbsd_alloc((size), 0)
-
-#define VN_RELE(vp) vrele(vp)
-#define VN_HOLD(vp) VREF(vp)
-
-#if defined(AFS_FBSD50_ENV)
-#define VT_AFS "afs"
-#define VROOT VV_ROOT
-#define v_flag v_vflag
-#define osi_curcred() (curthread->td_ucred)
-#define afs_suser() (!suser(curthread))
-#define simple_lock(x) mtx_lock(x)
-#define simple_unlock(x) mtx_unlock(x)
-#define gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(cred),(aresid), curthread)
-extern struct mtx afs_global_mtx;
-#define AFS_GLOCK() mtx_lock(&afs_global_mtx)
-#define AFS_GUNLOCK() mtx_unlock(&afs_global_mtx)
-#define ISAFS_GLOCK() (mtx_owned(&afs_global_mtx))
-
-#else /* FBSD50 */
-extern struct lock afs_global_lock;
-
-#define osi_curcred() (curproc->p_cred->pc_ucred)
-#define afs_suser() (!suser(curproc))
-#define getpid() curproc
-#define gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(aresid), curproc)
-extern struct proc *afs_global_owner;
-#define AFS_GLOCK() \
- do { \
- osi_Assert(curproc); \
- lockmgr(&afs_global_lock, LK_EXCLUSIVE, 0, curproc); \
- osi_Assert(afs_global_owner == 0); \
- afs_global_owner = curproc; \
- } while (0)
-#define AFS_GUNLOCK() \
- do { \
- osi_Assert(curproc); \
- osi_Assert(afs_global_owner == curproc); \
- afs_global_owner = 0; \
- lockmgr(&afs_global_lock, LK_RELEASE, 0, curproc); \
- } while(0)
-#define ISAFS_GLOCK() (afs_global_owner == curproc && curproc)
-#endif /* FBSD50 */
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-
-#undef SPLVAR
-#define SPLVAR int splvar
-#undef NETPRI
-#define NETPRI splvar=splnet()
-#undef USERPRI
-#define USERPRI splx(splvar)
-#endif /* KERNEL */
-
-#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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_misc.c,v 1.9 2004/03/10 23:01:51 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include <sys/namei.h>
-
-#ifdef AFS_FBSD50_ENV
-/* serious cheating */
-#undef curproc
-#define curproc curthread
-#endif
-
-int
-osi_lookupname(char *aname, enum uio_seg seg, int followlink,
- struct vnode **dirvpp, struct vnode **vpp)
-{
- struct nameidata n;
- int flags, error, wasowned;
-
-#ifdef AFS_FBSD50_ENV
- wasowned = mtx_owned(&afs_global_mtx);
- if (wasowned)
- mtx_unlock(&afs_global_mtx);
-#endif
-
- flags = 0;
- flags = LOCKLEAF;
- if (followlink)
- flags |= FOLLOW;
- else
- flags |= NOFOLLOW;
- /* if (dirvpp) flags|=WANTPARENT; *//* XXX LOCKPARENT? */
- NDINIT(&n, LOOKUP, flags, seg, aname, curproc);
- if ((error = namei(&n)) != 0) {
-#ifdef AFS_FBSD50_ENV
- if (wasowned)
- mtx_lock(&afs_global_mtx);
-#endif
- return error;
- }
- *vpp = n.ni_vp;
-/*
- if (dirvpp)
- *dirvpp = n.ni_dvp;
-*/
- /* should we do this? */
- VOP_UNLOCK(n.ni_vp, 0, curproc);
- NDFREE(&n, NDF_ONLY_PNBUF);
-#ifdef AFS_FBSD50_ENV
- if (wasowned)
- mtx_lock(&afs_global_mtx);
-#endif
- return 0;
-}
-
-/*
- * does not implement security features of kern_time.c:settime()
- */
-void
-afs_osi_SetTime(osi_timeval_t * atv)
-{
-#ifdef AFS_FBSD50_ENV
- printf("afs attempted to set clock; use \"afsd -nosettime\"\n");
-#else
- struct timespec ts;
- struct timeval tv, delta;
- int s;
-
- AFS_GUNLOCK();
- s = splclock();
- microtime(&tv);
- delta = *atv;
- timevalsub(&delta, &tv);
- ts.tv_sec = atv->tv_sec;
- ts.tv_nsec = atv->tv_usec * 1000;
- set_timecounter(&ts);
- (void)splsoftclock();
- lease_updatetime(delta.tv_sec);
- splx(s);
- resettodr();
- AFS_GLOCK();
-#endif
-}
-
-/*
- * Replace all of the bogus special-purpose memory allocators...
- */
-void *
-osi_fbsd_alloc(size_t size, int dropglobal)
-{
- void *rv;
-#ifdef AFS_FBSD50_ENV
- int wasowned;
-
- if (dropglobal) {
- wasowned = mtx_owned(&afs_global_mtx);
- if (wasowned)
- mtx_unlock(&afs_global_mtx);
- rv = malloc(size, M_AFS, M_WAITOK);
- if (wasowned)
- mtx_lock(&afs_global_mtx);
- } else
-#endif
- rv = malloc(size, M_AFS, M_NOWAIT);
-
- return (rv);
-}
-
-void
-osi_fbsd_free(void *p)
-{
-
- free(p, M_AFS);
-}
-
-void
-osi_AllocMoreSSpace(afs_int32 preallocs)
-{
- ;
-}
-
-void
-osi_FreeLargeSpace(void *p)
-{
- osi_fbsd_free(p);
-}
-
-void
-osi_FreeSmallSpace(void *p)
-{
- osi_fbsd_free(p);
-}
-
-void *
-osi_AllocLargeSpace(size_t size)
-{
- AFS_ASSERT_GLOCK();
- AFS_STATCNT(osi_AllocLargeSpace);
- return (osi_fbsd_alloc(size, 1));
-}
-
-void *
-osi_AllocSmallSpace(size_t size)
-{
- AFS_ASSERT_GLOCK();
- AFS_STATCNT(osi_AllocSmallSpace);
- return (osi_fbsd_alloc(size, 1));
-}
-
-void
-shutdown_osinet(void)
-{
- ;
-}
+++ /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>
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_module.c,v 1.5 2004/03/10 23:01:51 rees Exp $");
-
-#include <afs/sysincludes.h>
-#include <afsincludes.h>
-#include <sys/module.h>
-#include <sys/sysproto.h>
-#include <sys/syscall.h>
-#include <sys/sysent.h>
-
-extern struct vfsops afs_vfsops;
-extern struct vnodeopv_desc afs_vnodeop_opv_desc;
-extern struct mount *afs_globalVFS;
-static struct vfsconf afs_vfsconf;
-
-MALLOC_DEFINE(M_AFS, "afsmisc", "memory used by the AFS filesystem");
-
-extern int afs3_syscall();
-extern int Afs_xsetgroups();
-extern int afs_xioctl();
-
-int
-afs_module_handler(module_t mod, int what, void *arg)
-{
- static sy_call_t *old_handler;
- static int inited = 0;
- int error = 0;
-
- switch (what) {
- case MOD_LOAD:
- if (inited) {
- printf("afs cannot be MOD_LOAD'd more than once\n");
- error = -1;
- break;
- }
- if (sysent[AFS_SYSCALL].sy_call != nosys
- && sysent[AFS_SYSCALL].sy_call != lkmnosys) {
- printf("AFS_SYSCALL in use. aborting\n");
- error = -1;
- break;
- }
- memset(&afs_vfsconf, 0, sizeof(struct vfsconf));
- strcpy(afs_vfsconf.vfc_name, "AFS");
- afs_vfsconf.vfc_vfsops = &afs_vfsops;
- afs_vfsconf.vfc_typenum = -1; /* set by vfs_register */
- afs_vfsconf.vfc_flags = VFCF_NETWORK;
- vfs_register(&afs_vfsconf); /* doesn't fail */
- vfs_add_vnodeops(&afs_vnodeop_opv_desc);
- osi_Init();
-#if 0
- sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
- sysent[SYS_ioctl].sy_call = afs_xioctl;
-#endif
- old_handler = sysent[AFS_SYSCALL].sy_call;
- sysent[AFS_SYSCALL].sy_call = afs3_syscall;
- sysent[AFS_SYSCALL].sy_narg = 5;
- inited = 1;
- break;
- case MOD_UNLOAD:
-#ifndef RXK_LISTENER_ENV
- /* shutdown is incomplete unless RXK_LISTENER_ENV */
- printf("afs: I can't be unloaded yet\n");
- return -1;
-#endif
- if (!inited) {
- error = 0;
- break;
- }
- if (afs_globalVFS) {
- error = -1;
- break;
- }
- if (vfs_unregister(&afs_vfsconf)) {
- error = -1;
- break;
- }
- vfs_rm_vnodeops(&afs_vnodeop_opv_desc);
-#if 0
- sysent[SYS_ioctl].sy_call = ioctl;
- sysent[SYS_setgroups].sy_call = setgroups;
-#endif
- sysent[AFS_SYSCALL].sy_narg = 0;
- sysent[AFS_SYSCALL].sy_call = old_handler;
- break;
- }
-
- return (error);
-}
-
-
-static moduledata_t afs_mod = {
- "afs",
- afs_module_handler,
- &afs_mod
-};
-
-DECLARE_MODULE(afs, afs_mod, SI_SUB_VFS, SI_ORDER_MIDDLE);
+++ /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_prototypes.h
- *
- * Exported support routines.
- */
-#ifndef _OSI_PROTO_H_
-#define _OSI_PROTO_H_
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-
-/* osi_misc.c */
-extern int osi_lookupname(char *aname, enum uio_seg seg, int followlink,
- struct vnode **dirvpp, struct vnode **vpp);
-extern void *osi_fbsd_alloc(size_t size, int dropglobal);
-extern void osi_fbsd_free(void *p);
-
-/* osi_vfsops.c */
-#ifdef AFS_FBSD50_ENV
-extern int afs_statfs(struct mount *mp, struct statfs *abp, struct thread *th);
-#else
-extern int afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p);
-#endif
-
-#endif /* _OSI_PROTO_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
- */
-
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_sleep.c,v 1.11 2004/03/10 23:01:51 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#ifndef AFS_FBSD50_ENV
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-static char waitV;
-#endif
-
-
-void
-afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
-{
- AFS_STATCNT(osi_InitWaitHandle);
-#ifdef AFS_FBSD50_ENV
- cv_init(&achandle->wh_condvar, "afscondvar");
- achandle->wh_inited = 1;
-#else
- achandle->proc = NULL;
-#endif
-}
-
-/* cancel osi_Wait */
-/* XXX
- * I can't tell -- is this supposed to be cv_signal() or cv_waitq_remove()?
- * Or perhaps cv_broadcast()?
- * Assuming cv_signal() is the desired meaning. -GAW
- */
-void
-afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
-{
-#ifndef AFS_FBSD50_ENV
- caddr_t proc;
-#endif
-
- AFS_STATCNT(osi_CancelWait);
-
-#ifdef AFS_FBSD50_ENV
- /* XXX should not be necessary */
- if (!achandle->wh_inited)
- return;
- AFS_ASSERT_GLOCK();
- cv_signal(&achandle->wh_condvar);
-#else
- proc = achandle->proc;
- if (proc == 0)
- return;
- achandle->proc = NULL; /* so dude can figure out he was signalled */
- afs_osi_Wakeup(&waitV);
-#endif
-}
-
-/* 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;
-#ifdef AFS_FBSD50_ENV
- struct timeval tv;
- int ticks;
-#else
- afs_int32 endTime;
-#endif
-
- AFS_STATCNT(osi_Wait);
-#ifdef AFS_FBSD50_ENV
- tv.tv_sec = ams / 1000;
- tv.tv_usec = (ams % 1000) * 1000;
- ticks = tvtohz(&tv);
-
- AFS_ASSERT_GLOCK();
- if (ahandle == NULL) {
- /* This is nasty and evil and rude. */
- code = msleep(&tv, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS),
- "afswait", ticks);
- } else {
- if (!ahandle->wh_inited)
- afs_osi_InitWaitHandle(ahandle); /* XXX should not be needed */
-
- if (aintok)
- code = cv_timedwait_sig(&ahandle->wh_condvar, &afs_global_mtx,
- ticks);
- else
- code = cv_timedwait(&ahandle->wh_condvar, &afs_global_mtx, ticks);
- }
-#else
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) curproc;
- do {
- AFS_ASSERT_GLOCK();
- code = osi_TimedSleep(&waitV, ams, aintok);
- if (code)
- break; /* if something happened, quit now */
- /* if we we're cancelled, quit now */
- if (ahandle && (ahandle->proc == NULL)) {
- /* we've been signalled */
- break;
- }
- } while (osi_Time() < endTime);
-#endif
- return code;
-}
-
-/*
- * All this gluck should probably also be replaced with CVs.
- */
-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();
-#ifdef AFS_FBSD50_ENV
- msleep(event, &afs_global_mtx, PVFS, "afsslp", 0);
-#else
- AFS_GUNLOCK();
- tsleep(event, PVFS, "afs_osi_Sleep", 0);
- AFS_GLOCK();
-#endif
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-#ifndef AFS_FBSD50_ENV
-/* 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.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- int ticks;
- int seq, prio;
-
- ticks = (ams * afs_hz) / 1000;
-
-
- evp = afs_getevent(event);
- seq = evp->seq;
- AFS_GUNLOCK();
- if (aintok)
- prio = PCATCH | PPAUSE;
- else
- prio = PVFS;
- code = tsleep(event, prio, "afs_osi_TimedSleep", ticks);
- AFS_GLOCK();
- if (seq == evp->seq)
- code = EINTR;
- relevent(evp);
- return code;
-}
-#endif /* not AFS_FBSD50_ENV */
-
-int
-afs_osi_Wakeup(void *event)
-{
- int ret = 1;
- struct afs_event *evp;
-
- evp = afs_getevent(event);
- if (evp->refcount > 1) {
- evp->seq++;
- wakeup(event);
- ret = 0;
- }
- relevent(evp);
- return ret;
-}
+++ /dev/null
-#include <afsconfig.h>
-#include <afs/param.h>
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_vfsops.c,v 1.15 2004/03/10 23:01:51 rees Exp $");
-
-#include <afs/sysincludes.h> /* Standard vendor system headers */
-#include <afsincludes.h> /* Afs-based standard headers */
-#include <afs/afs_stats.h> /* statistics */
-#include <sys/malloc.h>
-#include <sys/namei.h>
-#include <sys/conf.h>
-#include <sys/syscall.h>
-
-struct vcache *afs_globalVp = 0;
-struct mount *afs_globalVFS = 0;
-int afs_pbuf_freecnt = -1;
-
-#ifdef AFS_FBSD50_ENV
-#define THREAD_OR_PROC struct thread *p
-#else
-#define THREAD_OR_PROC struct proc *p
-#endif
-
-int
-afs_start(struct mount *mp, int flags, THREAD_OR_PROC)
-{
- afs_pbuf_freecnt = nswbuf / 2 + 1;
- return (0); /* nothing to do. ? */
-}
-
-int
-afs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
- THREAD_OR_PROC)
-{
- /* ndp contains the mounted-from device. Just ignore it.
- * we also don't care about our proc struct. */
- size_t size;
-
- if (mp->mnt_flag & MNT_UPDATE)
- return EINVAL;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_mount);
-
- if (afs_globalVFS) { /* Don't allow remounts. */
- AFS_GUNLOCK();
- return (EBUSY);
- }
-
- afs_globalVFS = mp;
- mp->vfs_bsize = 8192;
- vfs_getnewfsid(mp);
- mp->mnt_stat.f_iosize = 8192;
-
- (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
- memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
- memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
- strcpy(mp->mnt_stat.f_mntfromname, "AFS");
- /* null terminated string "AFS" will fit, just leave it be. */
- strcpy(mp->mnt_stat.f_fstypename, "afs");
- AFS_GUNLOCK();
- (void)afs_statfs(mp, &mp->mnt_stat, p);
- return 0;
-}
-
-int
-afs_unmount(struct mount *mp, int flags, THREAD_OR_PROC)
-{
-
- /*
- * Release any remaining vnodes on this mount point.
- * The `1' means that we hold one extra reference on
- * the root vnode (this is just a guess right now).
- * This has to be done outside the global lock.
- */
- vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
- afs_globalVFS = 0;
- afs_shutdown();
- AFS_GUNLOCK();
-
- return 0;
-}
-
-int
-afs_root(struct mount *mp, struct vnode **vpp)
-{
- int error;
- struct vrequest treq;
- register struct vcache *tvp = 0;
-#ifdef AFS_FBSD50_ENV
- struct thread *td = curthread;
- struct ucred *cr = td->td_ucred;
-#else
- struct proc *p = curproc;
- struct ucred *cr = p->p_cred->pc_ucred;
-#endif
-
- AFS_GLOCK();
- AFS_STATCNT(afs_root);
- crhold(cr);
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- error = 0;
- } else {
-tryagain:
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- /* vrele() needed here or not? */
- afs_globalVp = NULL;
- }
-
- if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
- tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
- /* we really want this to stay around */
- if (tvp)
- afs_globalVp = tvp;
- else
- error = ENOENT;
- }
- }
- if (tvp) {
- struct vnode *vp = AFSTOV(tvp);
-
-#ifdef AFS_FBSD50_ENV
- ASSERT_VI_UNLOCKED(vp, "afs_root");
-#endif
- AFS_GUNLOCK();
- /*
- * I'm uncomfortable about this. Shouldn't this happen at a
- * higher level, and shouldn't we busy the top-level directory
- * to prevent recycling?
- */
-#ifdef AFS_FBSD50_ENV
- error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
- vp->v_vflag |= VV_ROOT;
-#else
- error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p);
- vp->v_flag |= VROOT;
-#endif
- AFS_GLOCK();
- if (error != 0)
- goto tryagain;
-
- afs_globalVFS = mp;
- *vpp = vp;
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
- ICL_TYPE_INT32, error);
- AFS_GUNLOCK();
- crfree(cr);
- return error;
-}
-
-int
-afs_statfs(struct mount *mp, struct statfs *abp, THREAD_OR_PROC)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_statfs);
-
- abp->f_bsize = mp->vfs_bsize;
- abp->f_iosize = mp->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_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
- abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
- if (abp != &mp->mnt_stat) {
- abp->f_type = mp->mnt_vfc->vfc_typenum;
- memcpy((caddr_t) & abp->f_mntonname[0],
- (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
- memcpy((caddr_t) & abp->f_mntfromname[0],
- (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
- }
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_sync(struct mount *mp, int waitfor, struct ucred *cred, THREAD_OR_PROC)
-{
- return 0;
-}
-
-int
-afs_init(struct vfsconf *vfc)
-{
- return 0;
-}
-
-struct vfsops afs_vfsops = {
- afs_mount,
- afs_start,
- afs_unmount,
- afs_root,
- vfs_stdquotactl,
- afs_statfs,
- afs_sync,
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- afs_init,
- vfs_stduninit,
- vfs_stdextattrctl,
-#ifdef AFS_FBSD50_ENV
- NULL,
-#endif
-};
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_vm.c,v 1.11 2004/03/10 23:01:51 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include <vm/vm_object.h>
-#include <vm/vm_map.h>
-#include <limits.h>
-#include <float.h>
-
-/*
- * FreeBSD implementation notes:
- * Most of these operations require us to frob vm_objects. Most
- * functions require that the object be locked (with VM_OBJECT_LOCK)
- * on entry and leave it locked on exit. In order to get the
- * vm_object itself we call VOP_GETVOBJECT on the vnode; the
- * locking protocol requires that we do so with the heavy vnode lock
- * held and the vnode interlock unlocked, and it returns the same
- * way.
- *
- * The locking protocol for vnodes is defined in
- * kern/vnode_if.src and sys/vnode.h; the locking is still a work in
- * progress, so some fields are (as of 5.1) still protected by Giant
- * rather than an explicit lock.
- */
-
-#ifdef AFS_FBSD50_ENV
-#define lock_vnode(v) vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curthread)
-#define unlock_vnode(v) VOP_UNLOCK((v), 0, curthread)
-#else
-#define lock_vnode(v) vn_lock((v), LK_EXCLUSIVE | LK_RETRY, curproc)
-#define unlock_vnode(v) VOP_UNLOCK((v), 0, curproc)
-/* need splvm() protection? */
-#define VM_OBJECT_LOCK(o)
-#define VM_OBJECT_UNLOCK(o)
-#endif
-
-/* 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.
- * XXX - should FreeBSD have done this, too? Certainly looks like it.
- * Maybe better to just call vnode_pager_setsize()?
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- struct vm_object *obj;
- struct vnode *vp;
- if (VREFCOUNT(avc) > 1)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* if a lock is held, give up */
- if (CheckLock(&avc->lock) || afs_CheckBozonLock(&avc->pvnLock))
- return EBUSY;
-
- AFS_GUNLOCK();
- vp = AFSTOV(avc);
- lock_vnode(vp);
- if (VOP_GETVOBJECT(vp, &obj) == 0) {
- VM_OBJECT_LOCK(obj);
- vm_object_page_remove(obj, 0, 0, FALSE);
-#if 0
- if (obj->ref_count == 0) {
- vgonel(vp, curproc);
- simple_lock(&vp->v_interlock);
- vp->v_tag = VT_AFS;
- SetAfsVnode(vp);
- }
-#endif
- VM_OBJECT_UNLOCK(obj);
- }
- unlock_vnode(vp);
- AFS_GLOCK();
-
- return 0;
-}
-
-/* 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)
-{
- struct vnode *vp;
- struct vm_object *obj;
- int anyio, tries;
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- tries = 5;
- vp = AFSTOV(avc);
-
- /*
- * I don't understand this. Why not just call vm_object_page_clean()
- * and be done with it? I particularly don't understand why we're calling
- * vget() here. Is there some reason to believe that the vnode might
- * be being recycled at this point? I don't think there's any need for
- * this loop, either -- if we keep the vnode locked all the time,
- * that and the object lock will prevent any new pages from appearing.
- * The loop is what causes the race condition. -GAW
- */
- do {
- anyio = 0;
- lock_vnode(vp);
- if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
- /* XXX - obj locking? */
- unlock_vnode(vp);
-#ifdef AFS_FBSD50_ENV
- if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
-#else
- if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
-#endif
- if (VOP_GETVOBJECT(vp, &obj) == 0) {
- VM_OBJECT_LOCK(obj);
- vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
- VM_OBJECT_UNLOCK(obj);
- anyio = 1;
- }
- vput(vp);
- }
- } else
- unlock_vnode(vp);
- } while (anyio && (--tries > 0));
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 94);
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- struct vnode *vp;
- struct vm_object *obj;
- int anyio, tries;
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- tries = 5;
- vp = AFSTOV(avc);
- do {
- anyio = 0;
- lock_vnode(vp);
- /* See the comments above. */
- if (VOP_GETVOBJECT(vp, &obj) == 0 && (obj->flags & OBJ_MIGHTBEDIRTY)) {
- /* XXX - obj locking */
- unlock_vnode(vp);
-#ifdef AFS_FBSD50_ENV
- if (!vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread)) {
-#else
- if (!vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
-#endif
- if (VOP_GETVOBJECT(vp, &obj) == 0) {
- VM_OBJECT_LOCK(obj);
- /*
- * Do we really want OBJPC_SYNC? OBJPC_INVAL would be
- * faster, if invalidation is really what we are being
- * asked to do. (It would make more sense, too, since
- * otherwise this function is practically identical to
- * osi_VM_StoreAllSegments().) -GAW
- */
- vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
- VM_OBJECT_UNLOCK(obj);
- anyio = 1;
- }
- vput(vp);
- }
- } else
- unlock_vnode(vp);
- } while (anyio && (--tries > 0));
- lock_vnode(vp);
- if (VOP_GETVOBJECT(vp, &obj) == 0) {
- VM_OBJECT_LOCK(obj);
- vm_object_page_remove(obj, 0, 0, FALSE);
- VM_OBJECT_UNLOCK(obj);
- }
- unlock_vnode(vp);
- /*vinvalbuf(AFSTOV(avc),0, NOCRED, curproc, 0,0); */
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 59);
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- struct vnode *vp;
- struct vm_object *obj;
-
- vp = AFSTOV(avc);
- ASSERT_VOP_LOCKED(vp, __func__);
- if (VOP_GETVOBJECT(vp, &obj) == 0) {
- VM_OBJECT_LOCK(obj);
- vm_object_page_remove(obj, 0, 0, FALSE);
- VM_OBJECT_UNLOCK(obj);
- }
- /*vinvalbuf(AFSTOV(avc),0, NOCRED, curproc, 0,0); */
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- vnode_pager_setsize(AFSTOV(avc), alen);
-}
+++ /dev/null
-/*
- * A large chunk of this file appears to be copied directly from
- * sys/nfsclient/nfs_bio.c, which has the following license:
- */
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Rick Macklem at The University of Guelph.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- */
-/*
- * Pursuant to a statement of U.C. Berkeley dated 1999-07-22, this license
- * is amended to drop clause (3) above.
- */
-
-#include <afsconfig.h>
-#include <afs/param.h>
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/FBSD/osi_vnodeops.c,v 1.18 2004/03/19 15:37:10 rees Exp $");
-
-#include <afs/sysincludes.h> /* Standard vendor system headers */
-#include <afsincludes.h> /* Afs-based standard headers */
-#include <afs/afs_stats.h> /* statistics */
-#include <sys/malloc.h>
-#include <sys/namei.h>
-#include <sys/unistd.h>
-#ifndef AFS_FBSD50_ENV
-#include <vm/vm_zone.h>
-#endif
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-#include <vm/vm_pager.h>
-#include <vm/vnode_pager.h>
-extern int afs_pbuf_freecnt;
-
-int afs_vop_lookup(struct vop_lookup_args *);
-int afs_vop_create(struct vop_create_args *);
-int afs_vop_mknod(struct vop_mknod_args *);
-int afs_vop_open(struct vop_open_args *);
-int afs_vop_close(struct vop_close_args *);
-int afs_vop_access(struct vop_access_args *);
-int afs_vop_getattr(struct vop_getattr_args *);
-int afs_vop_setattr(struct vop_setattr_args *);
-int afs_vop_read(struct vop_read_args *);
-int afs_vop_write(struct vop_write_args *);
-int afs_vop_getpages(struct vop_getpages_args *);
-int afs_vop_putpages(struct vop_putpages_args *);
-int afs_vop_ioctl(struct vop_ioctl_args *);
-static int afs_vop_pathconf(struct vop_pathconf_args *);
-int afs_vop_poll(struct vop_poll_args *);
-#ifndef AFS_FBSD50_ENV
-int afs_vop_mmap(struct vop_mmap_args *);
-#endif
-int afs_vop_fsync(struct vop_fsync_args *);
-int afs_vop_remove(struct vop_remove_args *);
-int afs_vop_link(struct vop_link_args *);
-int afs_vop_rename(struct vop_rename_args *);
-int afs_vop_mkdir(struct vop_mkdir_args *);
-int afs_vop_rmdir(struct vop_rmdir_args *);
-int afs_vop_symlink(struct vop_symlink_args *);
-int afs_vop_readdir(struct vop_readdir_args *);
-int afs_vop_readlink(struct vop_readlink_args *);
-int afs_vop_inactive(struct vop_inactive_args *);
-int afs_vop_reclaim(struct vop_reclaim_args *);
-int afs_vop_lock(struct vop_lock_args *);
-int afs_vop_unlock(struct vop_unlock_args *);
-int afs_vop_bmap(struct vop_bmap_args *);
-int afs_vop_strategy(struct vop_strategy_args *);
-int afs_vop_print(struct vop_print_args *);
-int afs_vop_islocked(struct vop_islocked_args *);
-int afs_vop_advlock(struct vop_advlock_args *);
-
-
-
-/* Global vfs data structures for AFS. */
-vop_t **afs_vnodeop_p;
-struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
- {&vop_default_desc, (vop_t *) vop_defaultop},
- {&vop_access_desc, (vop_t *) afs_vop_access}, /* access */
- {&vop_advlock_desc, (vop_t *) afs_vop_advlock}, /* advlock */
- {&vop_bmap_desc, (vop_t *) afs_vop_bmap}, /* bmap */
-#ifndef AFS_FBSD50_ENV
- {&vop_bwrite_desc, (vop_t *) vop_stdbwrite},
-#endif
- {&vop_close_desc, (vop_t *) afs_vop_close}, /* close */
- {&vop_createvobject_desc, (vop_t *) vop_stdcreatevobject},
- {&vop_destroyvobject_desc, (vop_t *) vop_stddestroyvobject},
- {&vop_create_desc, (vop_t *) afs_vop_create}, /* create */
- {&vop_fsync_desc, (vop_t *) afs_vop_fsync}, /* fsync */
- {&vop_getattr_desc, (vop_t *) afs_vop_getattr}, /* getattr */
- {&vop_getpages_desc, (vop_t *) afs_vop_getpages}, /* read */
- {&vop_getvobject_desc, (vop_t *) vop_stdgetvobject},
- {&vop_putpages_desc, (vop_t *) afs_vop_putpages}, /* write */
- {&vop_inactive_desc, (vop_t *) afs_vop_inactive}, /* inactive */
- {&vop_lease_desc, (vop_t *) vop_null},
- {&vop_link_desc, (vop_t *) afs_vop_link}, /* link */
- {&vop_lookup_desc, (vop_t *) afs_vop_lookup}, /* lookup */
- {&vop_mkdir_desc, (vop_t *) afs_vop_mkdir}, /* mkdir */
- {&vop_mknod_desc, (vop_t *) afs_vop_mknod}, /* mknod */
-#ifndef AFS_FBSD50_ENV
- {&vop_mmap_desc, (vop_t *) afs_vop_mmap}, /* mmap */
-#endif
- {&vop_open_desc, (vop_t *) afs_vop_open}, /* open */
- {&vop_pathconf_desc, (vop_t *) afs_vop_pathconf}, /* pathconf */
- {&vop_poll_desc, (vop_t *) afs_vop_poll}, /* select */
- {&vop_print_desc, (vop_t *) afs_vop_print}, /* print */
- {&vop_read_desc, (vop_t *) afs_vop_read}, /* read */
- {&vop_readdir_desc, (vop_t *) afs_vop_readdir}, /* readdir */
- {&vop_readlink_desc, (vop_t *) afs_vop_readlink}, /* readlink */
- {&vop_reclaim_desc, (vop_t *) afs_vop_reclaim}, /* reclaim */
- {&vop_remove_desc, (vop_t *) afs_vop_remove}, /* remove */
- {&vop_rename_desc, (vop_t *) afs_vop_rename}, /* rename */
- {&vop_rmdir_desc, (vop_t *) afs_vop_rmdir}, /* rmdir */
- {&vop_setattr_desc, (vop_t *) afs_vop_setattr}, /* setattr */
- {&vop_strategy_desc, (vop_t *) afs_vop_strategy}, /* strategy */
- {&vop_symlink_desc, (vop_t *) afs_vop_symlink}, /* symlink */
- {&vop_write_desc, (vop_t *) afs_vop_write}, /* write */
- {&vop_ioctl_desc, (vop_t *) afs_vop_ioctl}, /* XXX ioctl */
- /*{ &vop_seek_desc, afs_vop_seek }, *//* seek */
- {NULL, NULL}
-};
-struct vnodeopv_desc afs_vnodeop_opv_desc =
- { &afs_vnodeop_p, afs_vnodeop_entries };
-
-#define GETNAME() \
- struct componentname *cnp = ap->a_cnp; \
- char *name; \
- MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
- memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
- name[cnp->cn_namelen] = '\0'
-
-#define DROPNAME() FREE(name, M_TEMP)
-
-/* This is a bit of a cheat... */
-#ifdef AFS_FBSD50_ENV
-#define a_p a_td
-#endif
-
-/*
- * Mosty copied from sys/ufs/ufs/ufs_vnops.c:ufs_pathconf().
- * We should know the correct answers to these questions with
- * respect to the AFS protocol (which may differ from the UFS
- * values) but for the moment this will do.
- */
-static int
-afs_vop_pathconf(struct vop_pathconf_args *ap)
-{
- int error;
-
- error = 0;
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *ap->a_retval = NAME_MAX;
- break;
- case _PC_PATH_MAX:
- *ap->a_retval = PATH_MAX;
- break;
- case _PC_PIPE_BUF:
- *ap->a_retval = PIPE_BUF;
- break;
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- break;
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- break;
-#ifdef _PC_ACL_EXTENDED
- case _PC_ACL_EXTENDED:
- *ap->a_retval = 0;
- break;
- case _PC_ACL_PATH_MAX:
- *ap->a_retval = 3;
- break;
-#endif
-#ifdef _PC_MAC_PRESENT
- case _PC_MAC_PRESENT:
- *ap->a_retval = 0;
- break;
-#endif
-#ifdef _PC_ASYNC_IO
- case _PC_ASYNC_IO:
- /* _PC_ASYNC_IO should have been handled by upper layers. */
- KASSERT(0, ("_PC_ASYNC_IO should not get here"));
- error = EINVAL;
- break;
- case _PC_PRIO_IO:
- *ap->a_retval = 0;
- break;
- case _PC_SYNC_IO:
- *ap->a_retval = 0;
- break;
-#endif
-#ifdef _PC_ALLOC_SIZE_MIN
- case _PC_ALLOC_SIZE_MIN:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
- break;
-#endif
-#ifdef _PC_FILESIZEBITS
- case _PC_FILESIZEBITS:
- *ap->a_retval = 32; /* XXX */
- break;
-#endif
-#ifdef _PC_REC_INCR_XFER_SIZE
- case _PC_REC_INCR_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- case _PC_REC_MAX_XFER_SIZE:
- *ap->a_retval = -1; /* means ``unlimited'' */
- break;
- case _PC_REC_MIN_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- case _PC_REC_XFER_ALIGN:
- *ap->a_retval = PAGE_SIZE;
- break;
-#endif
-#ifdef _PC_SYMLINK_MAX
- case _PC_SYMLINK_MAX:
- *ap->a_retval = MAXPATHLEN;
- break;
-#endif
- default:
- error = EINVAL;
- break;
- }
- return (error);
-}
-
-int
-afs_vop_lookup(ap)
- struct vop_lookup_args /* {
- * struct vnodeop_desc * a_desc;
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error;
- struct vcache *vcp;
- struct vnode *vp, *dvp;
- register int flags = ap->a_cnp->cn_flags;
- int lockparent; /* 1 => lockparent flag is set */
- int wantparent; /* 1 => wantparent or lockparent flag */
-#ifdef AFS_FBSD50_ENV
- struct thread *p = ap->a_cnp->cn_thread;
-#else
- struct proc *p = ap->a_cnp->cn_proc;
-#endif
- GETNAME();
-
- lockparent = flags & LOCKPARENT;
- wantparent = flags & (LOCKPARENT | WANTPARENT);
-
- if (ap->a_dvp->v_type != VDIR) {
- *ap->a_vpp = 0;
- DROPNAME();
- return ENOTDIR;
- }
- dvp = ap->a_dvp;
- if (flags & ISDOTDOT)
- VOP_UNLOCK(dvp, 0, p);
- AFS_GLOCK();
- error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- if (flags & ISDOTDOT)
- VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
- && (flags & ISLASTCN) && error == ENOENT)
- error = EJUSTRETURN;
- if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
- cnp->cn_flags |= SAVENAME;
- DROPNAME();
- *ap->a_vpp = 0;
- return (error);
- }
- vp = AFSTOV(vcp); /* always get a node if no error */
-
- /* The parent directory comes in locked. We unlock it on return
- * unless the caller wants it left locked.
- * we also always return the vnode locked. */
-
- if (flags & ISDOTDOT) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
- if (lockparent && (flags & ISLASTCN)
- && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
- vput(vp);
- DROPNAME();
- return (error);
- }
- } else if (vp == dvp) {
- /* they're the same; afs_lookup() already ref'ed the leaf.
- * It came in locked, so we don't need to ref OR lock it */
- } else {
- if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp, 0, p); /* done with parent. */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- /* always return the child locked */
- }
- *ap->a_vpp = vp;
-
- if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN))
- || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)))
- cnp->cn_flags |= SAVENAME;
-
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_create(ap)
- struct vop_create_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- int error = 0;
- struct vcache *vcp;
- register struct vnode *dvp = ap->a_dvp;
-#ifdef AFS_FBSD50_ENV
- struct thread *p = ap->a_cnp->cn_thread;
-#else
- struct proc *p = ap->a_cnp->cn_proc;
-#endif
- GETNAME();
-
- AFS_GLOCK();
- error =
- afs_create(VTOAFS(dvp), name, ap->a_vap,
- ap->a_vap->va_vaflags & VA_EXCLUSIVE ? EXCL : NONEXCL,
- ap->a_vap->va_mode, &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- DROPNAME();
- return (error);
- }
-
- if (vcp) {
- *ap->a_vpp = AFSTOV(vcp);
- vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
- } else
- *ap->a_vpp = 0;
-
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_mknod(ap)
- struct vop_mknod_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- return (ENODEV);
-}
-
-#if 0
-static int
-validate_vops(struct vnode *vp, int after)
-{
- int ret = 0;
- struct vnodeopv_entry_desc *this;
- for (this = afs_vnodeop_entries; this->opve_op; this++) {
- if (vp->v_op[this->opve_op->vdesc_offset] != this->opve_impl) {
- if (!ret) {
- printf("v_op %d ", after);
- vprint("check", vp);
- }
- ret = 1;
- printf("For oper %d (%s), func is %p, not %p",
- this->opve_op->vdesc_offset, this->opve_op->vdesc_name,
- vp->v_op[this->opve_op->vdesc_offset], this->opve_impl);
- }
- }
- return ret;
-}
-#endif
-int
-afs_vop_open(ap)
- struct vop_open_args /* {
- * struct vnode *a_vp;
- * int a_mode;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int error;
- int bad;
- struct vcache *vc = VTOAFS(ap->a_vp);
- bad = 0;
- AFS_GLOCK();
- error = afs_open(&vc, ap->a_mode, ap->a_cred);
-#ifdef DIAGNOSTIC
- if (AFSTOV(vc) != ap->a_vp)
- panic("AFS open changed vnode!");
-#endif
- afs_BozonLock(&vc->pvnLock, vc);
- osi_FlushPages(vc, ap->a_cred);
- afs_BozonUnlock(&vc->pvnLock, vc);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_close(ap)
- struct vop_close_args /* {
- * struct vnode *a_vp;
- * int a_fflag;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- struct vcache *avc = VTOAFS(ap->a_vp);
- AFS_GLOCK();
- if (ap->a_cred)
- code = afs_close(avc, ap->a_fflag, ap->a_cred);
- else
- code = afs_close(avc, ap->a_fflag, afs_osi_credp);
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_access(ap)
- struct vop_access_args /* {
- * struct vnode *a_vp;
- * int a_mode;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_getattr(ap)
- struct vop_getattr_args /* {
- * struct vnode *a_vp;
- * struct vattr *a_vap;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_setattr(ap)
- struct vop_setattr_args /* {
- * struct vnode *a_vp;
- * struct vattr *a_vap;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- int code;
- AFS_GLOCK();
- code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_vop_read(ap)
- struct vop_read_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * int a_ioflag;
- * struct ucred *a_cred;
- *
- * } */ *ap;
-{
- int code;
- struct vcache *avc = VTOAFS(ap->a_vp);
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- return code;
-}
-
-/* struct vop_getpages_args {
- * struct vnode *a_vp;
- * vm_page_t *a_m;
- * int a_count;
- * int a_reqpage;
- * vm_oofset_t a_offset;
- * };
- */
-int
-afs_vop_getpages(struct vop_getpages_args *ap)
-{
- int code;
- int i, nextoff, size, toff, npages;
- struct uio uio;
- struct iovec iov;
- struct buf *bp;
- vm_offset_t kva;
- vm_object_t object;
- struct vnode *vp;
- struct vcache *avc;
-
-#ifdef AFS_FBSD50_ENV
- GIANT_REQUIRED;
-#endif
- vp = ap->a_vp;
- avc = VTOAFS(vp);
- if ((object = vp->v_object) == NULL) {
- printf("afs_getpages: called with non-merged cache vnode??\n");
- return VM_PAGER_ERROR;
- }
- npages = btoc(ap->a_count);
- /*
- * If the requested page is partially valid, just return it and
- * allow the pager to zero-out the blanks. Partially valid pages
- * can only occur at the file EOF.
- */
-
- {
- vm_page_t m = ap->a_m[ap->a_reqpage];
-
-#ifdef AFS_FBSD50_ENV
- VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
-#endif
- if (m->valid != 0) {
- /* handled by vm_fault now */
- /* vm_page_zero_invalid(m, TRUE); */
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
- vm_page_free(ap->a_m[i]);
- }
-#ifdef AFS_FBSD50_ENV
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(object);
-#endif
- return (0);
- }
-#ifdef AFS_FBSD50_ENV
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(object);
-#endif
- }
- bp = getpbuf(&afs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, ap->a_m, npages);
-#ifdef AFS_FBSD50_ENV
- cnt.v_vnodein++;
- cnt.v_vnodepgsin += npages;
-#endif
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = ap->a_count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = IDX_TO_OFF(ap->a_m[0]->pindex);
- uio.uio_resid = ap->a_count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
-#ifdef AFS_FBSD50_ENV
- uio.uio_td = curthread;
-#else
- uio.uio_procp = curproc;
-#endif
-
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, osi_curcred()); /* hold bozon lock, but not basic vnode lock */
- code = afs_read(avc, &uio, osi_curcred(), 0, 0, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- pmap_qremove(kva, npages);
-
- relpbuf(bp, &afs_pbuf_freecnt);
-
- if (code && (uio.uio_resid == ap->a_count)) {
-#ifdef AFS_FBSD50_ENV
- VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
-#endif
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
- vm_page_free(ap->a_m[i]);
- }
-#ifdef AFS_FBSD50_ENV
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(object);
-#endif
- return VM_PAGER_ERROR;
- }
-
- size = ap->a_count - uio.uio_resid;
-#ifdef AFS_FBSD50_ENV
- VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
-#endif
- for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
- vm_page_t m;
- nextoff = toff + PAGE_SIZE;
- m = ap->a_m[i];
-
- m->flags &= ~PG_ZERO;
-
- if (nextoff <= size) {
- /*
- * Read operation filled an entire page
- */
- m->valid = VM_PAGE_BITS_ALL;
- vm_page_undirty(m);
- } else if (size > toff) {
- /*
- * Read operation filled a partial page.
- */
- m->valid = 0;
- vm_page_set_validclean(m, 0, size - toff);
- /* handled by vm_fault now */
- /* vm_page_zero_invalid(m, TRUE); */
- }
-
- if (i != ap->a_reqpage) {
- /*
- * Whether or not to leave the page activated is up in
- * the air, but we should put the page on a page queue
- * somewhere (it already is in the object). Result:
- * It appears that emperical results show that
- * deactivating pages is best.
- */
-
- /*
- * Just in case someone was asking for this page we
- * now tell them that it is ok to use.
- */
- if (!code) {
- if (m->flags & PG_WANTED)
- vm_page_activate(m);
- else
- vm_page_deactivate(m);
- vm_page_wakeup(m);
- } else {
- vm_page_free(m);
- }
- }
- }
-#ifdef AFS_FBSD50_ENV
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(object);
-#endif
- return 0;
-}
-
-int
-afs_vop_write(ap)
- struct vop_write_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * int a_ioflag;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- int code;
- struct vcache *avc = VTOAFS(ap->a_vp);
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
- code =
- afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
- return code;
-}
-
-/*-
- * struct vop_putpages_args {
- * struct vnode *a_vp;
- * vm_page_t *a_m;
- * int a_count;
- * int a_sync;
- * int *a_rtvals;
- * vm_oofset_t a_offset;
- * };
- */
-/*
- * All of the pages passed to us in ap->a_m[] are already marked as busy,
- * so there is no additional locking required to set their flags. -GAW
- */
-int
-afs_vop_putpages(struct vop_putpages_args *ap)
-{
- int code;
- int i, size, npages, sync;
- struct uio uio;
- struct iovec iov;
- struct buf *bp;
- vm_offset_t kva;
- struct vnode *vp;
- struct vcache *avc;
-
-#ifdef AFS_FBSD50_ENV
- GIANT_REQUIRED;
-#endif
-
- vp = ap->a_vp;
- avc = VTOAFS(vp);
- /* Perhaps these two checks should just be KASSERTs instead... */
- if (vp->v_object == NULL) {
- printf("afs_putpages: called with non-merged cache vnode??\n");
- return VM_PAGER_ERROR; /* XXX I think this is insufficient */
- }
- if (vType(avc) != VREG) {
- printf("afs_putpages: not VREG");
- return VM_PAGER_ERROR; /* XXX I think this is insufficient */
- }
- npages = btoc(ap->a_count);
- for (i = 0; i < npages; i++)
- ap->a_rtvals[i] = VM_PAGER_AGAIN;
- bp = getpbuf(&afs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, ap->a_m, npages);
-#ifdef AFS_FBSD50_ENV
- cnt.v_vnodeout++;
- cnt.v_vnodepgsout += ap->a_count;
-#endif
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = ap->a_count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = IDX_TO_OFF(ap->a_m[0]->pindex);
- uio.uio_resid = ap->a_count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_WRITE;
-#ifdef AFS_FBSD50_ENV
- uio.uio_td = curthread;
-#else
- uio.uio_procp = curproc;
-#endif
- sync = IO_VMIO;
- if (ap->a_sync & VM_PAGER_PUT_SYNC)
- sync |= IO_SYNC;
- /*if (ap->a_sync & VM_PAGER_PUT_INVAL)
- * sync |= IO_INVAL; */
-
- AFS_GLOCK();
- afs_BozonLock(&avc->pvnLock, avc);
- code = afs_write(avc, &uio, sync, osi_curcred(), 0);
- afs_BozonUnlock(&avc->pvnLock, avc);
- AFS_GUNLOCK();
-
- pmap_qremove(kva, npages);
- relpbuf(bp, &afs_pbuf_freecnt);
-
- if (!code) {
- size = ap->a_count - uio.uio_resid;
- for (i = 0; i < round_page(size) / PAGE_SIZE; i++) {
- ap->a_rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(ap->a_m[i]);
- }
- }
- return ap->a_rtvals[0];
-}
-
-int
-afs_vop_ioctl(ap)
- struct vop_ioctl_args /* {
- * struct vnode *a_vp;
- * int a_command;
- * caddr_t a_data;
- * int a_fflag;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- struct vcache *tvc = VTOAFS(ap->a_vp);
- int error = 0;
-
- /* in case we ever get in here... */
-
- AFS_STATCNT(afs_ioctl);
- if (((ap->a_command >> 8) & 0xff) == 'V') {
- /* This is a VICEIOCTL call */
- AFS_GLOCK();
- error = HandleIoctl(tvc, NULL /*Not used */ ,
- ap->a_command, ap->a_data);
- AFS_GUNLOCK();
- return (error);
- } else {
- /* No-op call; just return. */
- return (ENOTTY);
- }
-}
-
-/* ARGSUSED */
-int
-afs_vop_poll(ap)
- struct vop_poll_args /* {
- * struct vnode *a_vp;
- * int a_events;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- /*
- * We should really check to see if I/O is possible.
- */
- return (1);
-}
-
-/*
- * Mmap a file
- *
- * NB Currently unsupported.
- */
-/* ARGSUSED */
-int
-afs_vop_mmap(ap)
- struct vop_mmap_args /* {
- * struct vnode *a_vp;
- * int a_fflags;
- * struct ucred *a_cred;
- * struct proc *a_p;
- * } */ *ap;
-{
- return (EINVAL);
-}
-
-int
-afs_vop_fsync(ap)
- struct vop_fsync_args /* {
- * struct vnode *a_vp;
- * struct ucred *a_cred;
- * int a_waitfor;
- * struct proc *a_p;
- * } */ *ap;
-{
- int error;
- register struct vnode *vp = ap->a_vp;
-
- AFS_GLOCK();
- /*vflushbuf(vp, wait); */
- if (ap->a_cred)
- error = afs_fsync(VTOAFS(vp), ap->a_cred);
- else
- error = afs_fsync(VTOAFS(vp), afs_osi_credp);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_remove(ap)
- struct vop_remove_args /* {
- * struct vnode *a_dvp;
- * struct vnode *a_vp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *vp = ap->a_vp;
- register struct vnode *dvp = ap->a_dvp;
-
- GETNAME();
- AFS_GLOCK();
- error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- cache_purge(vp);
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_link(ap)
- struct vop_link_args /* {
- * struct vnode *a_vp;
- * struct vnode *a_tdvp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *dvp = ap->a_tdvp;
- register struct vnode *vp = ap->a_vp;
-#ifdef AFS_FBSD50_ENV
- struct thread *p = ap->a_cnp->cn_thread;
-#else
- struct proc *p = ap->a_cnp->cn_proc;
-#endif
-
- GETNAME();
- if (dvp->v_mount != vp->v_mount) {
- error = EXDEV;
- goto out;
- }
- if (vp->v_type == VDIR) {
- error = EISDIR;
- goto out;
- }
- if ((error = vn_lock(vp, LK_EXCLUSIVE, p)) != 0) {
- goto out;
- }
- AFS_GLOCK();
- error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- if (dvp != vp)
- VOP_UNLOCK(vp, 0, p);
- out:
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_rename(ap)
- struct vop_rename_args /* {
- * struct vnode *a_fdvp;
- * struct vnode *a_fvp;
- * struct componentname *a_fcnp;
- * struct vnode *a_tdvp;
- * struct vnode *a_tvp;
- * struct componentname *a_tcnp;
- * } */ *ap;
-{
- int error = 0;
- struct componentname *fcnp = ap->a_fcnp;
- char *fname;
- struct componentname *tcnp = ap->a_tcnp;
- char *tname;
- struct vnode *tvp = ap->a_tvp;
- register struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- register struct vnode *fdvp = ap->a_fdvp;
-#ifdef AFS_FBSD50_ENV
- struct thread *p = fcnp->cn_thread;
-#else
- struct proc *p = fcnp->cn_proc;
-#endif
-
- /*
- * Check for cross-device rename.
- */
- if ((fvp->v_mount != tdvp->v_mount)
- || (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
- abortit:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
- /*
- * if fvp == tvp, we're just removing one name of a pair of
- * directory entries for the same element. convert call into rename.
- ( (pinched from FreeBSD 4.4's ufs_rename())
-
- */
- if (fvp == tvp) {
- if (fvp->v_type == VDIR) {
- error = EINVAL;
- goto abortit;
- }
-
- /* Release destination completely. */
- vput(tdvp);
- vput(tvp);
-
- /* Delete source. */
- vrele(fdvp);
- vrele(fvp);
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- if ((fcnp->cn_flags & SAVESTART) == 0)
- panic("afs_rename: lost from startdir");
- fcnp->cn_nameiop = DELETE;
- VREF(fdvp);
- error = relookup(fdvp, &fvp, fcnp);
- if (error == 0)
- vrele(fdvp);
- if (fvp == NULL) {
- return (ENOENT);
- }
-
- error = VOP_REMOVE(fdvp, fvp, fcnp);
- if (fdvp == fvp)
- vrele(fdvp);
- else
- vput(fdvp);
- vput(fvp);
- return (error);
- }
- if ((error = vn_lock(fvp, LK_EXCLUSIVE, p)) != 0)
- goto abortit;
-
- MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
- memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
- fname[fcnp->cn_namelen] = '\0';
- MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
- memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
- tname[tcnp->cn_namelen] = '\0';
-
-
- AFS_GLOCK();
- /* XXX use "from" or "to" creds? NFS uses "to" creds */
- error =
- afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
- AFS_GUNLOCK();
-
- FREE(fname, M_TEMP);
- FREE(tname, M_TEMP);
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vput(fvp);
- return error;
-}
-
-int
-afs_vop_mkdir(ap)
- struct vop_mkdir_args /* {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * } */ *ap;
-{
- register struct vnode *dvp = ap->a_dvp;
- register struct vattr *vap = ap->a_vap;
- int error = 0;
- struct vcache *vcp;
-#ifdef AFS_FBSD50_ENV
- struct thread *p = ap->a_cnp->cn_thread;
-#else
- struct proc *p = ap->a_cnp->cn_proc;
-#endif
-
- GETNAME();
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("afs_vop_mkdir: no name");
-#endif
- AFS_GLOCK();
- error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
- AFS_GUNLOCK();
- if (error) {
- DROPNAME();
- return (error);
- }
- if (vcp) {
- *ap->a_vpp = AFSTOV(vcp);
- vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, p);
- } else
- *ap->a_vpp = 0;
- DROPNAME();
- return error;
-}
-
-int
-afs_vop_rmdir(ap)
- struct vop_rmdir_args /* {
- * struct vnode *a_dvp;
- * struct vnode *a_vp;
- * struct componentname *a_cnp;
- * } */ *ap;
-{
- int error = 0;
- register struct vnode *dvp = ap->a_dvp;
-
- GETNAME();
- AFS_GLOCK();
- error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
- AFS_GUNLOCK();
- DROPNAME();
- return error;
-}
-
-/* struct vop_symlink_args {
- * struct vnode *a_dvp;
- * struct vnode **a_vpp;
- * struct componentname *a_cnp;
- * struct vattr *a_vap;
- * char *a_target;
- * };
- */
-int
-afs_vop_symlink(struct vop_symlink_args *ap)
-{
- struct vnode *dvp;
- struct vnode *newvp;
- struct vcache *vcp;
- int error;
-
- GETNAME();
- AFS_GLOCK();
-
- dvp = ap->a_dvp;
- newvp = NULL;
-
- error =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
- if (error == 0) {
- error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
- if (error == 0) {
- newvp = AFSTOV(vcp);
-#ifdef AFS_FBSD50_ENV
- vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_thread);
-#else
- vn_lock(newvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_proc);
-#endif
- }
- }
- AFS_GUNLOCK();
- DROPNAME();
- *(ap->a_vpp) = newvp;
- return error;
-}
-
-int
-afs_vop_readdir(ap)
- struct vop_readdir_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * struct ucred *a_cred;
- * int *a_eofflag;
- * u_long *a_cookies;
- * int ncookies;
- * } */ *ap;
-{
- int error;
- off_t off;
-/* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
- ap->a_ncookies); */
- off = ap->a_uio->uio_offset;
- AFS_GLOCK();
- error =
- afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
- AFS_GUNLOCK();
- if (!error && ap->a_ncookies != NULL) {
- struct uio *uio = ap->a_uio;
- const struct dirent *dp, *dp_start, *dp_end;
- int ncookies;
- u_long *cookies, *cookiep;
-
- if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
- panic("afs_readdir: burned cookies");
- dp = (const struct dirent *)
- ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
-
- dp_end = (const struct dirent *)uio->uio_iov->iov_base;
- for (dp_start = dp, ncookies = 0; dp < dp_end;
- dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
- ncookies++;
-
- MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
- M_WAITOK);
- for (dp = dp_start, cookiep = cookies; dp < dp_end;
- dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
- off += dp->d_reclen;
- *cookiep++ = off;
- }
- *ap->a_cookies = cookies;
- *ap->a_ncookies = ncookies;
- }
-
- return error;
-}
-
-int
-afs_vop_readlink(ap)
- struct vop_readlink_args /* {
- * struct vnode *a_vp;
- * struct uio *a_uio;
- * struct ucred *a_cred;
- * } */ *ap;
-{
- int error;
-/* printf("readlink %x\n", ap->a_vp);*/
- AFS_GLOCK();
- error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
- AFS_GUNLOCK();
- return error;
-}
-
-extern int prtactive;
-
-int
-afs_vop_inactive(ap)
- struct vop_inactive_args /* {
- * struct vnode *a_vp;
- * struct proc *a_p;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
-
- if (prtactive && vp->v_usecount != 0)
- vprint("afs_vop_inactive(): pushing active", vp);
-
- AFS_GLOCK();
- afs_InactiveVCache(VTOAFS(vp), 0); /* decrs ref counts */
- AFS_GUNLOCK();
- VOP_UNLOCK(vp, 0, ap->a_p);
- return 0;
-}
-
-/*
- * struct vop_reclaim_args {
- * struct vnode *a_vp;
- * };
- */
-int
-afs_vop_reclaim(struct vop_reclaim_args *ap)
-{
- /* copied from ../OBSD/osi_vnodeops.c:afs_nbsd_reclaim() */
- int code, slept;
- struct vnode *vp = ap->a_vp;
- struct vcache *avc = VTOAFS(vp);
- int haveGlock = ISAFS_GLOCK();
- int haveVlock = CheckLock(&afs_xvcache);
-
- if (!haveGlock)
- AFS_GLOCK();
- if (!haveVlock)
- ObtainWriteLock(&afs_xvcache, 901);
-#ifndef AFS_DISCON_ENV
- code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
-#else
- /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
- code = afs_FlushVS(avc);
-#endif
- if (!haveVlock)
- ReleaseWriteLock(&afs_xvcache);
- if (!haveGlock)
- AFS_GUNLOCK();
-
- /*
- * XXX Pretend it worked, to prevent panic on shutdown
- * Garrett, please fix - Jim Rees
- */
- if (code)
- printf("afs_vop_reclaim: afs_FlushVCache failed code %d\n", code);
- return 0;
-}
-
-int
-afs_vop_bmap(ap)
- struct vop_bmap_args /* {
- * struct vnode *a_vp;
- * daddr_t a_bn;
- * struct vnode **a_vpp;
- * daddr_t *a_bnp;
- * int *a_runp;
- * int *a_runb;
- * } */ *ap;
-{
- if (ap->a_bnp) {
- *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
- }
- if (ap->a_vpp) {
- *ap->a_vpp = ap->a_vp;
- }
- if (ap->a_runp != NULL)
- *ap->a_runp = 0;
- if (ap->a_runb != NULL)
- *ap->a_runb = 0;
-
- return 0;
-}
-
-int
-afs_vop_strategy(ap)
- struct vop_strategy_args /* {
- * struct buf *a_bp;
- * } */ *ap;
-{
- int error;
- AFS_GLOCK();
- error = afs_ustrategy(ap->a_bp);
- AFS_GUNLOCK();
- return error;
-}
-
-int
-afs_vop_print(ap)
- struct vop_print_args /* {
- * struct vnode *a_vp;
- * } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct vcache *vc = VTOAFS(ap->a_vp);
- int s = vc->states;
-
-#ifdef AFS_FBSD50_ENV
- printf("tag %s, fid: %d.%x.%x.%x, opens %d, writers %d", vp->v_tag,
- (int)vc->fid.Cell, (u_int) vc->fid.Fid.Volume,
- (u_int) vc->fid.Fid.Vnode, (u_int) vc->fid.Fid.Unique, vc->opens,
- vc->execsOrWriters);
-#else
- printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
- vc->fid.Cell, (u_int) vc->fid.Fid.Volume,
- (u_int) vc->fid.Fid.Vnode, (u_int) vc->fid.Fid.Unique, vc->opens,
- vc->execsOrWriters);
-#endif
- printf("\n states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
- (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
- (s & CMAPPED) ? " mapped" : "",
- (s & CVFlushed) ? " flush in progress" : "");
- printf("\n");
- return 0;
-}
-
-/*
- * Advisory record locking support (fcntl() POSIX style)
- */
-int
-afs_vop_advlock(ap)
- struct vop_advlock_args /* {
- * struct vnode *a_vp;
- * caddr_t a_id;
- * int a_op;
- * struct flock *a_fl;
- * int a_flags;
- * } */ *ap;
-{
- int error;
- struct ucred cr = *osi_curcred();
-
- AFS_GLOCK();
- error =
- afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
- AFS_GUNLOCK();
- return error;
-}
+++ /dev/null
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
- */
-
-extern struct vnodeop_desc vop_default_desc;
-struct vop_islocked_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_islocked_desc;
-static __inline int VOP_ISLOCKED __P((
- struct vnode *vp,
- struct proc *p));
-static __inline int VOP_ISLOCKED(vp, p)
- struct vnode *vp;
- struct proc *p;
-{
- struct vop_islocked_args a;
- int rc;
- a.a_desc = VDESC(vop_islocked);
- a.a_vp = vp;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_islocked), &a);
- return (rc);
-}
-struct vop_lookup_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-extern struct vnodeop_desc vop_lookup_desc;
-static __inline int VOP_LOOKUP __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp));
-static __inline int VOP_LOOKUP(dvp, vpp, cnp)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
-{
- struct vop_lookup_args a;
- int rc;
- a.a_desc = VDESC(vop_lookup);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- rc = VCALL(dvp, VOFFSET(vop_lookup), &a);
- return (rc);
-}
-struct vop_cachedlookup_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-extern struct vnodeop_desc vop_cachedlookup_desc;
-static __inline int VOP_CACHEDLOOKUP __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp));
-static __inline int VOP_CACHEDLOOKUP(dvp, vpp, cnp)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
-{
- struct vop_cachedlookup_args a;
- int rc;
- a.a_desc = VDESC(vop_cachedlookup);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- rc = VCALL(dvp, VOFFSET(vop_cachedlookup), &a);
- return (rc);
-}
-struct vop_create_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-extern struct vnodeop_desc vop_create_desc;
-static __inline int VOP_CREATE __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap));
-static __inline int VOP_CREATE(dvp, vpp, cnp, vap)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
- struct vattr *vap;
-{
- struct vop_create_args a;
- int rc;
- a.a_desc = VDESC(vop_create);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- rc = VCALL(dvp, VOFFSET(vop_create), &a);
- return (rc);
-}
-struct vop_whiteout_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct componentname *a_cnp;
- int a_flags;
-};
-extern struct vnodeop_desc vop_whiteout_desc;
-static __inline int VOP_WHITEOUT __P((
- struct vnode *dvp,
- struct componentname *cnp,
- int flags));
-static __inline int VOP_WHITEOUT(dvp, cnp, flags)
- struct vnode *dvp;
- struct componentname *cnp;
- int flags;
-{
- struct vop_whiteout_args a;
- int rc;
- a.a_desc = VDESC(vop_whiteout);
- a.a_dvp = dvp;
- a.a_cnp = cnp;
- a.a_flags = flags;
- rc = VCALL(dvp, VOFFSET(vop_whiteout), &a);
- return (rc);
-}
-struct vop_mknod_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-extern struct vnodeop_desc vop_mknod_desc;
-static __inline int VOP_MKNOD __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap));
-static __inline int VOP_MKNOD(dvp, vpp, cnp, vap)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
- struct vattr *vap;
-{
- struct vop_mknod_args a;
- int rc;
- a.a_desc = VDESC(vop_mknod);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- rc = VCALL(dvp, VOFFSET(vop_mknod), &a);
- return (rc);
-}
-struct vop_open_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_open_desc;
-static __inline int VOP_OPEN __P((
- struct vnode *vp,
- int mode,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_OPEN(vp, mode, cred, p)
- struct vnode *vp;
- int mode;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_open_args a;
- int rc;
- a.a_desc = VDESC(vop_open);
- a.a_vp = vp;
- a.a_mode = mode;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_open), &a);
- return (rc);
-}
-struct vop_close_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_close_desc;
-static __inline int VOP_CLOSE __P((
- struct vnode *vp,
- int fflag,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_CLOSE(vp, fflag, cred, p)
- struct vnode *vp;
- int fflag;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_close_args a;
- int rc;
- a.a_desc = VDESC(vop_close);
- a.a_vp = vp;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_close), &a);
- return (rc);
-}
-struct vop_access_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_access_desc;
-static __inline int VOP_ACCESS __P((
- struct vnode *vp,
- int mode,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_ACCESS(vp, mode, cred, p)
- struct vnode *vp;
- int mode;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_access_args a;
- int rc;
- a.a_desc = VDESC(vop_access);
- a.a_vp = vp;
- a.a_mode = mode;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_access), &a);
- return (rc);
-}
-struct vop_getattr_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_getattr_desc;
-static __inline int VOP_GETATTR __P((
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_GETATTR(vp, vap, cred, p)
- struct vnode *vp;
- struct vattr *vap;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_getattr_args a;
- int rc;
- a.a_desc = VDESC(vop_getattr);
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_getattr), &a);
- return (rc);
-}
-struct vop_setattr_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_setattr_desc;
-static __inline int VOP_SETATTR __P((
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_SETATTR(vp, vap, cred, p)
- struct vnode *vp;
- struct vattr *vap;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_setattr_args a;
- int rc;
- a.a_desc = VDESC(vop_setattr);
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_setattr), &a);
- return (rc);
-}
-struct vop_read_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-extern struct vnodeop_desc vop_read_desc;
-static __inline int VOP_READ __P((
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred));
-static __inline int VOP_READ(vp, uio, ioflag, cred)
- struct vnode *vp;
- struct uio *uio;
- int ioflag;
- struct ucred *cred;
-{
- struct vop_read_args a;
- int rc;
- a.a_desc = VDESC(vop_read);
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- rc = VCALL(vp, VOFFSET(vop_read), &a);
- return (rc);
-}
-struct vop_write_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-extern struct vnodeop_desc vop_write_desc;
-static __inline int VOP_WRITE __P((
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred));
-static __inline int VOP_WRITE(vp, uio, ioflag, cred)
- struct vnode *vp;
- struct uio *uio;
- int ioflag;
- struct ucred *cred;
-{
- struct vop_write_args a;
- int rc;
- a.a_desc = VDESC(vop_write);
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- rc = VCALL(vp, VOFFSET(vop_write), &a);
- return (rc);
-}
-struct vop_lease_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct proc *a_p;
- struct ucred *a_cred;
- int a_flag;
-};
-extern struct vnodeop_desc vop_lease_desc;
-static __inline int VOP_LEASE __P((
- struct vnode *vp,
- struct proc *p,
- struct ucred *cred,
- int flag));
-static __inline int VOP_LEASE(vp, p, cred, flag)
- struct vnode *vp;
- struct proc *p;
- struct ucred *cred;
- int flag;
-{
- struct vop_lease_args a;
- int rc;
- a.a_desc = VDESC(vop_lease);
- a.a_vp = vp;
- a.a_p = p;
- a.a_cred = cred;
- a.a_flag = flag;
- rc = VCALL(vp, VOFFSET(vop_lease), &a);
- return (rc);
-}
-struct vop_ioctl_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- u_long a_command;
- caddr_t a_data;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_ioctl_desc;
-static __inline int VOP_IOCTL __P((
- struct vnode *vp,
- u_long command,
- caddr_t data,
- int fflag,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_IOCTL(vp, command, data, fflag, cred, p)
- struct vnode *vp;
- u_long command;
- caddr_t data;
- int fflag;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_ioctl_args a;
- int rc;
- a.a_desc = VDESC(vop_ioctl);
- a.a_vp = vp;
- a.a_command = command;
- a.a_data = data;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_ioctl), &a);
- return (rc);
-}
-struct vop_poll_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_poll_desc;
-static __inline int VOP_POLL __P((
- struct vnode *vp,
- int events,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_POLL(vp, events, cred, p)
- struct vnode *vp;
- int events;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_poll_args a;
- int rc;
- a.a_desc = VDESC(vop_poll);
- a.a_vp = vp;
- a.a_events = events;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_poll), &a);
- return (rc);
-}
-struct vop_kqfilter_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct knote *a_kn;
-};
-extern struct vnodeop_desc vop_kqfilter_desc;
-static __inline int VOP_KQFILTER __P((
- struct vnode *vp,
- struct knote *kn));
-static __inline int VOP_KQFILTER(vp, kn)
- struct vnode *vp;
- struct knote *kn;
-{
- struct vop_kqfilter_args a;
- int rc;
- a.a_desc = VDESC(vop_kqfilter);
- a.a_vp = vp;
- a.a_kn = kn;
- rc = VCALL(vp, VOFFSET(vop_kqfilter), &a);
- return (rc);
-}
-struct vop_revoke_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_flags;
-};
-extern struct vnodeop_desc vop_revoke_desc;
-static __inline int VOP_REVOKE __P((
- struct vnode *vp,
- int flags));
-static __inline int VOP_REVOKE(vp, flags)
- struct vnode *vp;
- int flags;
-{
- struct vop_revoke_args a;
- int rc;
- a.a_desc = VDESC(vop_revoke);
- a.a_vp = vp;
- a.a_flags = flags;
- rc = VCALL(vp, VOFFSET(vop_revoke), &a);
- return (rc);
-}
-struct vop_mmap_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_fflags;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_mmap_desc;
-static __inline int VOP_MMAP __P((
- struct vnode *vp,
- int fflags,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_MMAP(vp, fflags, cred, p)
- struct vnode *vp;
- int fflags;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_mmap_args a;
- int rc;
- a.a_desc = VDESC(vop_mmap);
- a.a_vp = vp;
- a.a_fflags = fflags;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_mmap), &a);
- return (rc);
-}
-struct vop_fsync_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_fsync_desc;
-static __inline int VOP_FSYNC __P((
- struct vnode *vp,
- struct ucred *cred,
- int waitfor,
- struct proc *p));
-static __inline int VOP_FSYNC(vp, cred, waitfor, p)
- struct vnode *vp;
- struct ucred *cred;
- int waitfor;
- struct proc *p;
-{
- struct vop_fsync_args a;
- int rc;
- a.a_desc = VDESC(vop_fsync);
- a.a_vp = vp;
- a.a_cred = cred;
- a.a_waitfor = waitfor;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_fsync), &a);
- return (rc);
-}
-struct vop_remove_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-extern struct vnodeop_desc vop_remove_desc;
-static __inline int VOP_REMOVE __P((
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp));
-static __inline int VOP_REMOVE(dvp, vp, cnp)
- struct vnode *dvp;
- struct vnode *vp;
- struct componentname *cnp;
-{
- struct vop_remove_args a;
- int rc;
- a.a_desc = VDESC(vop_remove);
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- rc = VCALL(dvp, VOFFSET(vop_remove), &a);
- return (rc);
-}
-struct vop_link_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-extern struct vnodeop_desc vop_link_desc;
-static __inline int VOP_LINK __P((
- struct vnode *tdvp,
- struct vnode *vp,
- struct componentname *cnp));
-static __inline int VOP_LINK(tdvp, vp, cnp)
- struct vnode *tdvp;
- struct vnode *vp;
- struct componentname *cnp;
-{
- struct vop_link_args a;
- int rc;
- a.a_desc = VDESC(vop_link);
- a.a_tdvp = tdvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- rc = VCALL(tdvp, VOFFSET(vop_link), &a);
- return (rc);
-}
-struct vop_rename_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
-};
-extern struct vnodeop_desc vop_rename_desc;
-static __inline int VOP_RENAME __P((
- struct vnode *fdvp,
- struct vnode *fvp,
- struct componentname *fcnp,
- struct vnode *tdvp,
- struct vnode *tvp,
- struct componentname *tcnp));
-static __inline int VOP_RENAME(fdvp, fvp, fcnp, tdvp, tvp, tcnp)
- struct vnode *fdvp;
- struct vnode *fvp;
- struct componentname *fcnp;
- struct vnode *tdvp;
- struct vnode *tvp;
- struct componentname *tcnp;
-{
- struct vop_rename_args a;
- int rc;
- a.a_desc = VDESC(vop_rename);
- a.a_fdvp = fdvp;
- a.a_fvp = fvp;
- a.a_fcnp = fcnp;
- a.a_tdvp = tdvp;
- a.a_tvp = tvp;
- a.a_tcnp = tcnp;
- rc = VCALL(fdvp, VOFFSET(vop_rename), &a);
- return (rc);
-}
-struct vop_mkdir_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-extern struct vnodeop_desc vop_mkdir_desc;
-static __inline int VOP_MKDIR __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap));
-static __inline int VOP_MKDIR(dvp, vpp, cnp, vap)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
- struct vattr *vap;
-{
- struct vop_mkdir_args a;
- int rc;
- a.a_desc = VDESC(vop_mkdir);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- rc = VCALL(dvp, VOFFSET(vop_mkdir), &a);
- return (rc);
-}
-struct vop_rmdir_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-extern struct vnodeop_desc vop_rmdir_desc;
-static __inline int VOP_RMDIR __P((
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp));
-static __inline int VOP_RMDIR(dvp, vp, cnp)
- struct vnode *dvp;
- struct vnode *vp;
- struct componentname *cnp;
-{
- struct vop_rmdir_args a;
- int rc;
- a.a_desc = VDESC(vop_rmdir);
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- rc = VCALL(dvp, VOFFSET(vop_rmdir), &a);
- return (rc);
-}
-struct vop_symlink_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
-};
-extern struct vnodeop_desc vop_symlink_desc;
-static __inline int VOP_SYMLINK __P((
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap,
- char *target));
-static __inline int VOP_SYMLINK(dvp, vpp, cnp, vap, target)
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
- struct vattr *vap;
- char *target;
-{
- struct vop_symlink_args a;
- int rc;
- a.a_desc = VDESC(vop_symlink);
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_target = target;
- rc = VCALL(dvp, VOFFSET(vop_symlink), &a);
- return (rc);
-}
-struct vop_readdir_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- int *a_ncookies;
- u_long **a_cookies;
-};
-extern struct vnodeop_desc vop_readdir_desc;
-static __inline int VOP_READDIR __P((
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred,
- int *eofflag,
- int *ncookies,
- u_long **cookies));
-static __inline int VOP_READDIR(vp, uio, cred, eofflag, ncookies, cookies)
- struct vnode *vp;
- struct uio *uio;
- struct ucred *cred;
- int *eofflag;
- int *ncookies;
- u_long **cookies;
-{
- struct vop_readdir_args a;
- int rc;
- a.a_desc = VDESC(vop_readdir);
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_eofflag = eofflag;
- a.a_ncookies = ncookies;
- a.a_cookies = cookies;
- rc = VCALL(vp, VOFFSET(vop_readdir), &a);
- return (rc);
-}
-struct vop_readlink_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
-};
-extern struct vnodeop_desc vop_readlink_desc;
-static __inline int VOP_READLINK __P((
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred));
-static __inline int VOP_READLINK(vp, uio, cred)
- struct vnode *vp;
- struct uio *uio;
- struct ucred *cred;
-{
- struct vop_readlink_args a;
- int rc;
- a.a_desc = VDESC(vop_readlink);
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- rc = VCALL(vp, VOFFSET(vop_readlink), &a);
- return (rc);
-}
-struct vop_inactive_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_inactive_desc;
-static __inline int VOP_INACTIVE __P((
- struct vnode *vp,
- struct proc *p));
-static __inline int VOP_INACTIVE(vp, p)
- struct vnode *vp;
- struct proc *p;
-{
- struct vop_inactive_args a;
- int rc;
- a.a_desc = VDESC(vop_inactive);
- a.a_vp = vp;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_inactive), &a);
- return (rc);
-}
-struct vop_reclaim_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_reclaim_desc;
-static __inline int VOP_RECLAIM __P((
- struct vnode *vp,
- struct proc *p));
-static __inline int VOP_RECLAIM(vp, p)
- struct vnode *vp;
- struct proc *p;
-{
- struct vop_reclaim_args a;
- int rc;
- a.a_desc = VDESC(vop_reclaim);
- a.a_vp = vp;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_reclaim), &a);
- return (rc);
-}
-struct vop_lock_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_flags;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_lock_desc;
-static __inline int VOP_LOCK __P((
- struct vnode *vp,
- int flags,
- struct proc *p));
-static __inline int VOP_LOCK(vp, flags, p)
- struct vnode *vp;
- int flags;
- struct proc *p;
-{
- struct vop_lock_args a;
- int rc;
- a.a_desc = VDESC(vop_lock);
- a.a_vp = vp;
- a.a_flags = flags;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_lock), &a);
- return (rc);
-}
-struct vop_unlock_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_flags;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_unlock_desc;
-static __inline int VOP_UNLOCK __P((
- struct vnode *vp,
- int flags,
- struct proc *p));
-static __inline int VOP_UNLOCK(vp, flags, p)
- struct vnode *vp;
- int flags;
- struct proc *p;
-{
- struct vop_unlock_args a;
- int rc;
- a.a_desc = VDESC(vop_unlock);
- a.a_vp = vp;
- a.a_flags = flags;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_unlock), &a);
- return (rc);
-}
-struct vop_bmap_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- daddr_t a_bn;
- struct vnode **a_vpp;
- daddr_t *a_bnp;
- int *a_runp;
- int *a_runb;
-};
-extern struct vnodeop_desc vop_bmap_desc;
-static __inline int VOP_BMAP __P((
- struct vnode *vp,
- daddr_t bn,
- struct vnode **vpp,
- daddr_t *bnp,
- int *runp,
- int *runb));
-static __inline int VOP_BMAP(vp, bn, vpp, bnp, runp, runb)
- struct vnode *vp;
- daddr_t bn;
- struct vnode **vpp;
- daddr_t *bnp;
- int *runp;
- int *runb;
-{
- struct vop_bmap_args a;
- int rc;
- a.a_desc = VDESC(vop_bmap);
- a.a_vp = vp;
- a.a_bn = bn;
- a.a_vpp = vpp;
- a.a_bnp = bnp;
- a.a_runp = runp;
- a.a_runb = runb;
- rc = VCALL(vp, VOFFSET(vop_bmap), &a);
- return (rc);
-}
-struct vop_strategy_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct buf *a_bp;
-};
-extern struct vnodeop_desc vop_strategy_desc;
-static __inline int VOP_STRATEGY __P((
- struct vnode *vp,
- struct buf *bp));
-static __inline int VOP_STRATEGY(vp, bp)
- struct vnode *vp;
- struct buf *bp;
-{
- struct vop_strategy_args a;
- int rc;
- a.a_desc = VDESC(vop_strategy);
- a.a_vp = vp;
- a.a_bp = bp;
- rc = VCALL(vp, VOFFSET(vop_strategy), &a);
- return (rc);
-}
-struct vop_print_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
-};
-extern struct vnodeop_desc vop_print_desc;
-static __inline int VOP_PRINT __P((
- struct vnode *vp));
-static __inline int VOP_PRINT(vp)
- struct vnode *vp;
-{
- struct vop_print_args a;
- int rc;
- a.a_desc = VDESC(vop_print);
- a.a_vp = vp;
- rc = VCALL(vp, VOFFSET(vop_print), &a);
- return (rc);
-}
-struct vop_pathconf_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_name;
- register_t *a_retval;
-};
-extern struct vnodeop_desc vop_pathconf_desc;
-static __inline int VOP_PATHCONF __P((
- struct vnode *vp,
- int name,
- register_t *retval));
-static __inline int VOP_PATHCONF(vp, name, retval)
- struct vnode *vp;
- int name;
- register_t *retval;
-{
- struct vop_pathconf_args a;
- int rc;
- a.a_desc = VDESC(vop_pathconf);
- a.a_vp = vp;
- a.a_name = name;
- a.a_retval = retval;
- rc = VCALL(vp, VOFFSET(vop_pathconf), &a);
- return (rc);
-}
-struct vop_advlock_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
-};
-extern struct vnodeop_desc vop_advlock_desc;
-static __inline int VOP_ADVLOCK __P((
- struct vnode *vp,
- caddr_t id,
- int op,
- struct flock *fl,
- int flags));
-static __inline int VOP_ADVLOCK(vp, id, op, fl, flags)
- struct vnode *vp;
- caddr_t id;
- int op;
- struct flock *fl;
- int flags;
-{
- struct vop_advlock_args a;
- int rc;
- a.a_desc = VDESC(vop_advlock);
- a.a_vp = vp;
- a.a_id = id;
- a.a_op = op;
- a.a_fl = fl;
- a.a_flags = flags;
- rc = VCALL(vp, VOFFSET(vop_advlock), &a);
- return (rc);
-}
-struct vop_balloc_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- off_t a_startoffset;
- int a_size;
- struct ucred *a_cred;
- int a_flags;
- struct buf **a_bpp;
-};
-extern struct vnodeop_desc vop_balloc_desc;
-static __inline int VOP_BALLOC __P((
- struct vnode *vp,
- off_t startoffset,
- int size,
- struct ucred *cred,
- int flags,
- struct buf **bpp));
-static __inline int VOP_BALLOC(vp, startoffset, size, cred, flags, bpp)
- struct vnode *vp;
- off_t startoffset;
- int size;
- struct ucred *cred;
- int flags;
- struct buf **bpp;
-{
- struct vop_balloc_args a;
- int rc;
- a.a_desc = VDESC(vop_balloc);
- a.a_vp = vp;
- a.a_startoffset = startoffset;
- a.a_size = size;
- a.a_cred = cred;
- a.a_flags = flags;
- a.a_bpp = bpp;
- rc = VCALL(vp, VOFFSET(vop_balloc), &a);
- return (rc);
-}
-struct vop_reallocblks_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct cluster_save *a_buflist;
-};
-extern struct vnodeop_desc vop_reallocblks_desc;
-static __inline int VOP_REALLOCBLKS __P((
- struct vnode *vp,
- struct cluster_save *buflist));
-static __inline int VOP_REALLOCBLKS(vp, buflist)
- struct vnode *vp;
- struct cluster_save *buflist;
-{
- struct vop_reallocblks_args a;
- int rc;
- a.a_desc = VDESC(vop_reallocblks);
- a.a_vp = vp;
- a.a_buflist = buflist;
- rc = VCALL(vp, VOFFSET(vop_reallocblks), &a);
- return (rc);
-}
-struct vop_getpages_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_reqpage;
- vm_ooffset_t a_offset;
-};
-extern struct vnodeop_desc vop_getpages_desc;
-static __inline int VOP_GETPAGES __P((
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int reqpage,
- vm_ooffset_t offset));
-static __inline int VOP_GETPAGES(vp, m, count, reqpage, offset)
- struct vnode *vp;
- vm_page_t *m;
- int count;
- int reqpage;
- vm_ooffset_t offset;
-{
- struct vop_getpages_args a;
- int rc;
- a.a_desc = VDESC(vop_getpages);
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_reqpage = reqpage;
- a.a_offset = offset;
- rc = VCALL(vp, VOFFSET(vop_getpages), &a);
- return (rc);
-}
-struct vop_putpages_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_sync;
- int *a_rtvals;
- vm_ooffset_t a_offset;
-};
-extern struct vnodeop_desc vop_putpages_desc;
-static __inline int VOP_PUTPAGES __P((
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int sync,
- int *rtvals,
- vm_ooffset_t offset));
-static __inline int VOP_PUTPAGES(vp, m, count, sync, rtvals, offset)
- struct vnode *vp;
- vm_page_t *m;
- int count;
- int sync;
- int *rtvals;
- vm_ooffset_t offset;
-{
- struct vop_putpages_args a;
- int rc;
- a.a_desc = VDESC(vop_putpages);
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_sync = sync;
- a.a_rtvals = rtvals;
- a.a_offset = offset;
- rc = VCALL(vp, VOFFSET(vop_putpages), &a);
- return (rc);
-}
-struct vop_freeblks_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- daddr_t a_addr;
- daddr_t a_length;
-};
-extern struct vnodeop_desc vop_freeblks_desc;
-static __inline int VOP_FREEBLKS __P((
- struct vnode *vp,
- daddr_t addr,
- daddr_t length));
-static __inline int VOP_FREEBLKS(vp, addr, length)
- struct vnode *vp;
- daddr_t addr;
- daddr_t length;
-{
- struct vop_freeblks_args a;
- int rc;
- a.a_desc = VDESC(vop_freeblks);
- a.a_vp = vp;
- a.a_addr = addr;
- a.a_length = length;
- rc = VCALL(vp, VOFFSET(vop_freeblks), &a);
- return (rc);
-}
-struct vop_bwrite_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct buf *a_bp;
-};
-extern struct vnodeop_desc vop_bwrite_desc;
-static __inline int VOP_BWRITE __P((
- struct vnode *vp,
- struct buf *bp));
-static __inline int VOP_BWRITE(vp, bp)
- struct vnode *vp;
- struct buf *bp;
-{
- struct vop_bwrite_args a;
- int rc;
- a.a_desc = VDESC(vop_bwrite);
- a.a_vp = vp;
- a.a_bp = bp;
- rc = VCALL(vp, VOFFSET(vop_bwrite), &a);
- return (rc);
-}
-struct vop_getacl_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_getacl_desc;
-static __inline int VOP_GETACL __P((
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_GETACL(vp, type, aclp, cred, p)
- struct vnode *vp;
- acl_type_t type;
- struct acl *aclp;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_getacl_args a;
- int rc;
- a.a_desc = VDESC(vop_getacl);
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_getacl), &a);
- return (rc);
-}
-struct vop_setacl_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_setacl_desc;
-static __inline int VOP_SETACL __P((
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_SETACL(vp, type, aclp, cred, p)
- struct vnode *vp;
- acl_type_t type;
- struct acl *aclp;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_setacl_args a;
- int rc;
- a.a_desc = VDESC(vop_setacl);
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_setacl), &a);
- return (rc);
-}
-struct vop_aclcheck_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_aclcheck_desc;
-static __inline int VOP_ACLCHECK __P((
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_ACLCHECK(vp, type, aclp, cred, p)
- struct vnode *vp;
- acl_type_t type;
- struct acl *aclp;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_aclcheck_args a;
- int rc;
- a.a_desc = VDESC(vop_aclcheck);
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_aclcheck), &a);
- return (rc);
-}
-struct vop_getextattr_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- char *a_name;
- struct uio *a_uio;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_getextattr_desc;
-static __inline int VOP_GETEXTATTR __P((
- struct vnode *vp,
- char *name,
- struct uio *uio,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_GETEXTATTR(vp, name, uio, cred, p)
- struct vnode *vp;
- char *name;
- struct uio *uio;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_getextattr_args a;
- int rc;
- a.a_desc = VDESC(vop_getextattr);
- a.a_vp = vp;
- a.a_name = name;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_getextattr), &a);
- return (rc);
-}
-struct vop_setextattr_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- char *a_name;
- struct uio *a_uio;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_setextattr_desc;
-static __inline int VOP_SETEXTATTR __P((
- struct vnode *vp,
- char *name,
- struct uio *uio,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_SETEXTATTR(vp, name, uio, cred, p)
- struct vnode *vp;
- char *name;
- struct uio *uio;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_setextattr_args a;
- int rc;
- a.a_desc = VDESC(vop_setextattr);
- a.a_vp = vp;
- a.a_name = name;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_setextattr), &a);
- return (rc);
-}
-struct vop_createvobject_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct ucred *a_cred;
- struct proc *a_p;
-};
-extern struct vnodeop_desc vop_createvobject_desc;
-static __inline int VOP_CREATEVOBJECT __P((
- struct vnode *vp,
- struct ucred *cred,
- struct proc *p));
-static __inline int VOP_CREATEVOBJECT(vp, cred, p)
- struct vnode *vp;
- struct ucred *cred;
- struct proc *p;
-{
- struct vop_createvobject_args a;
- int rc;
- a.a_desc = VDESC(vop_createvobject);
- a.a_vp = vp;
- a.a_cred = cred;
- a.a_p = p;
- rc = VCALL(vp, VOFFSET(vop_createvobject), &a);
- return (rc);
-}
-struct vop_destroyvobject_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
-};
-extern struct vnodeop_desc vop_destroyvobject_desc;
-static __inline int VOP_DESTROYVOBJECT __P((
- struct vnode *vp));
-static __inline int VOP_DESTROYVOBJECT(vp)
- struct vnode *vp;
-{
- struct vop_destroyvobject_args a;
- int rc;
- a.a_desc = VDESC(vop_destroyvobject);
- a.a_vp = vp;
- rc = VCALL(vp, VOFFSET(vop_destroyvobject), &a);
- return (rc);
-}
-struct vop_getvobject_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- struct vm_object **a_objpp;
-};
-extern struct vnodeop_desc vop_getvobject_desc;
-static __inline int VOP_GETVOBJECT __P((
- struct vnode *vp,
- struct vm_object **objpp));
-static __inline int VOP_GETVOBJECT(vp, objpp)
- struct vnode *vp;
- struct vm_object **objpp;
-{
- struct vop_getvobject_args a;
- int rc;
- a.a_desc = VDESC(vop_getvobject);
- a.a_vp = vp;
- a.a_objpp = objpp;
- rc = VCALL(vp, VOFFSET(vop_getvobject), &a);
- return (rc);
-}
+++ /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 "param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_debug.c,v 1.5 2003/07/15 23:14:21 shadow Exp $");
-
-#include "sysincludes.h"
-#include "afsincludes.h"
-#include "afs_cbqueue.h"
-#include "afs_osidnlc.h"
-#include "afs_stats.h"
-#include "afs_sysnames.h"
-#include "afs_trace.h"
-#include "afs.h"
-#include "exporter.h"
-#include "fcrypt.h"
-#include "nfsclient.h"
-#include "private_data.h"
-#include "vice.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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_file.c,v 1.8 2003/07/15 23:14:21 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/osi_inode.h" /* igetinode() */
-
-
-int afs_osicred_initialized = 0;
-struct AFS_UCRED afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct vfs *afs_cacheVfsp;
-
-
-void *
-osi_UFSOpen(afs_int32 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");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- setuerror(0);
- AFS_GUNLOCK();
- ip = (struct inode *)igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev,
- (ino_t) ainode, &dummy);
- AFS_GLOCK();
- if (getuerror()) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UFSOpen: igetinode failed");
- }
- iunlock(ip);
- afile->vnode = ITOV(ip);
- afile->size = VTOI(afile->vnode)->i_size;
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, VSYNC);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&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)
-{
- struct AFS_UCRED *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;
- MObtainWriteLock(&afs_xosi, 321);
- VATTR_NULL(&tvattr);
- /* note that this credential swapping stuff is only necessary because
- * of ufs's references directly to u.u_cred instead of to
- * credentials parameter. Probably should fix ufs some day. */
- oldCred = p_cred(u.u_procp);
- set_p_cred(u.u_procp, &afs_osi_cred);
- tvattr.va_size = asize;
- AFS_GUNLOCK();
- code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, 0);
- AFS_GLOCK();
- set_p_cred(u.u_procp, oldCred); /* restore */
- MReleaseWriteLock(&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)
-{
- struct AFS_UCRED *oldCred;
- long 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;
- retry_IO:
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
- AFS_UIOSYS, IO_UNIT, &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,
- (afs_int32) resid, ICL_TYPE_INT32, code);
- /*
- * To handle periodic low-level EFAULT failures that we've seen with the
- * Weitek chip; in all observed failed cases a second read succeeded.
- */
- if ((code == EFAULT) && (cnt1++ < 5)) {
- afs_stats_cmperf.osiread_efaults++;
- goto retry_IO;
- }
- setuerror(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)
-{
- struct AFS_UCRED *oldCred;
- long 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;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, IO_UNIT, &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } else {
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
- setuerror(code);
- code = -1;
- }
- if (afile->proc) {
- (*afile->proc) (afile, code);
- }
- return code;
-}
-
-
-void
-shutdown_osifile(void)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * setgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_groups.c,v 1.8 2003/07/15 23:14:21 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-static int
- afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
-
-static int
- afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
- int change_parent);
-
-int
-Afs_xsetgroups()
-{
- int code = 0;
- struct vrequest treq;
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
- code = afs_InitReq(&treq, p_cred(u.u_procp));
- AFS_GUNLOCK();
- if (code)
- return code;
- setgroups();
-
- /* Note that if there is a pag already in the new groups we don't
- * overwrite it with the old pag.
- */
- if (PagInCred(p_cred(u.u_procp)) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- struct ucred *cred;
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- cred = p_cred(u.u_procp);
- AddPag(treq.uid, &cred);
- AFS_GUNLOCK();
- }
- }
- return code;
-}
-
-int
-setpag(cred, pagvalue, newpag, change_parent)
- 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 (setuerror(E2BIG), 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]);
-
- if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
- return (setuerror(code), code);
- }
- return code;
-}
-
-
-static int
-afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
-{
- int ngrps, savengrps;
- int *gp;
-
- gidset[0] = gidset[1] = 0;
- AFS_STATCNT(afs_getgroups);
-
- for (gp = &cred->cr_groups[NGROUPS]; gp > cred->cr_groups; gp--) {
- if (gp[-1] != NOGROUP)
- break;
- }
- savengrps = ngrps = MIN(ngroups, gp - cred->cr_groups);
- for (gp = cred->cr_groups; ngrps--;)
- *gidset++ = *gp++;
- return savengrps;
-}
-
-
-
-static int
-afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
- int change_parent)
-{
- int ngrps;
- int i;
- int *gp;
- struct ucred *newcr;
- ulong_t s;
-#if defined(AFS_HPUX110_ENV)
- register ulong_t context;
-#endif
-
- AFS_STATCNT(afs_setgroups);
-
- if (!change_parent) {
- newcr = (struct ucred *)crdup(*cred);
- /* nobody else has the pointer to newcr because we
- ** just allocated it, so no need for locking */
- } else {
- /* somebody else might have a pointer to this structure.
- ** make sure we do not have a race condition */
- newcr = *cred;
-#if defined(AFS_HPUX110_ENV)
- /* all of the uniprocessor spinlocks are not defined. */
- /* I assume the UP and MP are now handled together */
- MP_SPINLOCK_USAV(cred_lock, context);
-#else
- s = UP_SPL6();
- SPINLOCK(cred_lock);
-#endif
- }
-
-
- /* copy the group info */
- gp = newcr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- for (; gp < &(newcr)->cr_groups[NGROUPS]; gp++)
- *gp = ((gid_t) - 1);
-
- if (!change_parent) {
- /* replace the new cred structure in the proc area */
- struct ucred *tmp;
- tmp = *cred;
- set_p_cred(u.u_procp, newcr);
- crfree(tmp);
- } else {
-#if defined(AFS_HPUX110_ENV)
- MP_SPINUNLOCK_USAV(cred_lock, context);
-#else
- (void)UP_SPLX(s);
- SPINUNLOCK(cred_lock);
-#endif
- }
-
- return (setuerror(0), 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
- */
-
-/*
- * HPUX inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_inode.c,v 1.7 2003/07/15 23:14:21 shadow Exp $");
-
-#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/mount.h>
-
-
-static struct inode *
-getinode(struct vfs *vfsp, dev_t dev, ino_t inode, int *perror)
-{
- struct mount *mp = (vfsp ? VFSTOM(vfsp) : 0);
- struct inode *pip;
- *perror = 0;
-
- if (!mp && !(mp = getmp(dev))) {
- u.u_error = ENXIO;
- return (NULL);
- }
- pip = iget(dev, mp, inode);
- if (!pip)
- *perror = BAD_IGET;
- return (pip);
-}
-
-struct inode *
-igetinode(struct vfs *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);
- ip = getinode(vfsp, dev, inode, perror);
- if (ip == NULL) {
- *perror = BAD_IGET;
- u.u_error = ENOENT; /* Well... */
- return;
- }
- if (ip->i_mode == 0) {
- /* Not an allocated inode */
- iforget(ip);
- u.u_error = ENOENT;
- return;
- }
- if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
- iput(ip);
- u.u_error = ENOENT;
- return;
- }
- return ip;
-}
-
-iforget(ip)
- struct inode *ip;
-{
- idrop(ip);
-}
-
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4)
- long dev, near_inode, param1, param2, param3, param4;
-{
- int dummy, err = 0;
- struct inode *ip, *newip;
-
- AFS_STATCNT(afs_syscall_icreate);
-
- if (!afs_suser()) {
- u.u_error = EPERM;
- goto out;
- }
-
- ip = getinode(0, (dev_t) dev, 2, &dummy);
- if (ip == NULL) {
- u.u_error = ENOENT; /* Well... */
- goto out;
- }
-
- newip = (struct inode *)ialloc(ip, near_inode, 0);
- iput(ip);
- if (newip == NULL)
- goto out;
-
- newip->i_flag |= IACC | IUPD | ICHG;
- newip->i_nlink = 1;
- newip->i_mode = IFREG;
- newip->i_vnode.v_type = VREG;
- newip->i_vicemagic = VICEMAGIC;
- newip->i_vicep1 = param1;
- newip->i_vicep2 = param2;
- I_VICE3(newip) = param3;
- newip->i_vicep4 = param4;
- u.u_r.r_val1 = newip->i_number;
-
- iput(newip);
-
- out:
- return err;
-}
-
-afs_syscall_iopen(dev, inode, usrmod)
- int dev, inode, usrmod;
-{
- struct file *fp;
- struct inode *ip;
- struct vnode *vp = NULL;
- int dummy;
- extern struct fileops vnodefops;
- register int code;
-
- AFS_STATCNT(afs_syscall_iopen);
-
- if (!afs_suser()) {
- u.u_error = EPERM;
- goto out;
- }
-
- ip = igetinode(0, (dev_t) dev, (ino_t) inode, &dummy);
- if (u.u_error)
- goto out;
- fp = falloc();
- if (!fp) {
- iput(ip);
- goto out;
- }
- iunlock(ip);
-
- fp->f_ops = &vnodefops;
- vp = ITOV(ip);
- fp->f_data = (char *)vp;
- fp->f_type = DTYPE_VNODE;
- fp->f_flag = (usrmod + 1) & (FMASK);
-
- /* Obtained from hp kernel sys/vfs_scalls.c: copen().
- * Otherwise we panic because the v_writecount
- * goes less than 0 during close.
- */
- if ((vp->v_type == VREG) && (fp->f_flag & FWRITE)) {
- VN_INC_WRITECOUNT(vp);
- }
-
- /* fp->f_count, f_msgcount are set by falloc */
- /* fp->f_offset zeroed by falloc */
- /* f_cred set by falloc */
-
- /*
- * Obtained from hp kernel sys/vfs_scalls.c: copen() does
- * a PUTF() (defined earlier in the file) before returning,
- * so we parrot what it does. If this is not done, then
- * threaded processes will get EBADF errors when they try
- * to use the resulting file descriptor (e.g. with lseek()).
- *
- * Note: u.u_r.r_val1 is set by ufalloc(), which is
- * called by falloc(), which is called above.
- */
- if (is_multithreaded(u.u_procp)) {
- int fd = (int)u.u_r.r_val1;
- putf(fd);
- }
-
- out:
- return;
-}
-
-afs_syscall_iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- int dummy;
- struct inode *ip;
- register afs_int32 code;
-
- if (!afs_suser()) {
- u.u_error = EPERM;
- goto out;
- }
-
- ip = igetinode(0, (dev_t) dev, (ino_t) inode, &dummy);
- if (u.u_error) {
- goto out;
- }
-
- if (!IS_VICEMAGIC(ip))
- u.u_error = EPERM;
- else if (ip->i_vicep1 != inode_p1)
- u.u_error = ENXIO;
- else {
- ip->i_nlink += amount;
- if (ip->i_nlink == 0) {
- CLEAR_VICEMAGIC(ip);
- }
- ip->i_flag |= ICHG;
- }
-
- iput(ip);
-
- out:
- return;
-}
+++ /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
- */
-
-/*
- * Inode information required for HPUX servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0x84fa1cb6
-
-/* These exist because HP requires more work to extract uid. */
-#define DI_VICEP3(p) ( *(int32_t *) &((p)->di_ic.ic_uid_msb) )
-#define I_VICE3(p) ( *(int32_t *)( &((p)->i_icun.i_ic.ic_uid_msb) ) )
-
-#define _GET_DC_UID(DC) ((uid_t)((DC).ic_uid_msb << 16 | (DC).ic_uid_lsb))
-#define _GET_D_UID(DP) _GET_DC_UID((DP)->di_ic)
-
-/* the VICEMAGIC field is moved to ic_flags. This is because VICEMAGIC
-** happens to set the LARGEUID bit in the ic_flags field. UFS interprets
-** this as an inode which supports large uid's, hence does not do any UID
-** length conversion on the fly. We use the uid fields to store i_vicep3.
-*/
-#define i_vicemagic i_icun.i_ic.ic_flags
-#define i_vicep1 i_icun.i_ic.ic_spare[0]
-#define i_vicep2 i_icun.i_ic.ic_spare[1]
-#define i_vicep4 i_icun.i_ic.ic_gen
-#define i_vicep3 ( *(int32_t *)( &(i_icun.i_ic.ic_uid_msb) ) )
-
-#define di_vicemagic di_ic.ic_flags
-#define di_vicep1 di_ic.ic_spare[0]
-#define di_vicep2 di_ic.ic_spare[1]
-#define di_vicep4 di_ic.ic_gen
-#define di_vicep3 ( *(int32_t *)( &(di_ic.ic_uid_msb) ) )
-
-#define IS_VICEMAGIC(ip) ((ip)->i_vicemagic == VICEMAGIC ? 1 : 0)
-#define IS_DVICEMAGIC(dp) ((dp)->di_vicemagic == VICEMAGIC ? 1 : 0)
-
-#define CLEAR_VICEMAGIC(ip) (ip)->i_vicemagic = 0
-#define CLEAR_DVICEMAGIC(dp) (dp)->di_vicemagic = 0
-
-struct inode *igetinode(struct vfs *vfsp, dev_t dev, ino_t inode,
- int *perror);
-
-#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
- */
-
-/*
- * HPUX 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 "h/kern_sem.h"
-
-#define afs_hz hz
-extern struct timeval time;
-#define osi_Time() (time.tv_sec)
-
-#ifdef PAGESIZE
-#undef PAGESIZE
-#endif
-#define PAGESIZE 8192
-
-#define AFS_UCRED ucred
-#define AFS_PROC proc_t
-
-#define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0)
-#define gop_rdwr(rw,gp,base,len,offset,segflg,unit,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(aresid),0)
-
-#undef afs_suser
-
-#define osi_curcred() (p_cred(u.u_procp))
-
-#define getpid() (afs_uint32)p_pid(u.u_procp)
-
-#define getppid() (afs_uint32)p_ppid(u.u_procp)
-
-#ifdef KERNEL
-/*
- * Global lock support.
- *
- * HP uses global mutex to protect afs land
- */
-
-#if !defined(AFS_HPUX110_ENV)
-extern sema_t afs_global_sema;
-#else
-extern b_sema_t afs_global_sema;
-#endif
-
-extern void osi_InitGlock(void);
-
-#if !defined(AFS_HPUX110_ENV)
-extern void afsHash(int nbuckets);
-extern sv_sema_t *afsHashInsertFind(tid_t key);
-extern sv_sema_t *afsHashFind(tid_t key);
-extern void afsHashRelease(tid_t key);
-
-#define AFS_GLOCK_PID kt_tid(u.u_kthreadp)
-#define AFS_SAVE_SEMA afsHashInsertFind(AFS_GLOCK_PID)
-#define AFS_FIND_SEMA afsHashFind(AFS_GLOCK_PID)
-
-#define AFS_GLOCK() MP_PXSEMA(&afs_global_sema, AFS_SAVE_SEMA)
-#define AFS_GUNLOCK() (AFS_ASSERT_GLOCK(), MP_VXSEMA(&afs_global_sema,AFS_FIND_SEMA), (!uniprocessor ? (afsHashRelease(AFS_GLOCK_PID),0) : 0))
-#define ISAFS_GLOCK() (!uniprocessor ? owns_sema(&afs_global_sema):1)
-
-#else
-#define AFS_GLOCK() b_psema(&afs_global_sema)
-#define AFS_GUNLOCK() b_vsema(&afs_global_sema)
-#define ISAFS_GLOCK() b_owns_sema(&afs_global_sema)
-
-#endif
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-
-/* Uses splnet only in the SP case */
-#define SPLVAR register ulong_t splvar
-#define NETPRI NET_SPLNET(splvar)
-#define USERPRI NET_SPLX(splvar)
-#endif /* KERNEL */
-
-#if !defined(AFS_HPUX110_ENV)
-/*
- * On HP, the global lock is an alpha semaphore, hence it is automatically
- * released and reacquired aroubd a sleep() and wakeup().
- */
-
-#define afs_osi_Sleep(x) sleep((caddr_t) x,PZERO-2)
-#else
-/*
- * On 11.22 global lock is a beta semaphore, hence we need to
- * release and reacquire around sllep and wakeup. We also need to
- * use the get_sleep_lock.
- * afs_osi_Sleep and afs_osi_Wakeup are defined
- */
-void afs_osi_Sleep(void *event);
-int afs_osi_Wakeup(void *event);
-#endif
-
-#define osi_NullHandle(x) ((x)->proc == (caddr_t) 0)
-
-#if !defined(AFS_HPUX110_ENV)
-extern caddr_t kmem_alloc();
-#endif
-#include <sys/kthread_iface.h> /* for kt_cred() */
-
-/* Expected to be available as a patch from HP */
-/* See section D of the top level README for details */
-#if defined(AFS_HPUX110_ENV)
-#include <sys/vfs_vm.h>
-#else
-#include <vfs_vm.h>
-#endif
-
-#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
- */
-
-/*
- * Implements:
- * afs_suser
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_misc.c,v 1.6 2003/07/15 23:14:21 shadow Exp $");
-
-#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.
- *
- * Here we have to save and restore errno since the HP-UX suser() sets errno.
- */
-
-afs_suser()
-{
- int save_errno;
- int code;
-
- save_errno = u.u_error;
- code = suser();
- u.u_error = save_errno;
-
- return code;
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_sleep.c,v 1.12 2003/07/15 23:14:21 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if !defined(AFS_HPUX110_ENV)
-static char waitV;
-#endif
-
-/* call procedure aproc with arock as an argument, in ams milliseconds */
-static int
-afs_osi_CallProc(aproc, arock, ams)
- register void (*aproc) ();
- register char *arock;
- afs_int32 ams;
-{
- int code;
-
- AFS_STATCNT(osi_CallProc);
-#if !defined(AFS_HPUX110_ENV)
- AFS_GUNLOCK();
-#endif
- /* hz is in cycles/second, and timeout's 3rd parm is in cycles */
- code = timeout(aproc, arock, (ams * afs_hz) / 1000 + 1);
-#if !defined(AFS_HPUX110_ENV)
- AFS_GLOCK();
-#endif
- return code;
-}
-
-/* cancel a timeout, whether or not it has already occurred */
-static int
-afs_osi_CancelProc(aproc, arock)
- register void (*aproc) ();
- register char *arock;
-{
- int code = 0;
- AFS_STATCNT(osi_CancelProc);
-
-#if !defined(AFS_HPUX110_ENV)
- AFS_GUNLOCK();
-#endif
- code = untimeout(aproc, arock);
-#if !defined(AFS_HPUX110_ENV)
- AFS_GLOCK();
-#endif
- return code;
-}
-
-#if defined(AFS_HPUX110_ENV)
-static void
-AfsWaitHack(char *event)
-{
- lock_t *sleep_lock;
-
- AFS_STATCNT(WaitHack);
- sleep_lock = get_sleep_lock(event);
- wakeup(event);
- spinunlock(sleep_lock);
-}
-#else
-
-static void
-AfsWaitHack()
-{
- AFS_STATCNT(WaitHack);
- wakeup(&waitV);
-}
-#endif
-
-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 */
-#if defined(AFS_HPUX110_ENV)
- afs_osi_Wakeup((char *)achandle);
-#else
- afs_osi_Wakeup(&waitV);
-#endif
-
-}
-
-/* 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;
-#if defined(AFS_HPUX110_ENV)
- char localwait;
- char *event;
-#endif
-
- AFS_STATCNT(osi_Wait);
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) u.u_procp;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- /* do not do anything for solaris, digital, AIX, and SGI MP */
-#if defined(AFS_HPUX110_ENV)
- if (ahandle) {
- event = (char *)ahandle;
- } else {
- event = &localwait;
- }
- afs_osi_CallProc(AfsWaitHack, event, ams);
- afs_osi_Sleep(event);
- afs_osi_CancelProc(AfsWaitHack, event);
-#else
- afs_osi_CallProc(AfsWaitHack, (char *)u.u_procp, ams);
- afs_osi_Sleep(&waitV); /* for HP 10.0 */
-
- /* do not do anything for solaris, digital, and SGI MP */
- afs_osi_CancelProc(AfsWaitHack, (char *)u.u_procp);
- if (code)
- break; /* if something happened, quit now */
-#endif
- /* 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;
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-#if defined(AFS_HPUX110_ENV)
-void
-afs_osi_Sleep(void *event)
-{
- lock_t *sleep_lock;
-
- AFS_ASSERT_GLOCK();
- get_sleep_lock(event);
- AFS_GUNLOCK();
- sleep((caddr_t) event, PZERO - 2);
- AFS_GLOCK();
-}
-
-int
-afs_osi_Wakeup(void *event)
-{
- lock_t *sleep_lock;
-
- sleep_lock = get_sleep_lock(event);
- wakeup((caddr_t) event);
- spinunlock(sleep_lock);
- return 0;
-}
-#else
-int
-afs_osi_Wakeup(void *event)
-{
- wakeup((caddr_t) event);
- return 0;
-}
-#endif
+++ /dev/null
-/*
- * HPUX specific vfs related defines (from irix)
- */
-#ifndef _HPUX_VFS_H_
-#define _HPUX_VFS_H_
-/*
- * Flock(3) call. (from sys/file.h)
- */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* don't block when locking */
-#define LOCK_UN 8 /* unlock */
-
-#define d_fileno d_ino
-
-#define splclock() spl7()
-
-#endif
+++ /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 HPUX
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_vfsops.c,v 1.13 2003/11/27 01:17:39 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-#include <sys/scall_kernprivate.h>
-
-#if defined(AFS_HPUX1123_ENV)
-#include <sys/moddefs.h>
-#endif /* AFS_HPUX1123_ENV */
-
-#if defined(AFS_HPUX1123_ENV)
-/* defind DLKM tables so we can load dynamicly */
-/* we still need an afs_unload to unload */
-/* Note: There is to be a dependency on the
- * the name of the struct <name>_wrapper, and the
- * name of the dynamicly loaded file <name>
- * We will define -DAFS_WRAPPER=<name>_wrapper
- * and -DAFS_CONF_DATA=<name>_conf_data and pass into
- * this routine
- */
-
-extern struct mod_operations mod_misc_ops;
-extern struct mod_conf_data AFS_CONF_DATA;
-
-static int afs_load(void *arg);
-/* static int afs_unload(void *arg); */
-
-struct mod_type_data afs_mod_link = {
- "AFS kernel module",
- NULL
-};
-
-struct modlink afs_modlink[] = {
- {&mod_misc_ops, &afs_mod_link},
- { NULL, NULL }
-};
-
-struct modwrapper AFS_WRAPPER = {
- MODREV,
- afs_load,
- NULL, /* should be afs_unload if we had one */
- NULL,
- &AFS_CONF_DATA,
- afs_modlink
-};
-
-#endif /* AFS_HPUX1123_ENV */
-
-static char afs_mountpath[512];
-struct vfs *afs_globalVFS = 0;
-struct vcache *afs_globalVp = 0;
-
-int
-afs_mount(struct vfs *afsp, char *path, smountargs_t * data)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_mount);
-
- if (afs_globalVFS) { /* Don't allow remounts. */
- AFS_GUNLOCK();
- return (setuerror(EBUSY));
- }
-
- afs_globalVFS = afsp;
- afsp->vfs_bsize = 8192;
- afsp->vfs_fsid[0] = AFS_VFSMAGIC; /* magic */
- afsp->vfs_fsid[1] = AFS_VFSFSID;
- strcpy(afsp->vfs_name, "AFS");
- afsp->vfs_name[3] = '\0';
-
- strncpy(afs_mountpath, path, sizeof(afs_mountpath));
- afs_mountpath[sizeof afs_mountpath - 1] = '\0';
-
-#ifndef AFS_NONFSTRANS
- /* Set up the xlator in case it wasn't done elsewhere */
- afs_xlatorinit_v2();
-#endif
-
- AFS_GUNLOCK();
- return 0;
-}
-
-
-int
-afs_unmount(struct vfs *afsp)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
-
- afs_globalVFS = 0;
- afs_shutdown();
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_root(struct vfs *afsp, struct vnode **avpp, char *unused1)
-{
- int 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 (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, p_cred(u.u_procp)))
- && !(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) {
- VN_HOLD(AFSTOV(tvp));
- SET_V_FLAG(AFSTOV(tvp), VROOT);
-
- afs_globalVFS = afsp;
- *avpp = AFSTOV(tvp);
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
- ICL_TYPE_INT32, code);
-
- AFS_GUNLOCK();
- return code;
-}
-
-int
-afs_statfs(register struct vfs *afsp, struct k_statvfs *abp)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_statfs);
-
- abp->f_type = 0;
- abp->f_frsize = 1024;
- 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 = abp->f_favail = 9000000;
- abp->f_fsid = (AFS_VFSMAGIC << 16) || AFS_VFSFSID;
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_sync(struct vfs *unused1, int unused2)
-{
- AFS_STATCNT(afs_sync);
- return 0;
-}
-
-int
-afs_vget(struct vfs *afsp, struct vnode **avcp, struct fid *fidp)
-{
- int code;
- struct vrequest treq;
- AFS_GLOCK();
- AFS_STATCNT(afs_vget);
-
- *avcp = NULL;
-
- if ((code = afs_InitReq(&treq, p_cred(u.u_procp))) == 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;
-}
-
-int
-afs_getmount(struct vfs *vfsp, char *fsmntdir, struct mount_data *mdp,
- char *unused1)
-{
- int l;
-
- mdp->md_msite = 0;
- mdp->md_dev = 0;
- mdp->md_rdev = 0;
- return (copyoutstr
- (afs_mountpath, fsmntdir, strlen(afs_mountpath) + 1, &l));
-}
-
-
-struct vfsops Afs_vfsops = {
- afs_mount,
- afs_unmount,
- afs_root,
- afs_statfs,
- afs_sync,
- afs_vget,
- afs_getmount,
- (vfs_freeze_t *) 0, /* vfs_freeze */
- (vfs_thaw_t *) 0, /* vfs_thaw */
- (vfs_quota_t *) 0, /* vfs_quota */
- (vfs_mountroot_t *) 0, /* vfs_mountroot. Note: afs_mountroot_nullop in this
- * position panicked HP 11.00+
- */
- (vfs_size_t *) 0 /* vfs_size */
-};
-
-static int afs_Starting = 0;
-
-#pragma align 64
-#if !defined(AFS_HPUX110_ENV)
-sema_t afs_global_sema = {
- NULL, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, /* sa_type */
- 0, 0, 0, 0, 0, 0, 0, NULL, /* sa_link */
- NULL, NULL
-#ifdef SEMA_COUNTING
- , 0, 0, 0, NULL
-#endif
-};
-#else
-b_sema_t afs_global_sema = { 0 };
-#endif
-
-void
-osi_InitGlock()
-{
- register ulong_t context;
-
- SPINLOCK_USAV(sched_lock, context);
- if (!afs_Starting) {
- afs_Starting = 1;
- SPINUNLOCK_USAV(sched_lock, context);
-#if defined(AFS_HPUX110_ENV)
- b_initsema(&afs_global_sema, 1, NFS_LOCK_ORDER2, "AFS GLOCK");
- /* afsHash(64); *//* 64 buckets */
-#else
- initsema(&afs_global_sema, 1, FILESYS_SEMA_PRI, FILESYS_SEMA_ORDER);
- afsHash(64); /* 64 buckets */
-#endif
- } else {
- SPINUNLOCK_USAV(sched_lock, context);
- }
- if (!afs_Starting) {
- osi_Panic("osi_Init lost initialization race");
- }
-}
-
-#if defined(AFS_HPUX1123_ENV)
-/* DLKM routine called when loaded */
-static int
-afs_load(void *arg)
-{
- afsc_link();
- return 0;
-}
-#endif /* AFS_HPUX1123_ENV */
-
-/*
- * afsc_link - Initialize VFS
- */
-int afs_vfs_slot = -1;
-
-
-afsc_link()
-{
- extern int Afs_syscall(), afs_xioctl(), Afs_xsetgroups();
-
- /* For now nothing special is required during AFS initialization. */
- AFS_STATCNT(afsc_link);
- osi_Init();
- if ((afs_vfs_slot = add_vfs_type("afs", &Afs_vfsops)) < 0)
- return;
- sysent_assign_function(AFS_SYSCALL, 7, (void (*)())Afs_syscall,
- "Afs_syscall");
- sysent_define_arg(AFS_SYSCALL, 0, longArg);
- sysent_define_arg(AFS_SYSCALL, 1, longArg);
- sysent_define_arg(AFS_SYSCALL, 2, longArg);
- sysent_define_arg(AFS_SYSCALL, 3, longArg);
- sysent_define_arg(AFS_SYSCALL, 4, longArg);
- sysent_define_arg(AFS_SYSCALL, 5, longArg);
- sysent_define_arg(AFS_SYSCALL, 6, longArg);
- sysent_returns_long(AFS_SYSCALL);
-
- sysent_delete(80);
- sysent_assign_function(80, 2, (void (*)())Afs_xsetgroups, "setgroups");
- sysent_define_arg(80, 0, longArg);
- sysent_define_arg(80, 1, longArg);
- sysent_returns_long(80);
- 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_vm.c,v 1.8 2003/07/15 23:14:22 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-/* 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.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- if (avc->vrefCount > 1)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- return 0;
-}
-
-/* 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)
-{
- ; /* Nothing here yet */
-}
-
-/* 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.
- */
-void
-osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
-{
- struct vnode *vp = AFSTOV(avc);
-
- /* Flush the delayed write blocks associated with this vnode
- * from the buffer cache
- */
- if ((vp->v_flag & VTEXT) == 0) {
- mpurge(vp);
- }
- /* Mark the cached blocks on the free list as invalid; it invalidates blocks
- * associated with vp which are on the freelist.
- */
- binvalfree(vp);
- mpurge(vp);
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- ; /* Nothing here yet */
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- ; /* Nothing here yet */
-}
+++ /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
- */
-
-/* This is a placeholder for routines unique to the port of AFS to hp-ux*/
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/HPUX/osi_vnodeops.c,v 1.13 2003/11/27 01:17:39 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-
-#include <sys/uio.h>
-#include <sys/vfs.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/pathname.h>
-
-extern struct vfsops Afs_vfsops;
-extern int afs_hp_strategy();
-extern int afs_bmap(), afs_badop(), afs_noop(), afs_lockf();
-extern int afs_pagein();
-extern int afs_pageout();
-extern int afs_ioctl();
-extern int afs_prealloc();
-extern int afs_mapdbd();
-extern int afs_mmap();
-extern int afs_cachelimit();
-extern int afs_vm_checkpage();
-extern int afs_vm_fscontiguous();
-extern int afs_vm_stopio();
-extern int afs_read_ahead();
-extern int afs_unmap();
-extern int afs_release();
-extern int afs_swapfs_len();
-extern int afs_readdir2();
-extern int afs_readdir();
-extern int afs_readdir3();
-extern int afs_pathconf();
-extern int afs_close();
-
-#define vtoblksz(vp) ((vp)->v_vfsp->vfs_bsize)
-
-#if defined(AFS_HPUX110_ENV)
-/* We no longer need to lock on the VM Empire,
- * or at least that is what is claimed.
- * so we will noopt the vmemp_ routines
- * This needs to be looked at closer.
- */
-#define vmemp_lockx()
-#undef vmemp_returnx
-#define vmemp_returnx(a) return(a)
-#define vmemp_unlockx()
-#endif
-
-#if !defined(AFS_HPUX110_ENV)
-/*
- * Copy an mbuf to the contiguous area pointed to by cp.
- * Skip <off> bytes and copy <len> bytes.
- * Returns the number of bytes not transferred.
- * The mbuf is NOT changed.
- */
-int
-m_cpytoc(m, off, len, cp)
- register struct mbuf *m;
- register int off, len;
- register caddr_t cp;
-{
- register int ml;
-
- if (m == NULL || off < 0 || len < 0 || cp == NULL)
- osi_Panic("m_cpytoc");
- while (off && m)
- if (m->m_len <= off) {
- off -= m->m_len;
- m = m->m_next;
- continue;
- } else
- break;
- if (m == NULL)
- return (len);
-
- ml = MIN(len, m->m_len - off);
- memcpy(cp, mtod(m, caddr_t) + off, (u_int) ml);
- cp += ml;
- len -= ml;
- m = m->m_next;
-
- while (len && m) {
- ml = m->m_len;
- memcpy(cp, mtod(m, caddr_t), (u_int) ml);
- cp += ml;
- len -= ml;
- m = m->m_next;
- }
-
- return (len);
-}
-#endif
-
-/*
- * Note that the standard Sun vnode interface doesn't haven't an vop_lockf(), so this code is
- * totally new. This came about because HP-UX has lockf() implemented as
- * a system call while Sun has it implemented as a library (apparently).
- * To handle this, we have to translate the lockf() request into an
- * fcntl() looking request, and then translate the results back if necessary.
- * we call afs_lockctl() directly .
- */
-afs_lockf(vp, flag, len, cred, fp, LB, UB)
- struct vnode *vp;
- int flag;
- struct AFS_UCRED *cred;
- struct file *fp;
- k_off_t len, LB, UB;
-{
- /*for now, just pretend it works */
- struct k_flock flock;
- int cmd, code;
-
- /*
- * Create a flock structure and translate the lockf request
- * into an appropriate looking fcntl() type request for afs_lockctl()
- */
- flock.l_whence = 0;
- flock.l_len = len;
- flock.l_start = fp->f_offset;
- /* convert negative lengths to positive */
- if (flock.l_len < 0) {
- flock.l_start += flock.l_len;
- flock.l_len = -(flock.l_len);
- }
- /*
- * Adjust values to look like fcntl() requests.
- * All locks are write locks, only F_LOCK requests
- * are blocking. F_TEST has to be translated into
- * a get lock and then back again.
- */
- flock.l_type = F_WRLCK;
- cmd = F_SETLK;
- switch (flag) {
- case F_ULOCK:
- flock.l_type = F_UNLCK;
- break;
- case F_LOCK:
- cmd = F_SETLKW;
- break;
- case F_TEST:
- cmd = F_GETLK;
- break;
- }
- u.u_error = mp_afs_lockctl(vp, &flock, cmd, fp->f_cred);
- if (u.u_error) {
- return (u.u_error); /* some other error code */
- }
- /*
- * if request is F_TEST, and GETLK changed
- * the lock type to ULOCK, then return 0, else
- * set errno to EACCESS and return.
- */
- if (flag == F_TEST && flock.l_type != F_UNLCK) {
- u.u_error = EACCES;
- return (u.u_error);
- }
- return (0);
-}
-
-
-#if defined(AFS_HPUX1122_ENV)
-#include "machine/vm/vmparam.h"
-#else
-#include "../machine/vmparam.h" /* For KERNELSPACE */
-#endif
-#include "h/debug.h"
-#include "h/types.h"
-#if !defined(AFS_HPUX1123_ENV)
- /* 11.23 is using 64 bit in many cases */
-#define kern_daddr_t daddr_t
-#endif
-#include "h/param.h"
-#include "h/vmmac.h"
-#include "h/time.h"
-#include "ufs/inode.h"
-#include "ufs/fs.h"
-#include "h/dbd.h"
-#if defined(AFS_HPUX1123_ENV)
-dbd_t *finddbd();
-#endif /* AFS_HPUX1123_ENV */
-#include "h/vfd.h"
-#include "h/region.h"
-#include "h/pregion.h"
-#include "h/vmmeter.h"
-#include "h/user.h"
-#include "h/sysinfo.h"
-#include "h/pfdat.h"
-#if !defined(AFS_HPUX1123_ENV)
-#include "h/tuneable.h"
-#endif
-#include "h/buf.h"
-#include "netinet/in.h"
-
-/* 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).
- */
-afs_bread(vp, lbn, bpp)
- struct vnode *vp;
- kern_daddr_t lbn;
- struct buf **bpp;
-{
- int offset, fsbsize, error;
- struct buf *bp;
- struct iovec iov;
- struct uio uio;
-
- 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;
- uio.uio_fpflags = 0;
- *bpp = 0;
-
- error = afs_read(VTOAFS(vp), &uio, p_cred(u.u_procp), lbn, bpp, 0);
- if (error) {
- afs_bread_freebp = bp;
- return error;
- }
- if (*bpp) {
- afs_bread_freebp = bp;
- } else {
- *(struct buf **)&bp->b_vp = bp; /* mark as fake */
- *bpp = bp;
- }
- return 0;
-}
-
-afs_brelse(vp, bp)
- struct vnode *vp;
- struct buf *bp;
-{
- AFS_STATCNT(afs_brelse);
-
- if ((struct buf *)bp->b_vp != bp) { /* not fake */
- ufs_brelse(bp->b_vp, 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_bmap(avc, abn, anvp, anbn)
- register struct vcache *avc;
- kern_daddr_t abn, *anbn;
- struct vcache **anvp;
-{
- AFS_STATCNT(afs_bmap);
- if (anvp)
- *anvp = avc;
- if (anbn)
- *anbn = abn * (8192 / DEV_BSIZE); /* in 512 byte units */
- return 0;
-}
-
-afs_inactive(avc, acred)
- register struct vcache *avc;
- struct AFS_UCRED *acred;
-{
- struct vnode *vp = AFSTOV(avc);
- ulong_t context;
- lock_t *sv_lock;
- if (afs_shuttingdown)
- return;
-
- /*
- * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
- * v_count 1 on last reference!
- */
- MP_H_SPINLOCK_USAV(vn_h_sl_pool, vp, &sv_lock, &context);
- if (avc->vrefCount < 1)
- osi_Panic("afs_inactive : v_count < 1\n");
-
- /*
- * If more than 1 don't unmap the vnode but do decrement the ref count
- */
- vp->v_count--;
- if (vp->v_count > 0) {
- MP_SPINUNLOCK_USAV(sv_lock, context);
- return 0;
- }
- MP_SPINUNLOCK_USAV(sv_lock, context);
- afs_InactiveVCache(avc, acred);
- return 0;
-}
-
-
-int
-mp_afs_open(register struct vnode **avcp, int aflags, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_open(avcp, aflags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_close(register struct vnode *avcp, int aflags, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_close(avcp, aflags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_rdwr(register struct vnode *avcp, struct uio *uio, enum uio_rw arw,
- int aio, struct AFS_UCRED *acred)
-{
- register int code;
- long save_resid;
-
- AFS_GLOCK();
- save_resid = uio->uio_resid;
- code = afs_rdwr(avcp, uio, arw, aio, acred);
- if (arw == UIO_WRITE && code == ENOSPC) {
- /* HP clears code if any data written. */
- uio->uio_resid = save_resid;
- }
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_getattr(register struct vnode *avcp, struct vattr *attrs,
- struct AFS_UCRED *acred, enum vsync unused1)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_getattr(avcp, attrs, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_setattr(register struct vnode *avcp, register struct vattr *attrs,
- struct AFS_UCRED *acred, int unused1)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_setattr(avcp, attrs, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_access(register struct vnode *avcp, int mode, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_access(avcp, mode, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_lookup(register struct vnode *adp, char *aname,
- register struct vnode **avcp, struct AFS_UCRED *acred,
- struct vnode *unused1)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_lookup(adp, aname, avcp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_create(register struct vnode *adp, char *aname, struct vattr *attrs,
- enum vcexcl aexcl, int amode, struct vnode **avcp,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-mp_afs_remove(register struct vnode *adp, char *aname,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_remove(adp, aname, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_link(register struct vnode *avc, register struct vnode *adp,
- char *aname, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_link(avc, adp, aname, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_rename(register struct vnode *aodp, char *aname1,
- register struct vnode *andp, char *aname2,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_rename(aodp, aname1, andp, aname2, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_mkdir(register struct vnode *adp, char *aname, struct vattr *attrs,
- register struct vnode **avcp, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_mkdir(adp, aname, attrs, avcp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-mp_afs_rmdir(register struct vnode *adp, char *aname, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_rmdir(adp, aname, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-mp_afs_readdir(register struct vnode *avc, struct uio *auio,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_readdir(avc, auio, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_symlink(register struct vnode *adp, char *aname, struct vattr *attrs,
- char *atargetName, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_symlink(adp, aname, attrs, atargetName, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-mp_afs_readlink(register struct vnode *avc, struct uio *auio,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_readlink(avc, auio, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_fsync(register struct vnode *avc, struct AFS_UCRED *acred, int unused1)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_fsync(avc, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_bread(register struct vnode *avc, kern_daddr_t lbn, struct buf **bpp,
- struct vattr *unused1, struct ucred *unused2)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_bread(avc, lbn, bpp);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_brelse(register struct vnode *avc, struct buf *bp)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_brelse(avc, bp);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-mp_afs_inactive(register struct vnode *avc, struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_inactive(avc, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_lockctl(struct vnode *avc, struct flock *af, int cmd,
- struct AFS_UCRED *acred, struct file *unused1, off_t unused2,
- off_t unused3)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_lockctl(avc, af, cmd, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_fid(struct vnode *avc, struct fid **fidpp)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_fid(avc, fidpp);
- AFS_GUNLOCK();
- return (code);
-}
-
-int
-mp_afs_readdir2(register struct vnode *avc, struct uio *auio,
- struct AFS_UCRED *acred)
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_readdir2(avc, auio, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-struct vnodeops Afs_vnodeops = {
- mp_afs_open,
- mp_afs_close,
- mp_afs_rdwr,
- afs_ioctl,
- afs_noop,
- mp_afs_getattr,
- mp_afs_setattr,
- mp_afs_access,
- mp_afs_lookup,
- mp_afs_create,
- mp_afs_remove,
- mp_afs_link,
- mp_afs_rename,
- mp_afs_mkdir,
- mp_afs_rmdir,
- afs_readdir,
- mp_afs_symlink,
- mp_afs_readlink,
- mp_afs_fsync,
- mp_afs_inactive,
- afs_bmap,
- afs_hp_strategy,
-#if !defined(AFS_NONFSTRANS)
- /* on HPUX102 the nfs translator calls afs_bread but does
- * not call afs_brelse. Hence we see a memory leak. If the
- * VOP_BREAD() call fails, then nfs does VOP_RDWR() to get
- * the same data : this is the path we follow now. */
- afs_noop,
- afs_noop,
-#else
- mp_afs_bread,
- mp_afs_brelse,
-#endif
- afs_badop, /* pathsend */
- afs_noop, /* setacl */
- afs_noop, /* getacl */
- afs_pathconf,
- afs_pathconf,
- mp_afs_lockctl,
- afs_lockf, /* lockf */
- mp_afs_fid,
- afs_noop, /*fsctl */
- afs_badop,
- afs_pagein,
- afs_pageout,
- NULL,
- NULL,
- afs_prealloc,
- afs_mapdbd,
- afs_mmap,
- afs_cachelimit,
- afs_vm_checkpage,
- afs_vm_fscontiguous,
- afs_vm_stopio,
- afs_read_ahead,
- afs_release,
- afs_unmap,
- afs_swapfs_len,
- mp_afs_readdir2,
- afs_readdir3,
-};
-
-struct vnodeops *afs_ops = &Afs_vnodeops;
-
-/* vnode file operations, and our own */
-extern int vno_rw();
-extern int vno_ioctl();
-extern int vno_select();
-extern int afs_closex();
-extern int vno_close();
-struct fileops afs_fileops = {
- vno_rw,
- vno_ioctl,
- vno_select,
- afs_close,
-};
-
-#define vtoblksz(vp) ((vp)->v_vfsp->vfs_bsize)
-
-/*
- ********************************************************************
- ****
- **** afspgin_setup_io_ranges ()
- **** similar to: nfspgin_setup_io_ranges ()
- ********************************************************************
- */
-pgcnt_t
-afspgin_setup_io_ranges(vfspage_t * vm_info, pgcnt_t bpages, k_off_t isize,
- pgcnt_t startindex)
-{
- pgcnt_t file_offset = VM_FILE_OFFSET(vm_info);
- pgcnt_t minpage; /* first page to bring in */
- pgcnt_t maxpage; /* one past last page to bring in */
- pgcnt_t maxpagein;
- pgcnt_t multio_maxpage;
- kern_daddr_t start_blk;
- dbd_t *dbd;
- expnd_flags_t up_reason, down_reason;
- int count = 1;
- int indx = 0;
- int max_num_io;
- int dbdtype;
- preg_t *prp;
-
- VM_GET_IO_INFO(vm_info, maxpagein, max_num_io);
-
- /*
- * We do not go past the end of the current pregion nor past the end
- * of the current file.
- */
-
- maxpage = startindex + (bpages - (startindex + file_offset) % bpages);
- maxpage = vm_reset_maxpage(vm_info, maxpage);
- maxpage = MIN(maxpage, (pgcnt_t) btorp(isize) - file_offset);
- maxpage = MIN(maxpage, startindex + maxpagein);
- multio_maxpage = maxpage = vm_maxpage(vm_info, maxpage);
-
- if (!maxpage)
- return (0);
-
- VASSERT(maxpage >= startindex);
-
- /*
- * Expanding the fault will create calls to FINDENTRY() for new
- * pages, which will obsolete "dbd", so copy what it points to
- * and clear it to prevent using stale data.
- */
-
- prp = VM_PRP(vm_info);
- dbdtype = DBD_TYPE(vm_info);
- start_blk = DBD_DATA(vm_info);
- vm_info->dbd = NULL;
- vm_info->vfd = NULL;
- VASSERT(dbdtype != DBD_NONE);
-
- if (max_num_io == 1) {
- /*
- * We need to set up one I/O: First we attempt to expand the
- * I/O forward. Then we expand the I/O backwards.
- */
- count =
- expand_faultin_up(vm_info, dbdtype, (int)bpages, maxpage, count,
- startindex, start_blk, &up_reason);
- maxpage = startindex + count;
- VASSERT(maxpage <= startindex + maxpagein);
- minpage = startindex - (startindex + file_offset) % bpages;
- minpage = MAX(minpage, maxpage - maxpagein);
- VASSERT(startindex >= VM_BASE_OFFSET(vm_info));
- minpage = vm_minpage(vm_info, minpage);
- VASSERT(minpage <= startindex);
- count =
- expand_faultin_down(vm_info, dbdtype, (int)bpages, minpage, count,
- &startindex, &start_blk, &down_reason);
- VM_SET_IO_STARTINDX(vm_info, 0, startindex);
- VM_SET_IO_STARTBLK(vm_info, 0, start_blk);
- VM_SET_IO_COUNT(vm_info, 0, count);
- VM_SET_NUM_IO(vm_info, 1);
- }
-
- if (max_num_io > 1) {
- /*
- * We need to set up multiple I/O information; beginning
- * with the startindex, we will expand upwards. The expansion
- * could stop for one of 2 reasons; we take the appropriate
- * action in each of these cases:
- * o VM reasons: abort setting up the multiple I/O
- * information and return to our caller indicating
- * that "retry" is required.
- * o pagelimit: set up the next I/O info [we may have
- * reached multio_maxpage at this point].
- * Note that expansion involves no more than a block at a time;
- * hence it could never stop due to "discontiguous block"
- * reason.
- */
- startindex = minpage = vm_minpage(vm_info, 0);
- for (indx = 0; (indx < max_num_io) && (startindex < multio_maxpage);
- indx++, startindex += count) {
- dbd = FINDDBD(prp->p_reg, startindex);
- start_blk = dbd->dbd_data;
- maxpage =
- startindex + (bpages - (startindex + file_offset) % bpages);
- maxpage = min(maxpage, multio_maxpage);
- count =
- expand_faultin_up(vm_info, dbdtype, bpages, maxpage,
- 1 /* count */ ,
- startindex, start_blk, &up_reason);
- VM_SET_IO_STARTINDX(vm_info, indx, startindex);
- VM_SET_IO_STARTBLK(vm_info, indx, start_blk);
- VM_SET_IO_COUNT(vm_info, indx, count);
- if (up_reason & VM_REASONS)
- break;
- VASSERT(!(up_reason & NONCONTIGUOUS_BLOCK));
- VASSERT(up_reason & PAGELIMIT);
- }
- if (startindex < multio_maxpage) {
- VM_MULT_IO_FAILURE(vm_info);
- VM_REINIT_FAULT_DBDVFD(vm_info);
- return (0); /* retry */
- }
- count = maxpagein;
- VM_SET_NUM_IO(vm_info, indx);
- }
-
- /*
- * Tell VM where the I/O intends to start. This may be different
- * from the faulting point.
- */
-
- VM_SET_STARTINDX(vm_info, VM_GET_IO_STARTINDX(vm_info, 0));
-
- return (count);
-
-}
-
-/*
- ********************************************************************
- ****
- **** afspgin_blkflsh ()
- **** similar to: nfspgin_blkflsh ()
- ********************************************************************
- */
-retval_t
-afspgin_blkflsh(vfspage_t * vm_info, struct vnode * devvp, pgcnt_t * num_4k)
-{
- int flush_reslt = 0;
- pgcnt_t count = *num_4k;
- pgcnt_t page_count;
- int indx = 0;
- int num_io = VM_GET_NUM_IO(vm_info);
-
- /*
- * On this blkflush() we don't want to purge the buffer cache and we do
- * want to wait, so the flags are '0'.
- */
-
- for (indx = 0; indx < num_io; indx++) {
- flush_reslt =
- blkflush(devvp, (kern_daddr_t) VM_GET_IO_STARTBLK(vm_info, indx),
- ptob(VM_GET_IO_COUNT(vm_info, indx)), 0,
- VM_REGION(vm_info));
- if (flush_reslt) {
- vm_lock(vm_info);
- if (vm_page_now_valid(vm_info, &page_count)) {
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- *num_4k = page_count;
- return (VM_PAGE_PRESENT);
- }
- return (VM_RETRY);
- }
- }
- return (VM_DONE);
-}
-
-/*
- ********************************************************************
- ****
- **** afspgin_io ()
- **** similar to: nfspgin_io ()
- ********************************************************************
- */
-int
-afspgin_io(vfspage_t * vm_info, struct vnode *devvp, pgcnt_t bpages,
- pgcnt_t maxpagein, pgcnt_t count)
-{
- int i;
- int error = 0;
- caddr_t vaddr = VM_ADDR(vm_info);
- caddr_t virt_addr = VM_MAPPED_ADDR(vm_info);
- pagein_info_t *io = VM_PAGEIN_INFO(vm_info);
- preg_t *prp = VM_PRP(vm_info);
- int wrt = VM_WRT(vm_info);
- space_t space = VM_SPACE(vm_info);
- int num_io = VM_GET_NUM_IO(vm_info);
-
-#ifdef notdef /* Not used in AFS */
- /*
- * With VM_READ_AHEAD_ALLOWED() macro, check if read-ahead should
- * be used in this case.
- *
- * Unlike UFS, NFS does not start the faulting page I/O
- * asynchronously. Why? Asynchronous requests are handled by the
- * biod's. It doesn't make sense to queue up the faulting request
- * behind other asynchrnous requests. This is not true for UFS
- * where the asynchrnous request is immediately handled.
- */
-
- if ((VM_READ_AHEAD_ALLOWED(vm_info)) && (nfs_read_ahead_on)
- && (NFS_DO_READ_AHEAD) && (should_do_read_ahead(prp, vaddr))) {
-
- pgcnt_t max_rhead_io;
- caddr_t rhead_vaddr;
- pgcnt_t total_rheads_allowed;
-
- /*
- * Determine the maximum amount of read-ahead I/O.
- */
- total_rheads_allowed = maxpagein - count;
-
- /*
- * If the count is less than a block, raise it to one.
- */
- if (total_rheads_allowed < bpages)
- total_rheads_allowed = bpages;
-
- max_rhead_io = total_rheads_allowed;
- rhead_vaddr = VM_MAPPED_ADDR(vm_info) + (count * NBPG);
- error =
- nfs_read_ahead(vm_info->vp, prp, wrt, space, rhead_vaddr,
- &max_rhead_io);
-
- /*
- * Set the next fault location. If read_ahead launches any
- * I/O it will adjust it accordingly.
- */
- vm_info->prp->p_nextfault = vm_info->startindex + count;
-
- /*
- * Now perform the faulting I/O synchronously.
- */
- vm_unlock(vm_info);
-
- error =
- syncpageio((swblk_t) VM_GET_IO_STARTBLK(vm_info, 0),
- VM_MAPPED_SPACE(vm_info), VM_MAPPED_ADDR(vm_info),
- (int)ptob(count), B_READ, devvp,
- B_vfs_pagein | B_pagebf, VM_REGION(vm_info));
- } else
-#endif
- {
- virt_addr = VM_MAPPED_ADDR(vm_info);
- vm_unlock(vm_info);
- for (i = 0; i < num_io; i++) {
- /*
- * REVISIT -- investigate doing asyncpageio().
- */
- error |= (io[i].error =
- syncpageio((swblk_t) VM_GET_IO_STARTBLK(vm_info, i),
- VM_MAPPED_SPACE(vm_info), virt_addr,
- (int)ptob(VM_GET_IO_COUNT(vm_info, i)),
- B_READ, devvp, B_vfs_pagein | B_pagebf,
- VM_REGION(vm_info)));
- virt_addr += ptob(VM_GET_IO_COUNT(vm_info, i));
- }
- /*
- * Set the next fault location. If read_ahead launches any
- * I/O it will adjust it accordingly.
- */
- vm_info->prp->p_nextfault = vm_info->startindex + count;
- }
-
- return (error);
-}
-
-/*
- ********************************************************************
- ****
- **** afspgin_update_dbd ()
- **** similar to: nfspgin_update_dbd ()
- ********************************************************************
- */
-void
-afspgin_update_dbd(vfspage_t * vm_info, int bsize)
-{
- k_off_t off;
- pgcnt_t count = bsize / NBPG;
- k_off_t rem;
- pgcnt_t m;
- pgcnt_t pgindx;
- kern_daddr_t blkno;
- int num_io = VM_GET_NUM_IO(vm_info);
- int i;
-
- for (i = 0; i < num_io; i++) {
-
- pgindx = VM_GET_IO_STARTINDX(vm_info, i);
- off = vnodindx(VM_REGION(vm_info), pgindx);
- rem = off % bsize;
- blkno = VM_GET_IO_STARTBLK(vm_info, i);
-
- VASSERT(bsize % NBPG == 0);
- VASSERT(rem % NBPG == 0);
-
- pgindx -= (pgcnt_t) btop(rem);
- blkno -= (kern_daddr_t) btodb(rem);
-
- /*
- * This region could start in mid-block. If so, pgindx
- * could be less than 0, so we adjust pgindx and blkno back
- * up so that pgindx is 0.
- */
-
- if (pgindx < 0) {
- pgcnt_t prem;
- prem = 0 - pgindx;
- pgindx = 0;
- count -= prem;
- blkno += btodb(ptob(prem));
- }
-
- for (m = 0; m < count && pgindx < VM_REGION_SIZE(vm_info);
- m++, pgindx++, blkno += btodb(NBPG)) {
- /*
- * Note: since this only changes one block, it
- * assumes only one block was faulted in. Currently
- * this is always true for remote files, and we only
- * get here for remote files, so everything is ok.
- */
- vm_mark_dbd(vm_info, pgindx, blkno);
- }
- }
-}
-
-int
-afs_pagein(vp, prp, wrt, space, vaddr, ret_startindex)
- struct vnode *vp;
- preg_t *prp;
- int wrt;
- space_t space;
- caddr_t vaddr;
- pgcnt_t *ret_startindex;
-{
- pgcnt_t startindex;
- pgcnt_t pgindx = *ret_startindex;
- pgcnt_t maxpagein;
- struct vnode *devvp;
- pgcnt_t count;
- kern_daddr_t start_blk = 0;
- int bsize;
- int error;
- k_off_t isize;
- int shared; /* writable memory mapped file */
- retval_t retval = 0;
- pgcnt_t ok_dbd_limit = 0; /* last dbd that we can trust */
- pgcnt_t bpages; /* number of pages per block */
- pgcnt_t page_count;
- vfspage_t *vm_info = NULL;
- int done;
-
- struct vattr va;
-
- caddr_t nvaddr;
- space_t nspace;
- int change_to_fstore = 0; /* need to change dbds to DBD_FSTORE */
- int flush_start_blk = 0;
- int flush_end_blk = 0;
-
- int i, j;
-
- AFS_STATCNT(afs_pagein);
- vmemp_lockx(); /* lock down VM empire */
-
- /* Initialize the VM info structure */
- done =
- vm_pagein_init(&vm_info, prp, pgindx, space, vaddr, wrt, 0,
- LGPG_ENABLE);
-
- /* Check to see if we slept and the page was falted in. */
- if (done) {
- vm_release_structs(vm_info);
- vmemp_returnx(1);
- }
-
- vp = VM_GET_PAGEIN_VNODE(vm_info);
- VASSERT(vp != NULL);
- shared = VM_SHARED_OBJECT(vm_info);
- VASSERT(DBD_TYPE(vm_info) != DBD_NONE);
-
- /*
- * Get the devvp and block size for this vnode type
- */
- devvp = vp;
- bsize = vp->v_vfsp->vfs_bsize;
- if (bsize <= 0 || (bsize & (DEV_BSIZE - 1)))
- osi_Panic("afs_pagein: bsize is zero or not a multiple of DEV_BSIZE");
-
- bpages = (pgcnt_t) btop(bsize);
- VASSERT(bpages > 0);
- VM_SET_FS_MAX_PAGES(vm_info, bpages);
-
- /* this trace cannot be here because the afs_global lock might not be
- * held at this point. We hold the vm global lock throughout
- * this procedure ( and not the AFS global lock )
- * afs_Trace4(afs_iclSetp, CM_TRACE_HPPAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
- * ICL_TYPE_LONG, DBD_TYPE(vm_info), ICL_TYPE_LONG, bpages,
- * ICL_TYPE_LONG, shared);
- */
- /* Come here if we have to release the region lock before
- * locking pages. This can happen in memreserve() and
- * blkflush().
- */
- retry:
- /*
- * For remote files like ours, we want to check to see if the file has shrunk.
- * If so, we should invalidate any pages past the end. In the name
- * of efficiency, we only do this if the page we want to fault is
- * past the end of the file.
- */
- {
- if (VOP_GETATTR(vp, &va, kt_cred(u.u_kthreadp), VIFSYNC) != 0) {
- VM_ZOMBIE_OBJECT(vm_info);
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- vmemp_returnx(0);
- }
- isize = va.va_size;
- if (vnodindx(VM_REGION(vm_info), pgindx) >= isize) {
- /*
- * The file has shrunk and someone is trying to access a
- * page past the end of the object. Shrink the object back
- * to its currrent size, send a SIGBUS to the faulting
- * process and return.
- *
- * We must release the region lock before calling mtrunc(),
- * since mtrunc() locks all the regions that are using this
- * file.
- */
- vm_release_memory(vm_info);
- vm_truncate_region(vm_info, isize);
- vm_release_structs(vm_info);
- vmemp_returnx(-SIGBUS);
- }
- }
-
- maxpagein = vm_pick_maxpagein(vm_info);
- if (vm_wait_for_memory(vm_info, maxpagein, 1)) {
- /* Check to see if we should continue faulting. */
- if (vm_page_now_valid(vm_info, &page_count)) {
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- vmemp_returnx(page_count);
- }
- }
- if (count = vm_no_io_required(vm_info)) {
- /* Release any excess memory. */
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- vmemp_returnx(count);
- }
-#ifdef OSDEBUG
- /*
- * We should never have DBD_HOLE pages in a non-MMF region.
- */
- if (!shared)
- VASSERT(dbd->dbd_type != DBD_HOLE);
-#endif
- VASSERT(DBD_TYPE(vm_info) != DBD_NONE);
-
- startindex = *ret_startindex;
-
- /*
- * If the page we want is in memory already, take it
- */
- if (VM_MEMORY_RESERVED(vm_info) < maxpagein) {
- /* pick up the rest of memory now. */
- if (vm_wait_for_memory(vm_info, maxpagein, 0)) {
- if (vm_page_now_valid(vm_info, &page_count)) {
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- vmemp_returnx(page_count);
- }
- goto retry;
- }
- }
-
- if (!
- (count =
- afspgin_setup_io_ranges(vm_info, bpages, isize, startindex))) {
- goto retry;
- }
-
- startindex = VM_GET_STARTINDX(vm_info);
-
- VASSERT(maxpagein >= count);
-
- /*
- * Release the memory we won't need.
- */
- if (count < maxpagein) {
- vm_release_excess_memory(vm_info,
- (VM_MEMORY_RESERVED(vm_info) - count));
- }
-
- retval = afspgin_blkflsh(vm_info, devvp, &count);
-
- if (retval == VM_RETRY) {
- goto retry;
- }
-
- if (retval == VM_PAGE_PRESENT)
- return (count);
-
-#if 0
- /*
- * The definition of krusage_cntr_t is in h/kmetric.h, which
- * is not shipped. Since it's just statistics, we punt and do
- * not update it. If it's a problem we'll need to get HP to export
- * an interface that we can use to increment the counter.
- */
-
- /* It's a real fault, not a reclaim */
- {
- krusage_cntr_t *temp;
- temp = kt_cntrp(u.u_kthreadp);
- temp->krc_majflt++;
- }
-#endif
-
- /*
- * Tell VM where the I/O intends to start. This may be different
- * from the faulting point.
- */
-
- /*
- * vm_prepare_io will fill the region with pages and release the
- * region lock.
- */
- vm_prepare_io(vm_info, &count);
-
- /*
- * Count may have been adjusted, check to make sure it's non-zero.
- */
- if (count == 0) {
- if (vm_retry(vm_info)) {
- goto retry;
- }
-
- /*
- * Release resources and retry the fault. Release any excess
- * memory.
- */
-
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
- vmemp_returnx(0);
- }
-
- error = afspgin_io(vm_info, devvp, bpages, maxpagein, count);
-
- if ((VM_IS_ZOMBIE(vm_info)) || (error)) {
- retval = -SIGBUS;
- VM_ZOMBIE_OBJECT(vm_info);
- goto backout;
- }
- /*
- * For a writable memory mapped file that is remote we must
- * detect potential holes in the file and force allocation of
- * disk space on the remote system. Unfortunately, there is
- * no easy way to do this, so this gets a little ugly.
- */
- if (shared && wrt) {
- /*
- * See if The user wants to write to this page. Write some
- * minimal amount of data back to the remote file to
- * force allocation of file space. We only need to
- * write a small amount, since holes are always at
- * least one filesystem block in size.
- */
- error = vm_alloc_hole(vm_info);
-
- /*
- * If some sort of I/O error occurred we generate a
- * SIGBUS for the process that caused the write,
- * undo our page locks, etc and return.
- */
- if ((VM_IS_ZOMBIE(vm_info)) || (error)) {
- VM_ZOMBIE_OBJECT(vm_info);
- retval = -SIGBUS;
- goto backout;
- }
-
- /*
- * Change these dbds to DBD_FSTORE. We cannot do it here,
- * since the region must be locked, and it is not locked
- * at the moment. We cannot lock the region yet, as we
- * first have to release the page locks.
- */
- change_to_fstore = 1;
- }
-
- vm_finish_io(vm_info, count);
-
- /*
- * Acquire the lock before we play around with changing the vfd's.
- */
- vm_lock(vm_info);
-
- if (change_to_fstore)
- afspgin_update_dbd(vm_info, bsize);
-
-#if defined(AFS_HPUX110_ENV)
- getppdp()->cnt.v_exfod += count;
-#else
- mpproc_info[getprocindex()].cnt.v_exfod += count;
-#endif
- vmemp_unlockx(); /* free up VM empire */
- *ret_startindex = startindex;
-
- /*
- * In case we have any excess memory...
- */
- if (VM_MEMORY_RESERVED(vm_info))
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
-
- return count;
-
- backout:
-
- vm_finish_io_failed(vm_info, count);
-
- vm_lock(vm_info);
-
- vm_undo_validation(vm_info, count);
-
- /*
- * In case we have any excess memory...
- */
- if (VM_MEMORY_RESERVED(vm_info))
- vm_release_memory(vm_info);
- vm_release_structs(vm_info);
-
- vmemp_unlockx(); /* free up VM empire */
- return retval;
-}
-
-int
-afs_pageout(vp, prp, start, end, flags)
- struct vnode *vp; /* not used */
- preg_t *prp;
- pgcnt_t start;
- pgcnt_t end;
- int flags;
-{
- struct vnode *filevp;
- struct vnode *devvp;
- pgcnt_t i;
- int steal;
- int vhand;
- int hard;
- int *piocnt; /* wakeup counter used if PAGEOUT_WAIT */
- struct ucred *old_cred;
- vfspage_t vm_info;
- fsdata_t args;
-
- int inode_changed = 0;
- int file_is_remote;
- struct inode *ip;
-
- AFS_STATCNT(afs_pageout);
-
- steal = (flags & PAGEOUT_FREE);
- vhand = (flags & PAGEOUT_VHAND);
- hard = (flags & PAGEOUT_HARD);
-
- vmemp_lockx();
-
- /* Initialize the VM info structure. */
- vm_pageout_init(&vm_info, prp, start, end, 0, 0, 0, flags);
-
- /*
- * If the region is marked "don't swap", then don't steal any pages
- * from it. We can, however, write dirty pages out to disk (only if
- * PAGEOUT_FREE is not set).
- */
- if (vm_no_pageout(&vm_info)) {
- vmemp_unlockx();
- return (0);
- }
-
- /*
- * If caller wants to wait until the I/O is complete.
- */
- vm_setup_wait_for_io(&vm_info);
-
- filevp = VM_GET_PAGEOUT_VNODE(&vm_info); /* always page out to back store */
- VASSERT(filevp != NULL);
-
- memset((caddr_t) & args, 0, sizeof(fsdata_t));
- args.remote_down = 0; /* assume remote file servers are up */
- args.remote = 1; /* we are remote */
- args.bsize = 0; /* filled up later by afs_vm_checkpage() */
-
- if (filevp->v_fstype == VUFS) {
- ip = VTOI(filevp);
- devvp = ip->i_devvp;
- file_is_remote = 0;
- } else {
- file_is_remote = 1;
- devvp = filevp;
-
- /*
- * If we are vhand(), and this is an NFS file, we need to
- * see if the NFS server is "down". If so, we decide
- * if we will try to talk to it again, or defer pageouts
- * of dirty NFS pages until a future time.
- */
-#ifdef notdef
- if (vhand && filevp->v_fstype == VNFS && vtomi(filevp)->mi_down
- && vtomi(filevp)->mi_hard) {
- extern afs_int32 vhand_nfs_retry;
- /*
- * If there is still time left on our timer, we will
- * not talk to this server right now.
- */
- if (vhand_nfs_retry > 0)
- args.remote_down = 1;
- }
-#endif
- }
-
- /*
- * Initialize args. We set bsize to 0 to tell vfs_vfdcheck() that
- * it must get the file size and other attributes if it comes across
- * a dirty page.
- */
- vm_info.fs_data = (caddr_t) & args;
-
- /* this trace cannot be here because the afs_global lock might not be
- * held at this point. We hold the vm global lock throughout
- * this procedure ( and not the AFS global lock )
- * afs_Trace4(afs_iclSetp, CM_TRACE_HPPAGEOUT, ICL_TYPE_POINTER, (afs_int32) filevp,
- * ICL_TYPE_LONG, start, ICL_TYPE_LONG, end, ICL_TYPE_LONG, flags);
- */
-
- i = start;
-
- while (i <= end) {
- struct buf *bp;
- k_off_t start;
- pgcnt_t npages;
- k_off_t nbytes;
- int error;
-
- extern int pageiodone();
- space_t nspace;
- caddr_t nvaddr;
-
- /*
- * Ask the VM system to find the next run of pages.
- */
- vm_find_next_range(&vm_info, i, end);
-
- /*
- * It's possible that the remote file shrunk in size. Check the flags
- * to see if the request was beyond the end of the file. If it was,
- * truncate the region to the file size and continue. We could be on a
- * run so after trunction continue, there may be some I/O to write
- * out.
- */
- if (VM_FS_FLAGS(&vm_info) & PAGEOUT_TRUNCATE) {
- pgcnt_t pglen = (pgcnt_t) btorp(args.isize);
-
- /*
- * This page is past the end of the file. Unlock this page
- * (region_trunc will throw it away) and then call
- * region_trunc() to invalidate all pages past the new end of
- * the file.
- */
- region_trunc(VM_REGION(&vm_info), pglen, pglen + 1);
-
- /*
- * remove the truncation flag.
- */
- VM_UNSETFS_FLAGS(&vm_info, PAGEOUT_TRUNCATE);
- }
-
- if (VM_NO_PAGEOUT_RUN(&vm_info))
- break;
-
- /*
- * We have a run of dirty pages [args.start...args.end].
- */
- VASSERT(filevp->v_fstype != VCDFS);
- VASSERT((filevp->v_vfsp->vfs_flag & VFS_RDONLY) == 0);
- VASSERT(VM_GET_NUM_IO(&vm_info) == 1);
-
- /*
- * We will be doing an I/O on the region, let the VM system know.
- */
- (void)vm_up_physio_count(&vm_info);
-
- /*
- * Okay, get set to perform the I/O.
- */
- inode_changed = 1;
- npages =
- (VM_END_PAGEOUT_INDX(&vm_info) + 1) -
- VM_START_PAGEOUT_INDX(&vm_info);
-
- /*
- * Allocate and initialize an I/O buffer.
- */
- bp = bswalloc();
- vm_init_bp(&vm_info, bp); /* Let the VM system initialize */
-
- /* Identify this buffer for KI */
- bp->b_bptype = B_vfs_pageout | B_pagebf;
-
- if (steal)
- bp->b_flags = B_CALL | B_BUSY | B_PAGEOUT; /* steal pages */
- else
- bp->b_flags = B_CALL | B_BUSY; /* keep pages */
-
- /*
- * If we are vhand paging over NFS, we will wait for the I/O
- * to complete.
- */
- if (vhand && filevp->v_fstype == VNFS) {
- bp->b_flags &= ~B_CALL;
- } else {
- bp->b_iodone = (int (*)())pageiodone;
- }
-
- /*
- * Make sure we do not write past the end of the file.
- */
- nbytes = ptob(npages);
- start = vnodindx(VM_REGION(&vm_info), vm_info.start);
- if (start + nbytes > args.isize) {
-#ifdef OSDEBUG
- /*
- * The amount we are off better not be bigger than a
- * filesystem block.
- */
- if (start + nbytes - args.isize >= args.bsize) {
- osi_Panic("afs_pageout: remainder too large");
- }
-#endif
- /*
- * Reset the size of the I/O as necessary. For remote
- * files, we set the size to the exact number of bytes to
- * the end of the file. For local files, we round this up
- * to the nearest DEV_BSIZE chunk since disk I/O must always
- * be in multiples of DEV_BSIZE. In this case, we do not
- * bother to zero out the data past the "real" end of the
- * file, this is done when the data is read (either through
- * mmap() or by normal file system access).
- */
- if (file_is_remote)
- nbytes = args.isize - start;
- else
- nbytes = roundup(args.isize - start, DEV_BSIZE);
- }
-
- /*
- * Now get ready to perform the I/O
- */
- if (!vm_protect_pageout(&vm_info, npages)) {
- VASSERT(vhand);
- vm_undo_invalidation(&vm_info, vm_info.start, vm_info.end);
- vm_finish_io_failed(&vm_info, npages);
- bswfree(bp);
- break;
- }
- /*
- * If this is an NFS write by vhand(), we will not be calling
- * pageiodone(). asyncpageio() increments parolemem for us
- * if bp->b_iodone is pageiodone, so we must do it manually
- * if pageiodone() will not be called automatically.
- */
- if (!(bp->b_flags & B_CALL) && steal) {
- register ulong_t context;
-
- SPINLOCK_USAV(pfdat_lock, context);
- parolemem += btorp(nbytes);
- SPINUNLOCK_USAV(pfdat_lock, context);
- }
- blkflush(devvp, VM_START_PAGEOUT_BLK(&vm_info), (long)nbytes,
- (BX_NOBUFWAIT | BX_PURGE), VM_REGION(&vm_info));
-
- /*
- * If vhand is the one paging things out, and this is an NFS
- * file, we need to temporarily become a different user so
- * that we are not trying to page over NFS as root. We use
- * the user credentials associated with the writable file
- * pointer that is in the psuedo-vas for this MMF.
- *
- * NOTE: we are currently using "va_rss" to store the ucred
- * value in the vas (this should be fixed in 10.0).
- */
- old_cred = kt_cred(u.u_kthreadp);
- if (vhand) {
-#if defined(AFS_HPUX1123_ENV)
- /*
- * DEE - 1123 does not have the vas.h, and it looks
- * we should never be called with a NFS type file anyway.
- * so where did this come from? Was it copied from NFS?
- * I assume it was, so we will add an assert for now
- * and see if the code runs at all.
- */
- VASSERT(filevp->v_fstype != VNFS);
-#else
- set_kt_cred(u.u_kthreadp, filevp->v_vas->va_cred);
-
- /*
- * If root was the one who opened the mmf for write,
- * va_cred will be NULL. So reset kt_cred(u.u_kthreadp) to what it
- * was. We will page out as root, but that is the
- * correct thing to do in this case anyway.
- */
- if (kt_cred(u.u_kthreadp) == NULL)
- set_kt_cred(u.u_kthreadp, old_cred);
-#endif
- }
-
- /*
- * Really do the I/O.
- */
- error =
- asyncpageio(bp, VM_START_PAGEOUT_BLK(&vm_info),
- VM_MAPPED_SPACE(&vm_info), VM_MAPPED_ADDR(&vm_info),
- (int)nbytes, B_WRITE, devvp);
-
- VASSERT(error == 0);
-
-#ifdef notdef
- /*
- * If we are vhand paging over NFS we want to wait for the
- * I/O to complete and take the appropriate actions if an
- * error is encountered.
- */
- if (vhand) {
- if (waitforpageio(bp) && nfs_mi_harddown(filevp)) {
- /*
- * The server is down, ignore this failure, and
- * try again later. (rfscall() has set our retry
- * timer).
- */
- fsdata.remote_down = 1;
- pageiocleanup(bp, 0);
-
- /*
- * vm_vfdcheck() has cleared the valid bit on the
- * vfds for these pages. We must go back and set the
- * valid bit, as the pages are really not gone.
- *
- * NOTE: we can do this because we still hold (and have
- * not released) the region lock.
- */
- if (steal)
- vm_undo_invalidation(&vm_info, vm_info.start,
- vm_info.end);
- } else {
- /*
- * The I/O succeeded, or we had an error that we do
- * not want to defer until later. Call pageidone()
- * to handle things.
- */
- pageiodone(bp);
- }
- }
-#endif
-
- /*
- * And restore our credentials to what they were.
- */
- set_kt_cred(u.u_kthreadp, old_cred);
-
- /*
- * If we reserved memory in vfs_vfdcheck(), (only for NFS) we
- * can now unreserve it.
- */
- if (vm_info.vm_flags & PAGEOUT_RESERVED) {
- vm_info.vm_flags &= ~PAGEOUT_RESERVED;
- vm_release_malloc_memory();
- }
-
- /*
- * Update statistics
- */
- if (steal) {
- if (flags & PF_DEACT) {
-#if defined(AFS_HPUX110_ENV)
- getppdp()->cnt.v_pswpout += npages;
-#else
- mpproc_info[getprocindex()].cnt.v_pswpout += npages;
-#endif
-/* sar_bswapout += ptod(npages);*/
- } else if (vhand) {
-#if defined(AFS_HPUX110_ENV)
- getppdp()->cnt.v_pgout++;
- getppdp()->cnt.v_pgpgout += npages;
-#else
- mpproc_info[getprocindex()].cnt.v_pgout++;
- mpproc_info[getprocindex()].cnt.v_pgpgout += npages;
-#endif
- }
- }
-
- /*
- * If time and patience have delivered enough
- * pages, then quit now while we are ahead.
- */
- if (VM_STOP_PAGING(&vm_info))
- break;
-
- i = VM_END_PAGEOUT_INDX(&vm_info) - VM_BASE_OFFSET(&vm_info) + 1;
- }
-
- vm_finish_pageout(&vm_info); /* update vhand's stealscan */
-
- vmemp_unlockx();
-
- /*
- * If we wanted to wait for the I/O to complete, sleep on piocnt.
- * We must decrement it by one first, and then make sure that it
- * is non-zero before going to sleep.
- */
- vm_wait_for_io(&vm_info);
-
- if (inode_changed && !file_is_remote) {
- imark(ip, IUPD | ICHG);
- iupdat(ip, 0, 0);
- }
- return 0;
-}
-
-int
-afs_mapdbd(filevp, offset, bn, flags, hole, startidx, endidx)
- struct vnode *filevp;
- off_t offset;
- kern_daddr_t *bn; /* Block number. */
- int flags; /* B_READ or B_WRITE */
- int *hole; /* To be used for read-ahead. */
- pgcnt_t *startidx; /* To be used for read-ahead. */
- pgcnt_t *endidx; /* To be used for read-ahead. */
-{
- kern_daddr_t lbn, local_bn;
- int on;
- int err;
- long bsize = vtoblksz(filevp) & ~(DEV_BSIZE - 1);
-
- if (startidx)
- *startidx = (pgcnt_t) (offset / NBPG);
- if (endidx)
- *endidx = (pgcnt_t) (offset / NBPG);
- if (hole)
- *hole = 0; /* Can't have holes. */
- if (bsize <= 0)
- osi_Panic("afs_mapdbd: zero size");
-
- lbn = (kern_daddr_t) (offset / bsize);
- on = offset % bsize;
-
- err = VOP_BMAP(filevp, lbn, NULL, &local_bn, flags);
- VASSERT(err == 0);
-
- /*
- * We can never get a bn less than zero on remote files.
- */
- VASSERT(local_bn >= 0);
-
- local_bn = local_bn + btodb(on);
- *bn = local_bn;
-
- return (0);
-}
-
-/*
- * Return values:
- * 1: The blocks are contiguous.
- * 0: The blocks are not contiguous.
- */
-int
-afs_vm_fscontiguous(vp, args, cur_data)
- struct vnode *vp;
- vfspage_t *args;
- u_int cur_data;
-{
- if (cur_data == (VM_END_PAGEOUT_BLK(args) + btodb(NBPG))) {
- return (1);
- } else {
- return (0);
- }
-}
-
-/*
- * Return values:
- * 1: Stop, this page is the last in the block.
- * 0: Continue on
- * Terminate requests at filesystem block boundaries
- */
-afs_vm_stopio(vp, args)
- struct vnode *vp;
- vfspage_t *args;
-{
- fsdata_t *fsdata = (fsdata_t *) args->fs_data;
-
-#if defined(AFS_HPUX1123_ENV)
- uint64_t tmpdb;
- tmpdb = VM_END_PAGEOUT_BLK(args);
-
- if ((dbtob(tmpdb) + NBPG) % (fsdata->bsize) == 0)
-#else
- if ((dbtob(VM_END_PAGEOUT_BLK(args)) + NBPG) % (fsdata->bsize) == 0)
-#endif /* AFS_HPUX1123_ENV */
- {
- return (1);
- } else {
- return (0);
- }
-}
-
-/*
- * afs_vm_checkpage is called by the VM while collecting a run of
- * pages on a pageout. afs_vm_checkpage() is called for each page
- * VM wants to write to disk.
- */
-afs_vm_checkpage(vp, args, pgindx, cur_data)
- struct vnode *vp;
- vfspage_t *args;
- pgcnt_t pgindx;
- int cur_data;
-{
- fsdata_t *fsdata = (fsdata_t *) args->fs_data;
-
- if (fsdata->remote_down) { /* never happens for AFS */
- /*
- * The remote system is down.
- */
- VASSERT(args->run == 0);
- return 1;
- }
- /*
- * A dirty page. If we have not yet determined the file size and
- * other attributes that we need to write out pages (the block
- * size and ok_dbd_limit), get that information now.
- */
- if (fsdata->bsize == 0) {
- k_off_t isize;
- long bsize;
- struct vattr va;
- struct vnode *filevp;
- /*
- * Get the various attributes about the file. Store them
- * in args for the next time around.
- */
- filevp = args->vp;
-
- bsize = vtoblksz(filevp);
- args->maxpgs = (pgcnt_t) btop(bsize);
-
- if (VOP_GETATTR(filevp, &va, kt_cred(u.u_kthreadp), VIFSYNC) != 0) {
- /*
- * The VOP_GETATTR() failed.
- * we are vhand, and this is a hard mount, we will
- * skip dirty pages for a while and try again later.
- */
- if (args->vm_flags & PAGEOUT_VHAND) {
- VASSERT(args->run == 0);
- return 1;
- }
- /*
- * This is a "soft" mount, or some other error was
- * returned from the server. Mark this region
- * as a zombie, and free this dirty page.
- */
- VM_ZOMBIE_OBJECT(args);
-
- /*
- * The caller will see r_zomb and remove the page
- * appropriately.
- */
- return (1);
- }
- isize = va.va_size;
- fsdata->isize = isize;
- fsdata->bsize = bsize;
- fsdata->remote = 1;
- }
- /*
- * See if the file has shrunk (this could have happened
- * asynchronously because of NFS or DUX). If so, invalidate
- * all of the pages past the end of the file. This is only
- * needed for remote files, as local files are truncated
- * synchronously.
- */
-
- if (vnodindx(VM_REGION(args), pgindx) > fsdata->isize) {
- /*
- * This page is past the end of the file. Unlock this page
- * (region_trunc will throw it away) and then call region_trunc()
- * to invalidate all pages past the new end of the file.
- */
- VM_SETFS_FLAGS(args, PAGEOUT_TRUNCATE);
- return (1);
- }
-#ifdef notdef
- if ((args->vm_flags & PAGEOUT_VHAND)
- && (!(args->vm_flags & PAGEOUT_RESERVED))
- && (!(VM_IS_ZOMBIE(args)))) {
- VASSERT(args->run == 0);
- if (vm_reserve_malloc_memory(NFS_PAGEOUT_MEM)) {
- /*
- * Got enough memory to pageout. Mark the fact that we did
- * a sysprocmemreserve(), so that we can sysprocmemunreserve() it
- * later (in remote_pageout()).
- */
- args->vm_flags |= PAGEOUT_RESERVED;
- } else {
- /*
- * We do not have enough memory to do this pageout. By
- * definition, we do not yet have a run, so we just unlock
- * this page and tell foreach_valid() to continue scanning.
- * If we come across another dirty page, we will try to
- * reserve memory again. That is okay, in fact some memory
- * may have freed up (as earlier pageouts complete under
- * interrupt).
- */
- return 1;
- }
- }
-#endif
- return (0);
-}
-
-afs_swapfs_len(bp)
- struct buf *bp;
-{
- long fs_bsize;
- long max_size;
- long bnrem;
-
- fs_bsize = vtoblksz(bp->b_vp);
- /*
- * Check to see if we are starting mid block. If so, then
- * we must return the remainder of the block or less depending
- * on the length.
- */
- bnrem = bp->b_offset % fs_bsize;
- if (bnrem) {
- max_size = fs_bsize - bnrem;
- } else {
- max_size = fs_bsize;
- }
-
- if (bp->b_bcount > max_size) {
- return (max_size);
- } else {
- return (bp->b_bcount);
- }
-}
-
-afs_mmap(vp, off, size_bytes, access)
- struct vnode *vp;
- u_int off;
-#if defined(AFS_HPUX1111_ENV)
- u_long size_bytes;
-#else
- u_int size_bytes;
-#endif
- int access;
-{
- long bsize = vtoblksz(vp);
-
- if (bsize % NBPG != 0) {
- return (EINVAL);
- }
-
- return (0);
-}
-
-afs_cachelimit(vp, len, location)
- struct vnode *vp;
- k_off_t len;
- int *location;
-{
- /*
- * Disk addresses are logical, not physical, so fragments are
- * transparent.
- */
- *location = btorp(len) + 1;
-}
-
-afs_release(vp)
- struct vnode *vp;
-{
- return (0);
-}
-
-int
-afs_unmap(vp, off, size_bytes, access)
- struct vnode *vp;
- u_int off;
-#if defined(AFS_HPUX1111_ENV)
- u_long size_bytes;
-#else
- u_int size_bytes;
-#endif
- int access;
-{
- return 0;
-}
-
-int
-afs_read_ahead(vp, prp, wrt, space, vaddr, rhead_cnt)
- struct vnode *vp;
- preg_t *prp;
- int wrt;
- space_t space;
- caddr_t vaddr;
- pgcnt_t *rhead_cnt;
-{
- printf("afs_read_ahead returning 0 \n");
- return 0;
-}
-
-int
-afs_prealloc(vp, size, ignore_minfree, reserved)
- struct vnode *vp;
- /* DEE on 11.22 following is off_t */
- size_t size;
- int ignore_minfree;
- int reserved;
-{
- printf("afs_prealloc returning ENOSPC\n");
- return ENOSPC;
-}
-
-int
-afs_ioctl(vp, com, data, flag, cred)
- struct vnode *vp;
- int com;
- caddr_t data;
- int flag;
- struct ucred *cred;
-{
- int error;
- struct afs_ioctl afsioctl, *ai;
-
- AFS_STATCNT(afs_ioctl);
-
- /* The call must be a VICEIOCTL call */
- if (((com >> 8) & 0xff) == 'V') {
-#ifdef notdef
- /* AFS_COPYIN returns error 14. Copy data in instead */
- AFS_COPYIN(data, (caddr_t) & afsioctl, sizeof(afsioctl), error);
- if (error)
- return (error);
-#endif
- ai = (struct afs_ioctl *)data;
- afsioctl.in = ai->in;
- afsioctl.out = ai->out;
- afsioctl.in_size = ai->in_size;
- afsioctl.out_size = ai->out_size;
- error = HandleIoctl(VTOAFS(vp), com, &afsioctl);
- return (error);
- }
- return (ENOTTY);
-}
-
-#if defined(AFS_HPUX1111_ENV)
-/* looks like even if appl is 32 bit, we need to round to 8 bytes */
-/* This had no effect, it must not be being used */
-
-#define roundtoint(x) (((x) + (sizeof(long) - 1)) & ~(sizeof(long) - 1))
-#define reclen(dp) roundtoint(((dp)->d_namlen + 1 + (sizeof(u_long)) +\
- sizeof(u_int) + 2 * sizeof(u_short)))
-#else
-
-#define roundtoint(x) (((x) + (sizeof(int) - 1)) & ~(sizeof(int) - 1))
-#define reclen(dp) roundtoint(((dp)->d_namlen + 1 + (sizeof(u_long)) +\
- 2 * sizeof(u_short)))
-#endif
-
-int
-afs_readdir(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- struct uio auio;
- struct iovec aiov;
- caddr_t ibuf, obuf, ibufend, obufend;
- struct __dirent32 *idp;
- struct dirent *odp;
- int count, outcount;
- dir_off_t offset;
- uint64_t tmp_offset;
-
- count = uiop->uio_resid;
- /* Allocate temporary space for format conversion */
- ibuf = kmem_alloc(2 * count); /* overkill - fix later */
- obuf = kmem_alloc(count + sizeof(struct dirent));
- aiov.iov_base = ibuf;
- aiov.iov_len = count;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- offset = auio.uio_offset = uiop->uio_offset;
- auio.uio_seg = UIOSEG_KERNEL;
- auio.uio_resid = count;
- auio.uio_fpflags = 0;
-
- u.u_error = mp_afs_readdir2(vp, &auio, cred);
- if (u.u_error)
- goto out;
-
- /* Convert entries from __dirent32 to dirent format */
-
- for (idp = (struct __dirent32 *)ibuf, odp =
- (struct dirent *)obuf, ibufend =
- ibuf + (count - auio.uio_resid), obufend = obuf + count;
- (caddr_t) idp < ibufend;
- idp = (struct __dirent32 *)((caddr_t) idp + idp->__d_reclen), odp =
- (struct dirent *)((caddr_t) odp + odp->d_reclen)) {
- odp->d_ino = idp->__d_ino;
- odp->d_namlen = idp->__d_namlen;
- (void)strcpy(odp->d_name, idp->__d_name);
- odp->d_reclen = reclen(odp);
- if ((caddr_t) odp + odp->d_reclen > obufend)
- break;
- /* record offset *after* we're sure to use this entry */
- memcpy((char *)&tmp_offset, (char *)&idp->__d_off, sizeof tmp_offset);
- offset = tmp_offset;
- }
-
- outcount = (caddr_t) odp - obuf;
- AFS_UIOMOVE(obuf, outcount, UIO_READ, uiop, u.u_error);
- if (u.u_error)
- goto out;
- uiop->uio_offset = offset;
- out:
- kmem_free(ibuf, count);
- kmem_free(obuf, count + sizeof(struct dirent));
- return u.u_error;
-}
-
-
-#define roundtolong(x) (((x) + (sizeof(long) - 1)) & ~(sizeof(long) - 1))
-#define reclen_dirent64(dp) roundtolong(((dp)->__d_namlen + 1 + (2*sizeof(u_long)) +\
- 2 * sizeof(u_short)))
-
-int
-afs_readdir3(vp, uiop, cred)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
-{
- struct uio auio;
- struct iovec aiov;
- caddr_t ibuf, obuf, ibufend, obufend;
- struct __dirent32 *idp;
- struct __dirent64 *odp;
- int count, outcount;
- dir_off_t offset;
-
- count = uiop->uio_resid;
- /* Allocate temporary space for format conversion */
- ibuf = kmem_alloc(2 * count); /* overkill - fix later */
- obuf = kmem_alloc(count + sizeof(struct __dirent64));
- aiov.iov_base = ibuf;
- aiov.iov_len = count;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- offset = auio.uio_offset = uiop->uio_offset;
- auio.uio_seg = UIOSEG_KERNEL;
- auio.uio_resid = count;
- auio.uio_fpflags = 0;
-
- u.u_error = mp_afs_readdir2(vp, &auio, cred);
- if (u.u_error)
- goto out;
-
- /* Convert entries from __dirent32 to __dirent64 format */
-
- for (idp = (struct __dirent32 *)ibuf, odp =
- (struct __dirent64 *)obuf, ibufend =
- ibuf + (count - auio.uio_resid), obufend = obuf + count;
- (caddr_t) idp < ibufend;
- idp = (struct __dirent32 *)((caddr_t) idp + idp->__d_reclen), odp =
- (struct __dirent64 *)((caddr_t) odp + odp->__d_reclen)) {
- memcpy((char *)&odp->__d_off, (char *)&idp->__d_off,
- sizeof odp->__d_off);
- odp->__d_ino = idp->__d_ino;
- odp->__d_namlen = idp->__d_namlen;
- (void)strcpy(odp->__d_name, idp->__d_name);
- odp->__d_reclen = reclen_dirent64(odp);
- if ((caddr_t) odp + odp->__d_reclen > obufend)
- break;
- /* record offset *after* we're sure to use this entry */
- offset = odp->__d_off;
- }
-
- outcount = (caddr_t) odp - obuf;
- AFS_UIOMOVE(obuf, outcount, UIO_READ, uiop, u.u_error);
- if (u.u_error)
- goto out;
- uiop->uio_offset = offset;
- out:
- kmem_free(ibuf, count);
- kmem_free(obuf, count + sizeof(struct __dirent64));
- return u.u_error;
-}
-
-#define AFS_SV_SEMA_HASH 1
-#define AFS_SV_SEMA_HASH_DEBUG 0
-
-#if AFS_SV_SEMA_HASH
-/* This portion of the code was originally used to implement
- * thread specific storage for the semaphore save area. However,
- * there were some spare fields in the proc structure, this is
- * now being used for the saving semapores. Hence, this portion of
- * the code is no longer used.
- */
-
-/* This portion of the code implements thread specific information.
- * The thread id is passed in as the key. The semaphore saved area
- * is hashed on this key.
- */
-
-/* why is this hash table required ?
- * The AFS code is written in such a way that a GLOCK() is done in
- * one function and the GUNLOCK() is done in another function further
- * down the call chain. The GLOCK() call has to save the current
- * semaphore status before acquiring afs_global_sema. The GUNLOCK
- * has to release afs_global_sema and reacquire the sempahore status
- * that existed before the corresponding GLOCK. If GLOCK() and
- * GUNLOCK() were called in the same function, the GLOCK call could
- * have stored the saved sempahore status in a local variable and the
- * corresponding GUNLOCK() call could have restored the original
- * status from this local variable. But this is not the case with
- * AFS code. Hence, we have to implement a thread specific semaphore
- * save area. This is implemented as a hash table. The key is the
- * thread id.
- */
-
-/* In order for multithreaded processes to work, the sv_sema structures
- * must be saved on a per-thread basis, not a per-process basis. There
- * is no per-thread storage available to hijack in the OS per-thread
- * data structures (e.g. struct user) so we revive this code.
- * I removed the upper limit on the memory consumption since we don't
- * know how many threads there will be. Now the code first checks the
- * freeList. If that fails it then tries garbage collecting. If that
- * doesn't free up anything then it allocs what it needs.
- */
-
-#define ELEMENT sv_sema_t
-#define KEY tid_t
-#define Hash(xx) ( (xx) % sizeOfHashTable )
-#define hashLockInit(xx) initsema(&xx,1, FILESYS_SEMA_PRI, FILESYS_SEMA_ORDER)
-#define hashLock(xx) MP_PSEMA(&xx)
-#define hashUnlock(xx) MP_VSEMA(&xx)
-
-typedef struct elem {
- struct elem *next;
- ELEMENT element;
- KEY key;
- int refCnt;
-} Element;
-
-typedef struct bucket {
- sema_t lock;
- Element *element;
-} Bucket;
-
-static int sizeOfHashTable;
-static Bucket *hashTable;
-
-static int currentSize = 0;
-static Element *freeList; /* free list */
-
-#pragma align 64
-static sema_t afsHashLock = { 0 }; /* global lock for hash table */
-
-static void afsHashGarbageCollect();
-
-/*
-** The global lock protects the global data structures,
-** e.g. freeList and currentSize.
-** The bucket lock protects the link list hanging off that bucket.
-** The lock hierarchy : one can obtain the bucket lock while holding
-** the global lock, but not vice versa.
-*/
-
-
-void
-afsHash(int nbuckets)
-{ /* allocate the hash table */
- int i;
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHash: enter\n");
-#endif
-
- sizeOfHashTable = nbuckets;
- currentSize = nbuckets * sizeof(Bucket);
-
- if (hashTable)
- osi_Panic("afs: SEMA Hashtable already created\n");
-
- hashTable = (Bucket *) AFS_KALLOC(sizeOfHashTable * sizeof(Bucket));
- if (!hashTable)
- osi_Panic("afs: cannot create SEMA Hashtable\n");
-
- /* initialize the hash table and associated locks */
- memset((char *)hashTable, 0, sizeOfHashTable * sizeof(Bucket));
- for (i = 0; i < sizeOfHashTable; i++)
- hashLockInit(hashTable[i].lock);
- hashLockInit(afsHashLock);
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHash: exit\n");
-#endif
-}
-
-ELEMENT *
-afsHashInsertFind(KEY key)
-{
- int index;
- Element *ptr;
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashInsertFind: %d\n", key);
-#endif
- if (!hashTable)
- osi_Panic("afs: afsHashInsertFind: no hashTable\n");
-
- index = Hash(key); /* get bucket number */
- hashLock(hashTable[index].lock); /* lock this bucket */
- ptr = hashTable[index].element;
-
- /* if it is already there */
- while (ptr) {
- if (ptr->key == key) {
- ptr->refCnt++; /* hold it */
- hashUnlock(hashTable[index].lock);
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashInsertFind: %d FOUND\n", key);
-#endif
- return &(ptr->element);
- } else {
- ptr = ptr->next;
- }
- }
-
- hashUnlock(hashTable[index].lock);
-
- /* if something exists in the freeList, take it from there */
- ptr = NULL;
- hashLock(afsHashLock);
-
- if (freeList) {
- ptr = freeList; /* reuse entry */
- freeList = freeList->next;
- } else {
- afsHashGarbageCollect(); /* afsHashLock locked */
- if (freeList) {
- ptr = freeList; /* reuse entry */
- freeList = freeList->next;
- } else {
- ptr = (Element *) AFS_KALLOC(sizeof(Element));
- }
- }
-
- currentSize += sizeof(Element); /* update memory used */
- hashUnlock(afsHashLock);
-
- if (!ptr)
- osi_Panic("afs: SEMA Hashtable cannot create new entry\n");
- /* create new entry */
- ptr->key = key;
- memset((char *)&ptr->element, 0, sizeof(ptr->element));
- ptr->refCnt = 1; /* this guy */
-
- /* insert new entry in bucket */
- hashLock(hashTable[index].lock); /* lock this bucket */
- ptr->next = hashTable[index].element;
- hashTable[index].element = ptr;
- hashUnlock(hashTable[index].lock);
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashInsertFind: %d MADE\n", key);
-#endif
-
- return &(ptr->element);
-}
-
-ELEMENT *
-afsHashFind(KEY key)
-{
- int index;
- Element *ptr;
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashFind: %d\n", key);
-#endif
- if (!hashTable)
- osi_Panic("afs: afsHashFind: no hashTable\n");
-
- index = Hash(key); /* get bucket number */
- hashLock(hashTable[index].lock); /* lock this bucket */
- ptr = hashTable[index].element;
-
- /* it should be in the hash table */
- while (ptr) {
- if (ptr->key == key) {
- if (ptr->refCnt <= 0)
- osi_Panic("afs: SEMA HashTable entry already released\n");
- hashUnlock(hashTable[index].lock);
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashFind: %d FOUND\n", key);
-#endif
- return &(ptr->element);
- } else {
- ptr = ptr->next;
- }
- }
-
- hashUnlock(hashTable[index].lock);
- /* it better be in the hash table */
- osi_Panic("afs: SEMA HashTable wants non-existent entry \n");
- return 0;
-}
-
-void
-afsHashRelease(KEY key)
-{
- int index;
- Element *ptr;
-
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashRelease: %d\n", key);
-#endif
- if (!hashTable)
- osi_Panic("afs: afsHashRelease: no hashTable\n");
-
- index = Hash(key); /* get bucket number */
- hashLock(hashTable[index].lock); /* lock this bucket */
- ptr = hashTable[index].element;
-
- /* it should be in the hash table */
- while (ptr) {
- if (ptr->key == key) {
- if (ptr->refCnt <= 0)
- osi_Panic("afs: SEMA HashTable entry already released\n");
- ptr->refCnt--; /* release this guy */
- hashUnlock(hashTable[index].lock);
-#if AFS_SV_SEMA_HASH_DEBUG
- printf("afsHashRelease: %d FOUND\n", key);
-#endif
- return;
- } else {
- ptr = ptr->next;
- }
- }
-
- hashUnlock(hashTable[index].lock);
- /* it better be in the hash table */
- osi_Panic("afs: SEMA HashTable deleting non-existent entry \n");
-}
-
-/* this should be called with afsHashLock WRITE locked */
-static void
-afsHashGarbageCollect()
-{
- int index;
- Element *ptr;
- int foundFlag = 0;
-
- if (!hashTable)
- osi_Panic("afs: afsHashGarbageCollect: no hashTable\n");
-
- for (index = 0; index < sizeOfHashTable; index++) {
- hashLock(hashTable[index].lock);
- ptr = hashTable[index].element; /* pick up bucket */
-
- while (ptr && !ptr->refCnt) {
- /* insert this element into free list */
- Element *temp;
- temp = ptr->next;
- ptr->next = freeList;
- freeList = ptr;
-
- foundFlag = 1; /* found at least one */
- currentSize -= sizeof(Element);
- ptr = temp;
- }
- hashTable[index].element = ptr;
-
- /* scan thru the remaining list */
- if (ptr) {
- while (ptr->next) {
- if (ptr->next->refCnt == 0) {
- /* collect this element */
- Element *temp;
- temp = ptr->next;
- ptr->next = ptr->next->next;
- temp->next = freeList;
- freeList = temp;
- foundFlag = 1;
- currentSize -= sizeof(Element);
- } else {
- ptr = ptr->next;
- }
- }
- }
- hashUnlock(hashTable[index].lock);
- }
-#if 0
- if (!foundFlag)
- osi_Panic("afs: SEMA HashTable full\n");
-#endif
-}
-
-#endif /* AFS_SV_SEMA_HASH */
-
-
-afs_hp_strategy(bp)
- register struct buf *bp;
-{
- register afs_int32 code;
- struct uio tuio;
- struct iovec tiovec[1];
- extern caddr_t hdl_kmap_bp();
- register struct kthread *t = u.u_kthreadp;
-
- AFS_STATCNT(afs_hp_strategy);
- /*
- * hdl_kmap_bp() saves "b_bcount" and restores it in hdl_remap_bp() after
- * the I/O. We must save and restore the count because pageiodone()
- * uses b_bcount to determine how many pages to unlock.
- *
- * Remap the entire range.
- */
- hdl_kmap_bp(bp);
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_HPSTRAT, ICL_TYPE_POINTER, bp->b_vp,
- ICL_TYPE_LONG, (int)bp->b_blkno * DEV_BSIZE, ICL_TYPE_LONG,
- bp->b_bcount, ICL_TYPE_LONG, 0);
-
- /* Set up the uio structure */
- tuio.afsio_iov = tiovec;
- tuio.afsio_iovcnt = 1;
- tuio.afsio_offset = DEV_BSIZE * bp->b_blkno;
- tuio.afsio_seg = AFS_UIOSYS;
- tuio.afsio_resid = bp->b_bcount;
- tuio.uio_fpflags = 0;
- tiovec[0].iov_base = bp->b_un.b_addr;
- tiovec[0].iov_len = bp->b_bcount;
-
- /* Do the I/O */
- if ((bp->b_flags & B_READ) == B_READ) {
- /* read b_bcount bytes into kernel address b_un.b_addr
- * starting at byte DEV_BSIZE * b_blkno. Bzero anything
- * we can't read, and finally call iodone(bp). File is
- * in bp->b_vp. Credentials are from u area??
- */
- code = afs_rdwr(VTOAFS(bp->b_vp), &tuio, UIO_READ, 0, kt_cred(t));
- if (code == 0)
- if (tuio.afsio_resid > 0) {
- privlbzero(bvtospace(bp, bp->b_un.b_addr),
- bp->b_un.b_addr + bp->b_bcount - tuio.afsio_resid,
- (size_t) tuio.afsio_resid);
-
- }
- } else
- code = afs_rdwr(VTOAFS(bp->b_vp), &tuio, UIO_WRITE, 0, kt_cred(t));
-
- /* Remap back to the user's space */
- hdl_remap_bp(bp);
-
- AFS_GUNLOCK();
-
- iodone(bp);
- return code;
-}
-
-afs_pathconf(vp, name, resultp, cred)
- struct vnode *vp;
- int name;
- int *resultp;
- struct ucred *cred; /* unused */
-{
- switch (name) {
- case _PC_LINK_MAX: /* Maximum number of links to a file */
- *resultp = 255; /* an unsigned short on the fileserver */
- break; /* a unsigned char in the client.... */
-
- case _PC_NAME_MAX: /* Max length of file name */
- *resultp = 255;
- break;
-
- case _PC_PATH_MAX: /* Maximum length of Path Name */
- *resultp = 1024;
- break;
-
- case _PC_PIPE_BUF: /* Max atomic write to pipe. See fifo_vnops */
- case _PC_CHOWN_RESTRICTED: /* Anybody can chown? */
- case _PC_NO_TRUNC: /* No file name truncation on overflow? */
- u.u_error = EOPNOTSUPP;
- return (EOPNOTSUPP);
- break;
-
- case _PC_MAX_CANON: /* TTY buffer size for canonical input */
- /* need more work here for pty, ite buffer size, if differ */
- if (vp->v_type != VCHR) {
- u.u_error = EINVAL;
- return (EINVAL);
- }
- *resultp = CANBSIZ; /*for tty */
- break;
-
- case _PC_MAX_INPUT:
- /* need more work here for pty, ite buffer size, if differ */
- if (vp->v_type != VCHR) { /* TTY buffer size */
- u.u_error = EINVAL;
- return (EINVAL);
- }
- *resultp = TTYHOG; /*for tty */
- break;
-
- case _PC_VDISABLE:
- /* Terminal special characters can be disabled? */
- if (vp->v_type != VCHR) {
- u.u_error = EINVAL;
- return (EINVAL);
- }
- *resultp = 1;
- break;
-
- case _PC_SYNC_IO:
- if ((vp->v_type != VREG) && (vp->v_type != VBLK)) {
- *resultp = -1;
- return EINVAL;
- }
- *resultp = 1; /* Synchronized IO supported for this file */
- break;
-
- case _PC_FILESIZEBITS:
- if (vp->v_type != VDIR)
- return (EINVAL);
- *resultp = MAX_SMALL_FILE_BITS;
- break;
-
- default:
- return (EINVAL);
- }
-
- 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_file.c,v 1.10 2003/07/15 23:14:23 shadow Exp $");
-
-#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_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct vfs *afs_cacheVfsp;
-
-
-/* As of 6.2, we support either XFS or EFS clients. osi_UFSOpen
- * now vectors to the correct EFS or XFS function. If new functionality is
- * added which accesses the inode, that will also need EFS/XFS variants.
- */
-#ifdef AFS_SGI_EFS_IOPS_ENV
-vnode_t *
-afs_EFSIGetVnode(ino_t ainode)
-{
- struct inode *ip;
- int error;
-
- if ((error = igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, ainode, &ip))) {
- osi_Panic("afs_EFSIGetVnode: igetinode failed, error=%d", error);
- }
- /* We don't care about atimes on the cache files, so disable them. I'm not
- * sure that this is the right place to do this: it should be *after* readi
- * and getattr and stuff.
- */
- ip->i_flags &= ~(ISYN | IACC);
- iunlock(ip);
- return (EFS_ITOV(ip));
-}
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
-vnode_t *
-afs_XFSIGetVnode(ino_t ainode)
-{
- struct xfs_inode *ip;
- int error;
- vnode_t *vp;
-
- if ((error =
- xfs_igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, ainode, &ip))) {
- osi_Panic("afs_XFSIGetVnode: xfs_igetinode failed, error=%d", error);
- }
- vp = XFS_ITOV(ip);
- return vp;
-}
-
-/* Force to 64 bits, even for EFS filesystems. */
-void *
-osi_UFSOpen(ino_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");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- afile->vnode = AFS_SGI_IGETVNODE(ainode);
- AFS_GLOCK();
- afile->size = VnodeToSize(afile->vnode);
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- 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);
- MObtainWriteLock(&afs_xosi, 320);
- AFS_GUNLOCK();
- tvattr.va_mask = AT_SIZE | AT_BLKSIZE | AT_MTIME | AT_ATIME;
- AFS_VOP_GETATTR(afile->vnode, &tvattr, 0, &afs_osi_cred, code);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blocksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-int
-osi_UFSClose(register struct osi_file *afile)
-{
- AFS_STATCNT(osi_Close);
- if (afile->vnode) {
- VN_RELE(afile->vnode);
- }
-
- osi_FreeSmallSpace(afile);
- return 0;
-}
-
-int
-osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- struct vattr tvattr;
- register afs_int32 code;
- struct osi_stat tstat;
- mon_state_t ms;
- 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;
- MObtainWriteLock(&afs_xosi, 321);
- AFS_GUNLOCK();
- tvattr.va_mask = AT_SIZE;
- tvattr.va_size = asize;
- AFS_VOP_SETATTR(afile->vnode, &tvattr, 0, &afs_osi_cred, code);
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-#ifdef AFS_SGI_EFS_IOPS_ENV
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- if (afs_CacheFSType == AFS_SGI_EFS_CACHE) {
- struct inode *ip = EFS_VTOI(avp);
- ip->i_flags &= ~IACC;
- }
-
-}
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- ssize_t 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, 0, 0x7fffffff, &afs_osi_cred, &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
-#ifdef AFS_SGI_EFS_IOPS_ENV
- osi_DisableAtimes(afile->vnode);
-#endif /* AFS_SGI_EFS_IOPS_ENV */
- } 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)
-{
- struct AFS_UCRED *oldCred;
- ssize_t 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;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, 0, 0x7fffffff, &afs_osi_cred,
- &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } else {
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
- 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)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * afsDFS_SetPagInCred (shared with SGI)
- * osi_DFSGetPagFromCred (shared with SGI)
- * Afs_xsetgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_groups.c,v 1.9 2003/07/15 23:14:23 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-
-static int
- afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
-
-static int
- afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
- int change_parent);
-
-
-/* This is common code between SGI's DFS and our AFS. Do *not* alter it's
- * interface or semantics without notifying SGI.
- */
-#ifdef AFS_SGI65_ENV
-/* fixup_pags returns error code if relevant or 0 on no error.
- * Sets up the cred for the call to estgroups. This is pretty convoluted
- * in order to avoid including the private proc.h header file.
- */
-int
-fixup_pags(int **credpp, int ngroups, gid_t * gidset, int old_afs_pag,
- int old_dfs_pag)
-{
- int new_afs_pag = 0;
- int new_dfs_pag = 0;
- int new, old;
- int changed = 0;
- cred_t *cr;
- gid_t groups[NGROUPS_UMAX];
- int code;
-
- if (ngroups < 0 || ngroups > ngroups_max)
- return EINVAL;
-
- if (ngroups) {
- AFS_COPYIN(gidset, groups, ngroups * sizeof(gid_t), code);
- if (code)
- return EFAULT;
- }
-
- if (ngroups >= 2) { /* possibly an AFS PAG */
- new_afs_pag =
- (afs_get_pag_from_groups(groups[0], groups[1]) != NOPAG);
- }
- if (ngroups >= 1) { /* possibly a DFS PAG */
- new_dfs_pag = (int)groups[ngroups - 1];
- if (((new_dfs_pag >> 24) & 0xff) == 'A')
- new_dfs_pag = (int)groups[ngroups - 1];
- else
- new_dfs_pag = 0;
- }
-
- /* Now compute the number of groups we will need. */
- new = ngroups;
- if (old_afs_pag && !new_afs_pag) /* prepend old AFS pag */
- new += 2;
- if (old_dfs_pag && !new_dfs_pag) /* append old DFS pag */
- new++;
-
- if (new > ngroups_max)
- return EINVAL; /* sorry */
-
- cr = crdup(OSI_GET_CURRENT_CRED()); /* we will replace all the groups. */
- memset((char *)&cr->cr_groups, 0, ngroups_max * sizeof(gid_t));
-
- /* Now cobble the new groups list together. */
- new = 0;
- old = 0;
- if (old_afs_pag && !new_afs_pag) { /* prepend old AFS pag */
- gid_t g0, g1;
- changed = 1;
- afs_get_groups_from_pag(old_afs_pag, &g0, &g1);
- cr->cr_groups[new++] = g0;
- cr->cr_groups[new++] = g1;
- }
-
- for (old = 0; old < ngroups; old++)
- cr->cr_groups[new++] = groups[old];
-
- if (old_dfs_pag && !new_dfs_pag) { /* append old DFS pag */
- changed = 1;
- cr->cr_groups[new++] = old_dfs_pag;
- }
-
- /* Now, did we do anything? */
- if (changed) {
- cr->cr_ngroups = new;
- *credpp = cr;
- } else {
- crfree(cr);
- *credpp = NULL;
- }
- return 0;
-}
-#else
-/*
- * Generic routine to set the PAG in the cred for AFS and DFS.
- * If flag = 0 this is a DFS pag held in one group.
- * If flag = 1 this is a AFS pag held in two group entries
- */
-static int
-afsDFS_SetPagInCred(struct ucred *credp, int pag, int flag)
-{
- int *gidset;
- int i, ngrps;
- gid_t g0, g1;
- int n = 0;
- struct ucred *newcredp;
- int groups_taken = (flag ? 2 : 1);
-
- ngrps = credp->cr_ngroups + groups_taken;
- if (ngrps >= ngroups_max)
- return E2BIG;
-
-
- if (flag) {
- /* Break out the AFS pag into two groups */
- afs_get_groups_from_pag(pag, &g0, &g1);
- }
-
- newcredp = crdup(credp);
- newcredp->cr_ngroups = ngrps;
-
- if (flag) {
- /* AFS case */
- newcredp->cr_groups[0] = g0;
- newcredp->cr_groups[1] = g1;
- } else {
- /* DFS case */
- if (PagInCred(newcredp) != NOPAG) {
- /* found an AFS PAG is set in this cred */
- n = 2;
- }
- newcredp->cr_groups[n] = pag;
- }
- for (i = n; i < credp->cr_ngroups; i++)
- newcredp->cr_groups[i + groups_taken] = credp->cr_groups[i];
-
- /* estgroups sets current threads cred from newcredp and crfree's credp */
- estgroups(credp, newcredp);
-
- return 0;
-}
-#endif /* AFS_SGI65_ENV */
-
-/* SGI's osi_GetPagFromCred - They return a long. */
-int
-osi_DFSGetPagFromCred(struct ucred *credp)
-{
- int pag;
- int ngroups;
-
- /*
- * For IRIX, the PAG is stored in the first entry
- * of the gruop list in the cred structure. gid_t's
- * are 32 bits on 64 bit and 32 bit hardware types.
- * As of Irix 6.5, the DFS pag is the last group in the list.
- */
- ngroups = credp->cr_ngroups;
- if (ngroups < 1)
- return NOPAG;
- /*
- * Keep in mind that we might be living with AFS here.
- * This means we don't really know if our DFS PAG is in
- * the first or third group entry.
- */
-#ifdef AFS_SGI65_ENV
- pag = credp->cr_groups[ngroups - 1];
-#else
- pag = credp->cr_groups[0];
- if (PagInCred(credp) != NOPAG) {
- /* AFS has a PAG value in the first two group entries */
- if (ngroups < 3)
- return NOPAG;
- pag = credp->cr_groups[2];
- }
-#endif
- if (((pag >> 24) & 0xff) == 'A')
- return pag;
- else
- return NOPAG;
-}
-
-int
-Afs_xsetgroups(int ngroups, gid_t * gidset)
-{
- int old_afs_pag = NOPAG;
- int old_dfs_pag = NOPAG;
- int code = 0;
- struct ucred *credp = OSI_GET_CURRENT_CRED();
- struct ucred *modcredp;
-
-
- credp = OSI_GET_CURRENT_CRED();
- /* First get any old PAG's */
- old_afs_pag = PagInCred(credp);
- old_dfs_pag = osi_DFSGetPagFromCred(credp);
-
- /* Set the passed in group list. */
- if (code = setgroups(ngroups, gidset))
- return code;
-
-#ifdef AFS_SGI65_ENV
- if (old_afs_pag == NOPAG && old_dfs_pag == NOPAG)
- return 0;
-
- /* Well, we could get the cred, except it's in the proc struct which
- * is not a publicly available header. And the cred won't be valid on
- * the uthread until we return to user space. So, we examine the passed
- * in groups in fixup_pags.
- */
- code =
- fixup_pags(&modcredp, ngroups, gidset,
- (old_afs_pag == NOPAG) ? 0 : old_afs_pag,
- (old_dfs_pag == NOPAG) ? 0 : old_dfs_pag);
- if (!code && modcredp)
- estgroups(OSI_GET_CURRENT_PROCP(), modcredp);
-#else
-
- /*
- * The setgroups gave our curent thread a new cred pointer
- * Get the value again
- */
- credp = OSI_GET_CURRENT_CRED();
- if ((PagInCred(credp) == NOPAG) && (old_afs_pag != NOPAG)) {
- /* reset the AFS PAG */
- code = afsDFS_SetPagInCred(credp, old_afs_pag, 1);
- }
- /*
- * Once again get the credp because the afsDFS_SetPagInCred might have
- * assigned a new one.
- */
- credp = OSI_GET_CURRENT_CRED();
- if ((osi_DFSGetPagFromCred(credp) == NOPAG)
- && (old_dfs_pag != NOPAG)) {
- code = afsDFS_SetPagInCred(credp, old_dfs_pag, 0);
- }
-#endif /* AFS_SGI65_ENV */
- return code;
-}
-
-
-int
-setpag(cred, pagvalue, newpag, change_parent)
- 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) {
-#if defined(KERNEL_HAVE_UERROR)
- return (setuerror(E2BIG), E2BIG);
-#else
- return (E2BIG);
-#endif
- }
- 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]);
- if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
-#if defined(KERNEL_HAVE_UERROR)
- return (setuerror(code), code);
-#else
- return code;
-#endif
- }
- return code;
-}
-
-
-static int
-afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
-{
- int ngrps, savengrps;
- gid_t *gp;
-
- gidset[0] = gidset[1] = 0;
- 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 ucred **cred, int ngroups, gid_t * gidset,
- int change_parent)
-{
- gid_t *gp;
- cred_t *cr, *newcr;
-
- AFS_STATCNT(afs_setgroups);
-
- if (ngroups > ngroups_max)
- return EINVAL;
- cr = *cred;
- if (!change_parent)
- newcr = crdup(cr);
- else
- newcr = cr;
- newcr->cr_ngroups = ngroups;
- gp = newcr->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- if (!change_parent) {
-#ifdef AFS_SGI65_ENV
- estgroups(OSI_GET_CURRENT_PROCP(), newcr);
-#else
- estgroups(cr, newcr);
-#endif
- }
- *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
- */
-
-/*
- * Implementation of Irix IDBG facility for AFS.
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_idbg.c,v 1.6 2003/07/15 23:14:23 shadow Exp $");
-
-#ifdef AFS_SGI62_ENV
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-
-/*
- * debugging routine - invoked by calling kp vnode xx
- */
-static void
-printflags(register unsigned int flags, register char **strings)
-{
- register int mask = 1;
-
- while (flags != 0) {
- if (mask & flags) {
- qprintf("%s ", *strings);
- flags &= ~mask;
- }
- mask <<= 1;
- strings++;
- }
-}
-
-char *tab_vcache[] = {
- "CStatd", /* 1 */
- "CBackup", /* 2 */
- "CRO", /* 4 */
- "CMValid", /* 8 */
- "CCore", /* 0x10 */
- "CDirty", /* 0x20 */
- "CSafeStore", /* 0x40 */
- "CMAPPED", /* 0x80 */
- "CNSHARE", /* 0x100 */
-};
-
-int
-idbg_prafsnode(OSI_VC_DECL(avc))
-{
- OSI_VC_CONVERT(avc)
-
- AFS_GLOCK();
- qprintf(" Len %d DV %d Date %d Own %d Grp %d Mode 0%o Lnk %d\n",
- avc->m.Length, avc->m.DataVersion, avc->m.Date, avc->m.Owner,
- avc->m.Group, avc->m.Mode, avc->m.LinkCount);
- qprintf(" flushDV %d mapDV %d truncpos 0x%x cb 0x%x cbE 0x%x\n",
- avc->flushDV, avc->mapDV, avc->truncPos, avc->callback,
- avc->cbExpires);
- qprintf(" opens %d ex/wr %d flckcnt %d state 0x%x ", avc->opens,
- avc->execsOrWriters, avc->flockCount, avc->states);
- printflags(avc->states, tab_vcache);
- qprintf("\n");
-#ifdef AFS_SGI64_ENV
- qprintf(" mapcnt %llu, mvstat %d anyAcc 0x%x Access 0x%x\n",
- avc->mapcnt, avc->mvstat, avc->anyAccess, avc->Access);
- qprintf(" mvid 0x%x &lock 0x%x cred 0x%x\n", avc->mvid, &avc->lock,
- avc->cred);
- qprintf(" rwlock 0x%x (%d) id %llu trips %d\n", &avc->vc_rwlock,
- valusema(&avc->vc_rwlock), avc->vc_rwlockid, avc->vc_locktrips);
-#else
- qprintf(" mapcnt %d mvstat %d anyAcc 0x%x Access 0x%x\n", avc->mapcnt,
- avc->mvstat, avc->anyAccess, avc->Access);
- qprintf(" mvid 0x%x &lock 0x%x cred 0x%x\n", avc->mvid, &avc->lock,
- avc->cred);
- qprintf(" rwlock 0x%x (%d) id %d trips %d\n", &avc->vc_rwlock,
- valusema(&avc->vc_rwlock), avc->vc_rwlockid, avc->vc_locktrips);
-#endif
- AFS_GUNLOCK();
- return 0;
-}
-
-extern struct afs_q VLRU; /*vcache LRU */
-static char *tab_vtypes[] = {
- "VNON",
- "VREG",
- "VDIR",
- "VBLK",
- "VCHR",
- "VLNK",
- "VFIFO",
- "VXNAM",
- "VBAD",
- "VSOCK",
- 0
-};
-
-int
-idbg_afsvfslist()
-{
- struct vcache *tvc;
- register struct afs_q *tq;
- struct afs_q *uq;
- afs_int32 nodeid; /* what ls prints as 'inode' */
-
- AFS_GLOCK();
- for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
- nodeid = tvc->fid.Fid.Vnode + (tvc->fid.Fid.Volume << 16);
- nodeid &= 0x7fffffff;
- qprintf("avp 0x%x type %s cnt %d pg %d map %d nodeid %d(0x%x)\n", tvc,
- tab_vtypes[((vnode_t *) tvc)->v_type],
- ((vnode_t *) tvc)->v_count,
- (int)VN_GET_PGCNT((vnode_t *) tvc), (int)tvc->mapcnt, nodeid,
- nodeid);
- }
- AFS_GUNLOCK();
- return 0;
-}
-
-static char *tab_userstates[] = {
- "UHasTokens",
- "UTokensBad",
- "UPrimary",
- "UNeedsReset",
- "UPAGcounted",
- "UNK",
-};
-
-static void
-idbg_pruser(struct unixuser *tu)
-{
- qprintf("@0x%x nxt 0x%x uid %d (0x%x) cell 0x%x vid 0x%x ref %d\n", tu,
- tu->next, tu->uid, tu->uid, tu->cell, tu->vid, tu->refCount);
- qprintf("time %d stLen %d stp 0x%x exp 0x%x ", tu->tokenTime, tu->stLen,
- tu->stp, tu->exporter);
- printflags(tu->states, tab_userstates);
- qprintf("\n");
- qprintf("ClearToken: handle 0x%x ViceID 0x%x Btime %d Etime %d\n",
- tu->ct.AuthHandle, tu->ct.ViceId, tu->ct.BeginTimestamp,
- tu->ct.EndTimestamp);
-}
-
-extern struct unixuser *afs_users[NUSERS];
-int
-idbg_afsuser(void *x)
-{
- struct unixuser *tu;
- int i;
- AFS_GLOCK();
-
- if (x == (void *)-1L) {
- for (i = 0; i < NUSERS; i++)
- for (tu = afs_users[i]; tu; tu = tu->next)
- idbg_pruser(tu);
- } else
- idbg_pruser((struct unixuser *)x);
-
- AFS_GUNLOCK();
- return 0;
-}
-
-#endif /* AFS_SGI62_ENV */
+++ /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
- */
-
-/*
- * IRIX inode operations
- *
- * Implements:
- * afsdptoip
- * afsiptodp
- * afsidestroy
- * getinode
- * igetinode
- * xfs_getinode
- * xfs_igetinode
- * icreate
- * afs_syscall_icreate
- * xfs_icreatename64
- * afs_syscall_icreatename64
- * iopenargs64
- * afs_syscall_iopen
- * iopen
- * iopen64
- * efs_iincdec
- * xfs_iincdec64
- * iincdec64
- * afs_syscall_idec64
- * afs_syscall_iinc64
- * iincdec
- * iinc
- * idec
- * afs_syscall_iincdec
- * afs_syscall_ilistinode64
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_inode.c,v 1.11 2003/07/15 23:14:23 shadow Exp $");
-
-#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 */
-
-#define BAD_IGET -1000
-
-/*
- * SGI dependent system calls
- */
-#ifndef INODESPECIAL
-/*
- * `INODESPECIAL' type inodes are ones that describe volumes.
- */
-#define INODESPECIAL 0xffffffff /* ... from ../vol/viceinode.h */
-#endif
-/*
- * copy disk inode to incore inode and vice-versa
- */
-void
-afsdptoip(struct efs_dinode *dp, struct inode *ip)
-{
- struct afsparms *ap;
-
- ip->i_afs = kmem_alloc(sizeof(struct afsparms), KM_SLEEP);
- osi_Assert(ip->i_version == EFS_IVER_AFSSPEC
- || ip->i_version == EFS_IVER_AFSINO);
- ap = (struct afsparms *)ip->i_afs;
- /* vicep1 is VOLid */
- ap->vicep1 =
- dmag(dp, 0) << 24 | dmag(dp, 1) << 16 | dmag(dp, 2) << 8 | dmag(dp,
- 3) <<
- 0;
-
- if (ip->i_version == EFS_IVER_AFSSPEC) {
- ap->vicep3 = dmag(dp, 8); /* Type */
- ap->vicep4 =
- dmag(dp, 4) << 24 | dmag(dp, 5) << 16 | dmag(dp,
- 6) << 8 | dmag(dp,
- 7) <<
- 0;
-
- } else {
- /* vnode number */
- ap->vicep2 = dmag(dp, 4) << 16 | dmag(dp, 5) << 8 | dmag(dp, 6) << 0;
- /* disk uniqifier */
- ap->vicep3 = dmag(dp, 7) << 16 | dmag(dp, 8) << 8 | dmag(dp, 9) << 0;
- /* data version */
- ap->vicep4 = dmag(dp, 10) << 16 | dmag(dp, 11) << 8 | (dp)->di_spare;
- }
-}
-
-void
-afsiptodp(struct inode *ip, struct efs_dinode *dp)
-{
- struct afsparms *ap;
-
- if (ip->i_afs == NULL)
- return;
-
- osi_Assert(ip->i_version == EFS_IVER_AFSSPEC
- || ip->i_version == EFS_IVER_AFSINO);
- ap = (struct afsparms *)ip->i_afs;
- /* vicep1 is VOLid */
- dmag(dp, 0) = ap->vicep1 >> 24;
- dmag(dp, 1) = ap->vicep1 >> 16;
- dmag(dp, 2) = ap->vicep1 >> 8;
- dmag(dp, 3) = ap->vicep1 >> 0;
-
- if (ip->i_version == EFS_IVER_AFSSPEC) {
- /* Type */
- dmag(dp, 8) = ap->vicep3;
- /* ParentId */
- dmag(dp, 4) = ap->vicep4 >> 24;
- dmag(dp, 5) = ap->vicep4 >> 16;
- dmag(dp, 6) = ap->vicep4 >> 8;
- dmag(dp, 7) = ap->vicep4 >> 0;
- } else {
- /* vnode number */
- dmag(dp, 4) = ap->vicep2 >> 16;
- dmag(dp, 5) = ap->vicep2 >> 8;
- dmag(dp, 6) = ap->vicep2 >> 0;
- /* disk uniqifier */
- dmag(dp, 7) = ap->vicep3 >> 16;
- dmag(dp, 8) = ap->vicep3 >> 8;
- dmag(dp, 9) = ap->vicep3 >> 0;
- /* data version */
- dmag(dp, 10) = ap->vicep4 >> 16;
- dmag(dp, 11) = ap->vicep4 >> 8;
- dp->di_spare = ap->vicep4 >> 0;
- }
-}
-
-void
-afsidestroy(struct inode *ip)
-{
- if (ip->i_afs) {
- kmem_free(ip->i_afs, sizeof(struct afsparms));
- ip->i_afs = NULL;
- }
-}
-
-extern int efs_fstype;
-#ifdef AFS_SGI_XFS_IOPS_ENV
-extern int xfs_fstype;
-#endif
-
-int
-getinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct inode **ipp)
-{
- struct inode *ip;
- int error;
-
- if (!vfsp) {
-#ifdef AFS_SGI65_ENV
- vfsp = vfs_devsearch(dev, efs_fstype);
-#else
- vfsp = vfs_devsearch(dev);
-#endif
- if (!vfsp) {
- return ENXIO;
- }
- }
-#ifndef AFS_SGI65_ENV
- if (vfsp->vfs_fstype != efs_fstype)
- return ENOSYS;
-#endif
-
- if (error =
- iget((((struct mount *)((vfsp)->vfs_bh.bh_first)->bd_pdata)),
- (unsigned int)(inode & 0xffffffff), &ip)) {
- return error;
- }
- *ipp = ip;
- return 0;
-}
-
-int
-igetinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct inode **ipp)
-{
- struct inode *ip;
- int error;
-
- AFS_STATCNT(igetinode);
- if (error = getinode(vfsp, dev, inode, &ip))
- return error;
- *ipp = ip;
- return 0;
-}
-
-int XFS_IGET_EPOS;
-ino_t XFS_IGET_INO;
-dev_t XFS_IGET_DEV;
-#define SET_XFS_ERROR(POS, DEV, INO) \
- XFS_IGET_EPOS = (POS), XFS_IGET_DEV = (DEV), XFS_IGET_INO = (INO)
-
-int
-xfs_getinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct xfs_inode **ipp)
-{
- struct xfs_inode *ip;
- int error;
-
- if (!vfsp) {
-#ifdef AFS_SGI65_ENV
- vfsp = vfs_devsearch(dev, xfs_fstype);
-#else
- vfsp = vfs_devsearch(dev);
-#endif
- if (!vfsp) {
- SET_XFS_ERROR(1, dev, inode);
- return ENXIO;
- }
- }
-#ifndef AFS_SGI65_ENV
- if (vfsp->vfs_fstype != xfs_fstype) {
- SET_XFS_ERROR(2, vfsp->vfs_dev, inode);
- return ENOSYS;
- }
-#endif
-
- if (error = xfs_iget((((struct mount *)
- ((vfsp)->vfs_bh.bh_first)->bd_pdata)), (void *)0,
- (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
- (daddr_t) 0)) {
- SET_XFS_ERROR(3, vfsp->vfs_dev, inode);
- return error;
- }
-
- *ipp = ip;
- return 0;
-}
-
-/* xfs_igetinode now returns an unlocked inode. This is fine, since we
- * have a refcount on the holding vnode.
- */
-int
-xfs_igetinode(struct vfs *vfsp, dev_t dev, ino_t inode,
- struct xfs_inode **ipp)
-{
- struct xfs_inode *ip;
- vnode_t *vp;
- vattr_t vattr;
- int error;
-
- AFS_STATCNT(igetinode);
-
- *ipp = NULL;
- if (error = xfs_getinode(vfsp, dev, inode, &ip)) {
- return error;
- }
-
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
- vp = XFS_ITOV(ip);
- vattr.va_mask = AT_STAT;
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), error);
- if (error) {
- SET_XFS_ERROR(4, vp->v_vfsp->vfs_dev, inode);
- VN_RELE(vp);
- return error;
- }
- if (vattr.va_nlink == 0 || vattr.va_type != VREG) {
- SET_XFS_ERROR(5, vp->v_vfsp->vfs_dev, inode);
- VN_RELE(vp);
- return ENOENT;
- }
-
- *ipp = ip;
- return 0;
-}
-
-/**************************************************************************
- * inode creation routines.
- *
- ***************************************************************************/
-struct icreateargs {
- sysarg_t dev;
- sysarg_t near_inode;
- sysarg_t param1;
- sysarg_t param2;
- sysarg_t param3;
- sysarg_t param4;
-};
-
-/* EFS only fs suite uses this entry point - icreate in afssyscalls.c. */
-int
-icreate(struct icreateargs *uap, rval_t * rvp)
-{
-#ifdef AFS_SGI_EFS_IOPS_ENV
- AFS_STATCNT(icreate);
- return (afs_syscall_icreate
- (uap->dev, uap->near_inode, uap->param1, uap->param2, uap->param3,
- uap->param4, rvp));
-#else
- return ENOSYS;
-#endif
-}
-
-#ifdef AFS_SGI_EFS_IOPS_ENV
-int
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp)
- afs_uint32 dev, near_inode, param1, param2, param3, param4;
- rval_t *rvp;
-{
- struct inode *ip, *newip;
- struct afsparms *ap;
- struct cred cr;
- int error;
-
- AFS_STATCNT(afs_syscall_icreate);
- if (!afs_suser())
- return EPERM;
-
- if (error = getinode(0, (dev_t) dev, 2, &ip))
- return error;
-
- cr.cr_uid = 0;
- cr.cr_gid = -2;
- if (error = efs_ialloc(ip, IFREG, 1, NODEV, &newip, &cr)) {
- iput(ip);
- return error;
- }
- iput(ip);
- osi_Assert(newip);
- newip->i_flags |= IACC | IUPD | ICHG;
-
- osi_Assert(newip->i_afs == NULL);
- newip->i_afs = kmem_alloc(sizeof(struct afsparms), KM_SLEEP);
- if (param2 == INODESPECIAL)
- newip->i_version = EFS_IVER_AFSSPEC;
- else
- newip->i_version = EFS_IVER_AFSINO;
- ap = (struct afsparms *)newip->i_afs;
- ap->vicep1 = param1; /* VOLid */
- ap->vicep2 = param2; /* Vnode # */
- ap->vicep3 = param3; /* SPEC:type INO:vnode uniq */
- ap->vicep4 = param4; /* SPEC:parentId INO:data version */
- rvp->r_val1 = newip->i_number;
- iput(newip);
- return 0;
-}
-#else /* !AFS_SGI_EFS_IOPS_ENV */
-int
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp)
- afs_uint32 dev, near_inode, param1, param2, param3, param4;
- rval_t *rvp;
-{
- return ENOSYS;
-}
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
-#ifdef AFS_SGI_XFS_IOPS_ENV
-/* inode creation routines for icreatename64 entry point. Use for EFS/XFS
- * fileserver suite. For XFS, create a name in the namespace as well as the
- * inode. For EFS, just call the original routine.
- */
-
-#include <afs/xfsattrs.h>
-#include <sys/attributes.h>
-
-extern char *int_to_base64(char *, int);
-
-/* Lock against races creating/removing directory - vos zap RO, vos create RW*/
-kmutex_t afs_vol_create_lock;
-int afs_vol_create_lock_inited = 0;
-#define AFS_LOCK_VOL_CREATE() { \
- if (!afs_vol_create_lock_inited) { \
- mutex_init(&afs_vol_create_lock, MUTEX_DEFAULT, \
- "afs_vol_create_lock"); \
- afs_vol_create_lock_inited = 1; \
- } \
- mutex_enter(&afs_vol_create_lock); \
- }
-#define AFS_UNLOCK_VOL_CREATE() mutex_exit(&afs_vol_create_lock)
-
-
-/* xfs_icreatename64
- * Create an AFS inode in the XFS name space. If required create the proper
- * containing directory. See sys/xfsattrs.h for the details on the naming
- * conventions and the usage of file and directory attributes.
- *
- * The inode parameters are stored in an XFS attribute called "AFS". In
- * addition gid is set to XFS_VICEMAGIC and uid is set to the low 31 bits
- * of the RW volume id. This is so inode verification in iinc and idec
- * don't need to get the attribute. Note that only the low 31 bits are set.
- * This is because chmod only accepts up to MAX_UID and chmod is used
- * to correct these values in xfs_ListViceInodes.
- */
-int
-xfs_icreatename64(struct vfs *vfsp, int datap, int datalen,
- afs_inode_params_t params, ino_t * inop)
-{
-#define AFS_PNAME_SIZE 16
- char path[64];
- char name[64];
- b64_string_t stmp1, stmp2;
- afs_xfs_attr_t attrs;
- struct vattr vattr;
- int name_version = AFS_XFS_NAME_VERS;
- int code = 0, unused;
- struct vnode *vp;
- struct vnode *dvp;
- int rw_vno; /* volume ID of parent volume */
- int i;
- int createdDir = 0;
- size_t junk;
- char *s;
-
-
- /* Get vnode for directory which will contain new inode. */
- if (datalen >= AFS_PNAME_SIZE)
- return E2BIG;
-
- AFS_COPYINSTR((char *)datap, path, AFS_PNAME_SIZE - 1, &junk, unused);
- if (*path != '/') {
- return EINVAL;
- }
-
- rw_vno = (params[1] == INODESPECIAL) ? params[3] : params[0];
-
- /* directory name */
- strcat(path, "/");
- strcat(path, AFS_INODE_DIR_NAME);
- strcat(path, int_to_base64(stmp1, rw_vno));
-
- if (params[1] == INODESPECIAL)
- AFS_LOCK_VOL_CREATE();
-
- code = gop_lookupname(path, AFS_UIOSYS, FOLLOW, NULL, &dvp);
- if (code == ENOENT) {
- /* Maybe it's an old directory name format. */
- AFS_COPYINSTR((char *)datap, name, AFS_PNAME_SIZE - 1, &junk, unused);
- strcat(name, "/.");
- strcat(name, int_to_base64(stmp1, rw_vno));
- code = gop_lookupname(name, AFS_UIOSYS, FOLLOW, NULL, &dvp);
- if (!code) {
- /* Use old name format. */
- strcpy(path, name);
- name_version = AFS_XFS_NAME_VERS1;
- }
- }
-
- if (code == ENOENT) {
- afs_xfs_dattr_t dattr;
- /* make directory. */
-
- code =
- AFS_VN_OPEN(path, UIO_SYSSPACE, FCREAT | FEXCL, 0700, &dvp,
- CRMKDIR);
- if (code) {
- if (code == EEXIST) {
- /* someone beat us to it? */
- code = gop_lookupname(path, AFS_UIOSYS, 0, NULL, &dvp);
- }
- if (code) {
- AFS_UNLOCK_VOL_CREATE();
- return code;
- }
- } else
- createdDir = 1;
- memset((char *)&dattr, 0, sizeof(dattr));
- dattr.atd_version = AFS_XFS_ATD_VERS;
- dattr.atd_volume = rw_vno;
- AFS_VOP_ATTR_SET(dvp, AFS_XFS_DATTR, (char *)&dattr,
- SIZEOF_XFS_DATTR_T, ATTR_ROOT | ATTR_CREATE,
- OSI_GET_CURRENT_CRED(), code);
- if (code) {
- VN_RELE(dvp);
- if (createdDir)
- (void)vn_remove(path, UIO_SYSSPACE, RMDIRECTORY);
- AFS_UNLOCK_VOL_CREATE();
- return code;
- }
- }
-
- vattr.va_mask = AT_FSID | AT_NODEID; /* gets a guick return using FSID */
- AFS_VOP_GETATTR(dvp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- if (code) {
- VN_RELE(dvp);
- return code;
- }
-
- memset((char *)&attrs, 0, sizeof(attrs));
- attrs.at_pino = vattr.va_nodeid;
- VN_RELE(dvp);
-
- /* Create the desired file. Use up to ten tries to create a unique name. */
- (void)strcpy(name, path);
- (void)strcat(name, "/.");
- (void)strcat(name, int_to_base64(stmp2, params[2]));
- s = &name[strlen(name)];
-
- attrs.at_tag = 0; /* Initial guess at a unique tag. */
- for (i = 0; i < 10; i++) {
- *s = '\0';
- strcat(s, ".");
- strcat(s, int_to_base64(stmp1, attrs.at_tag));
- code =
- AFS_VN_OPEN(name, UIO_SYSSPACE, FCREAT | FEXCL, 0600, &vp,
- CRCREAT);
- if (!code || code != EEXIST)
- break;
-
- attrs.at_tag++;
- }
- /* Unlock the creation process since the directory now has a file in it. */
- if (params[1] == INODESPECIAL)
- AFS_UNLOCK_VOL_CREATE();
-
- if (!code) {
- /* Set attributes. */
- memcpy((char *)attrs.at_param, (char *)params,
- sizeof(afs_inode_params_t));
- attrs.at_attr_version = AFS_XFS_ATTR_VERS;
- attrs.at_name_version = name_version;
- AFS_VOP_ATTR_SET(vp, AFS_XFS_ATTR, (char *)&attrs, SIZEOF_XFS_ATTR_T,
- ATTR_ROOT | ATTR_CREATE, OSI_GET_CURRENT_CRED(),
- code);
- if (!code) {
- vattr.va_mode = 1;
- vattr.va_uid = AFS_XFS_VNO_CLIP(params[0]);
- vattr.va_gid = XFS_VICEMAGIC;
- vattr.va_mask = AT_MODE | AT_UID | AT_GID;
- AFS_VOP_SETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- }
- if (!code) {
- vattr.va_mask = AT_NODEID;
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- }
- if (!code)
- *inop = vattr.va_nodeid;
- VN_RELE(vp);
- }
-
- if (code) {
- /* remove partially created file. */
- (void)vn_remove(name, UIO_SYSSPACE, RMFILE);
-
- /* and directory if volume special file. */
- if (createdDir) {
- AFS_LOCK_VOL_CREATE();
- (void)vn_remove(path, UIO_SYSSPACE, RMDIRECTORY);
- AFS_UNLOCK_VOL_CREATE();
- }
- }
- return code;
-}
-
-/* afs_syscall_icreatename64
- * This is the icreatename64 entry point used by the combined EFS/XFS
- * fileserver suite. The datap and datalen do not need to be set for EFS.
- */
-int
-afs_syscall_icreatename64(int dev, int datap, int datalen, int paramp,
- int inop)
-{
- struct vfs *vfsp;
- afs_inode_params_t param;
- int code;
- rval_t rval;
- ino_t ino;
-
-
- if (!afs_suser())
- return EPERM;
-
-#ifdef AFS_SGI65_ENV
- vfsp = vfs_devsearch(dev, VFS_FSTYPE_ANY);
-#else
- vfsp = vfs_devsearch(dev);
-#endif
- if (vfsp == NULL) {
- return ENXIO;
- }
-
- AFS_COPYIN((char *)paramp, (char *)param, sizeof(afs_inode_params_t),
- code);
- if (vfsp->vfs_fstype == xfs_fstype) {
- code = xfs_icreatename64(vfsp, datap, datalen, param, &ino);
- if (code)
- return code;
- else {
- AFS_COPYOUT((char *)&ino, (char *)inop, sizeof(ino_t), code);
- return code;
- }
- } else if (vfsp->vfs_fstype == efs_fstype) {
- code =
- afs_syscall_icreate(dev, 0, param[0], param[1], param[2],
- param[3], &rval);
- if (code)
- return code;
- else {
- ino = (ino_t) rval.r_val1;
- AFS_COPYOUT((char *)&ino, (char *)inop, sizeof(ino_t), code);
- return code;
- }
- }
- return ENXIO;
-}
-#endif /* AFS_SGI_XFS_IOPS_ENV */
-
-/*
- * iopen system calls -- open an inode for reading/writing
- * Restricted to super user.
- * Any IFREG files.
- * The original EFS only system calls are still present in the kernel for
- * in case a kernel upgrade is done for a fix, but the EFS fileserver is
- * still in use.
- */
-struct iopenargs {
- sysarg_t dev;
- sysarg_t inode;
- sysarg_t usrmod;
-};
-
-#ifdef AFS_SGI_XFS_IOPS_ENV
-struct iopenargs64 {
- sysarg_t dev;
- sysarg_t inode_hi;
- sysarg_t inode_lo;
- sysarg_t usrmod;
-};
-
-#ifdef AFS_SGI65_ENV
-int
-afs_syscall_iopen(int dev, ino_t inode, int usrmod, rval_t * rvp)
-{
- struct file *fp;
- int fd;
- int error;
- struct vfs *vfsp;
- struct vnode *vp;
-
- AFS_STATCNT(afs_syscall_iopen);
- if (!afs_suser())
- return EPERM;
- vfsp = vfs_devsearch(dev, xfs_fstype);
- if (!vfsp)
- vfsp = vfs_devsearch(dev, efs_fstype);
- if (!vfsp)
- return ENXIO;
-
-#ifdef AFS_SGI_EFS_IOPS_ENV
- if (vfsp->vfs_fstype == efs_fstype) {
- struct inode *ip;
- if (error = igetinode(vfsp, (dev_t) dev, inode, &ip))
- return error;
- vp = EFS_ITOV(ip);
- if (error = vfile_alloc((usrmod + 1) & (FMASK), &fp, &fd)) {
- iput(ip);
- return error;
- }
- iunlock(ip);
- } else
-#endif /* AFS_SGI_EFS_IOPS_ENV */
- if (vfsp->vfs_fstype == xfs_fstype) {
- struct xfs_inode *xip;
- if (error = xfs_igetinode(vfsp, (dev_t) dev, inode, &xip))
- return error;
- vp = XFS_ITOV(xip);
- if (error = vfile_alloc((usrmod + 1) & (FMASK), &fp, &fd)) {
- VN_RELE(vp);
- return error;
- }
- } else {
- osi_Panic("afs_syscall_iopen: bad fstype = %d\n", vfsp->vfs_fstype);
- }
- vfile_ready(fp, vp);
- rvp->r_val1 = fd;
- return 0;
-}
-#else
-/* afs_syscall_iopen
- * EFS/XFS version vectors to correct code based vfs_fstype. Expects a
- * 64 bit inode number.
- */
-int
-afs_syscall_iopen(int dev, ino_t inode, int usrmod, rval_t * rvp)
-{
- struct file *fp;
- int fd;
- int error;
- struct vfs *vfsp;
-
- AFS_STATCNT(afs_syscall_iopen);
- if (!afs_suser())
- return EPERM;
- vfsp = vfs_devsearch(dev);
- if (!vfsp) {
- return ENXIO;
- }
-
- if (vfsp->vfs_fstype == xfs_fstype) {
- struct xfs_inode *xip;
- struct vnode *vp;
- if (error = xfs_igetinode(vfsp, (dev_t) dev, inode, &xip))
- return error;
- vp = XFS_ITOV(xip);
- if (error = falloc(vp, (usrmod + 1) & (FMASK), &fp, &fd)) {
- VN_RELE(vp);
- return error;
- }
- } else if (vfsp->vfs_fstype == efs_fstype) {
- struct inode *ip;
- if (error = igetinode(vfsp, (dev_t) dev, inode, &ip))
- return error;
- if (error = falloc(EFS_ITOV(ip), (usrmod + 1) & (FMASK), &fp, &fd)) {
- iput(ip);
- return error;
- }
- iunlock(ip);
- } else {
- osi_Panic("afs_syscall_iopen: bad fstype = %d\n", vfsp->vfs_fstype);
- }
- fready(fp);
- rvp->r_val1 = fd;
- return 0;
-}
-#endif /* AFS_SGI65_ENV */
-
-int
-iopen(struct iopenargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(iopen);
- return (afs_syscall_iopen
- (uap->dev, (ino_t) uap->inode, uap->usrmod, rvp));
-}
-
-int
-iopen64(struct iopenargs64 *uap, rval_t * rvp)
-{
- AFS_STATCNT(iopen);
- return (afs_syscall_iopen
- (uap->dev, (ino_t) ((uap->inode_hi << 32) | uap->inode_lo),
- uap->usrmod, rvp));
-}
-
-#else /* AFS_SGI_XFS_IOPS_ENV */
-/* iopen/afs_syscall_iopen
- *
- * Original EFS only 32 bit iopen call.
- */
-int
-iopen(struct iopenargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(iopen);
- return (afs_syscall_iopen(uap->dev, uap->inode, uap->usrmod, rvp));
-}
-
-int
-afs_syscall_iopen(dev, inode, usrmod, rvp)
- int dev, inode, usrmod;
- rval_t *rvp;
-{
- struct file *fp;
- struct inode *ip;
- int fd;
- int error;
-
- AFS_STATCNT(afs_syscall_iopen);
- if (!afs_suser())
- return EPERM;
- if (error = igetinode(0, (dev_t) dev, inode, &ip))
- return error;
- if (error = falloc(EFS_ITOV(ip), (usrmod + 1) & (FMASK), &fp, &fd)) {
- iput(ip);
- return error;
- }
- iunlock(ip);
- rvp->r_val1 = fd;
-#ifdef AFS_SGI53_ENV
- fready(fp);
-#endif
- return 0;
-}
-#endif /* AFS_SGI_XFS_IOPS_ENV */
-
-/*
- * Support for iinc() and idec() system calls--increment or decrement
- * count on inode.
- * Restricted to super user.
- * Only VICEMAGIC type inodes.
- */
-#ifdef AFS_SGI_XFS_IOPS_ENV
-#ifdef AFS_SGI_EFS_IOPS_ENV
-/* efs_iincdec
- *
- * XFS/EFS iinc/idec code for EFS. Uses 32 bit inode numbers.
- */
-static int
-efs_iincdec(vfsp, inode, inode_p1, amount)
- struct vfs *vfsp;
- int inode, inode_p1, amount;
-{
- struct inode *ip;
- int error;
-
- if (error = igetinode(vfsp, NULL, inode, &ip))
- return error;
-
- if (!IS_VICEMAGIC(ip))
- error = EPERM;
- else if (((struct afsparms *)ip->i_afs)->vicep1 != inode_p1)
- error = ENXIO;
- else {
- ip->i_nlink += amount;
- osi_Assert(ip->i_nlink >= 0);
- if (ip->i_nlink == 0) {
- CLEAR_VICEMAGIC(ip);
- afsidestroy(ip);
- }
- ip->i_flags |= ICHG;
- }
- /* XXX sync write?? */
- iput(ip);
- return error;
-}
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
-/* xfs_iincdec
- *
- * XFS/EFS iinc/idec code for EFS. Uses 64 bit inode numbers.
- */
-static int
-xfs_iincdec64(struct vfs *vfsp, ino_t inode, int inode_p1, int amount)
-{
- vnode_t *vp;
- xfs_inode_t *ip;
- int code = 0;
- afs_xfs_attr_t attrs;
- int length = SIZEOF_XFS_ATTR_T;
- afs_xfs_dattr_t dattr;
- struct vattr vattr;
- int nlink;
- int vol;
-
- code =
- xfs_iget((((struct mount *)((vfsp)->vfs_bh.bh_first)->bd_pdata)),
- (void *)0, (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
- (daddr_t) 0);
- if (code)
- return code;
-
- vp = XFS_ITOV(ip);
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
- vattr.va_mask = AT_GID | AT_UID | AT_MODE;
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- if (code)
- code = EPERM;
-
- if (!code && (vattr.va_gid != XFS_VICEMAGIC))
- code = EPERM;
-
- if (!code && (AFS_XFS_VNO_CLIP(inode_p1) != vattr.va_uid))
- code = ENXIO;
-
- if (code) {
- VN_RELE(vp);
- return code;
- }
-
- nlink = vattr.va_mode & AFS_XFS_MODE_LINK_MASK;
- nlink += amount;
- if (nlink > 07) {
- code = EOVERFLOW;
- }
- if (nlink > 0) {
- vattr.va_mode &= ~AFS_XFS_MODE_LINK_MASK;
- vattr.va_mode |= nlink;
- vattr.va_mask = AT_MODE;
- AFS_VOP_SETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- VN_RELE(vp);
- return code;
- } else {
- char path[64];
- b64_string_t stmp1, stmp2;
- vnode_t *dvp;
- xfs_inode_t *ip;
-
- length = SIZEOF_XFS_ATTR_T;
- AFS_VOP_ATTR_GET(vp, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT,
- OSI_GET_CURRENT_CRED(), code);
- VN_RELE(vp);
- if (!code) {
- if (length != SIZEOF_XFS_ATTR_T
- || attrs.at_attr_version != AFS_XFS_ATTR_VERS)
- return EINVAL;
- }
- /* Get the vnode for the directory this file is in. */
- if (!attrs.at_pino)
- return ENOENT;
-
- code = xfs_getinode(vp->v_vfsp, NULL, attrs.at_pino, &ip);
- if (code)
- return code;
-
- dvp = XFS_ITOV(ip);
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
- /* Verify directory attributes. */
- length = SIZEOF_XFS_DATTR_T;
- AFS_VOP_ATTR_GET(dvp, AFS_XFS_DATTR, (char *)&dattr, &length,
- ATTR_ROOT, OSI_GET_CURRENT_CRED(), code);
- if (!code) {
- if (length != SIZEOF_XFS_DATTR_T
- || dattr.atd_version != AFS_XFS_ATD_VERS)
- code = ENXIO;
- }
- if (code) {
- VN_RELE(dvp);
- return code;
- }
-
- strcpy(path, ".");
- strcat(path, int_to_base64(stmp1, attrs.at_param[2]));
- strcat(path, ".");
- strcat(path, int_to_base64(stmp1, attrs.at_tag));
-
- AFS_VOP_REMOVE(dvp, path, OSI_GET_CURRENT_CRED(), code);
-
- if (!code) {
- int code2;
- vattr.va_mask = AT_NLINK;
- AFS_VOP_GETATTR(dvp, &vattr, 0, OSI_GET_CURRENT_CRED(), code2);
- if (!code2) {
- if (vattr.va_nlink == 2) {
- vnode_t *ddvp; /* parent of volume directory. */
- /* Try to remove the directory if this is a volume
- * special file. It's ok to fail.
- */
- AFS_VOP_LOOKUP(dvp, "..", &ddvp, (struct pathname *)NULL,
- 0, OSI_GET_CURRENT_RDIR(),
- OSI_GET_CURRENT_CRED(), code2);
- if (!code2) {
- VN_RELE(dvp);
- dvp = (vnode_t *) 0;
- strcpy(path, ".");
- if (attrs.at_name_version == AFS_XFS_NAME_VERS2)
- strcpy(path, AFS_INODE_DIR_NAME);
- else
- strcpy(path, ".");
- int_to_base64(stmp1,
- (attrs.at_param[1] ==
- INODESPECIAL) ? attrs.
- at_param[3] : attrs.at_param[0]);
- strcat(path, stmp1);
- AFS_LOCK_VOL_CREATE();
- AFS_VOP_RMDIR(ddvp, path, OSI_GET_CURRENT_CDIR(),
- OSI_GET_CURRENT_CRED(), code2);
- AFS_UNLOCK_VOL_CREATE();
- VN_RELE(ddvp);
- }
- }
- }
- }
- if (dvp)
- VN_RELE(dvp);
- }
- return code;
-}
-
-int
-iincdec64(int dev, int inode_hi, int inode_lo, int inode_p1, int amount)
-{
- struct vfs *vfsp;
-
- if (!afs_suser())
- return EPERM;
-#ifdef AFS_SGI65_ENV
- vfsp = vfs_devsearch(dev, VFS_FSTYPE_ANY);
-#else
- vfsp = vfs_devsearch(dev);
-#endif
- if (!vfsp) {
- return ENXIO;
- }
-
- if (vfsp->vfs_fstype == xfs_fstype) {
- ino_t inode;
- inode = inode_hi;
- inode <<= 32;
- inode |= inode_lo;
- return xfs_iincdec64(vfsp, inode, inode_p1, amount);
- }
-#ifdef AFS_SGI_EFS_IOPS_ENV
- else if (vfsp->vfs_fstype == efs_fstype) {
- return efs_iincdec(vfsp, inode_lo, inode_p1, amount);
- }
-#endif /* AFS_SGI_EFS_IOPS_ENV */
- return ENXIO;
-}
-
-int
-afs_syscall_idec64(int dev, int inode_hi, int inode_lo, int inode_p1)
-{
- return iincdec64(dev, inode_hi, inode_lo, inode_p1, -1);
-}
-
-int
-afs_syscall_iinc64(int dev, int inode_hi, int inode_lo, int inode_p1)
-{
- return iincdec64(dev, inode_hi, inode_lo, inode_p1, 1);
-}
-
-
-
-
-struct iincargs {
- sysarg_t dev;
- sysarg_t inode;
- sysarg_t inode_p1;
-};
-
-#ifdef AFS_SGI65_ENV
-int
-iinc(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(iinc);
- return ENOTSUP;
-}
-
-int
-idec(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(idec);
- return ENOTSUP;
-}
-#else
-/* iincdec
- *
- * XFS/EFS iinc/idec entry points for EFS only fileservers.
- *
- */
-int
-iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- struct vfs *vfsp;
-
- if (!afs_suser())
- return EPERM;
- vfsp = vfs_devsearch(dev);
- if (!vfsp) {
- return ENXIO;
- }
- if (vfsp->vfs_fstype != efs_fstype)
- return ENOSYS;
-
- return efs_iincdec(vfsp, inode, inode_p1, amount);
-}
-
-int
-iinc(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(iinc);
- return (iincdec(uap->dev, uap->inode, uap->inode_p1, 1));
-}
-
-int
-idec(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(idec);
- return (iincdec(uap->dev, uap->inode, uap->inode_p1, -1));
-}
-#endif /* AFS_SGI65_ENV */
-
-#else /* AFS_SGI_XFS_IOPS_ENV */
-/* afs_syscall_iincdec iinc idec
- *
- * These are the original EFS only entry points.
- */
-int
-afs_syscall_iincdec(dev, inode, inode_p1, amount)
- int dev, inode, inode_p1, amount;
-{
- struct inode *ip;
- int error = 0;
-
- if (!afs_suser())
- return EPERM;
- if (error = igetinode(0, (dev_t) dev, inode, &ip))
- return error;
-
- if (!IS_VICEMAGIC(ip))
- error = EPERM;
- else if (((struct afsparms *)ip->i_afs)->vicep1 != inode_p1)
- error = ENXIO;
- else {
- ip->i_nlink += amount;
- osi_Assert(ip->i_nlink >= 0);
- if (ip->i_nlink == 0) {
- CLEAR_VICEMAGIC(ip);
- afsidestroy(ip);
- }
- ip->i_flags |= ICHG;
- }
- /* XXX sync write?? */
- iput(ip);
- return error;
-}
-
-struct iincargs {
- sysarg_t dev;
- sysarg_t inode;
- sysarg_t inode_p1;
-};
-
-int
-iinc(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(iinc);
- return (afs_syscall_iincdec(uap->dev, uap->inode, uap->inode_p1, 1));
-}
-
-int
-idec(struct iincargs *uap, rval_t * rvp)
-{
- AFS_STATCNT(idec);
- return (afs_syscall_iincdec(uap->dev, uap->inode, uap->inode_p1, -1));
-}
-#endif /* AFS_SGI_XFS_IOPS_ENV */
-
-#ifdef AFS_SGI_XFS_IOPS_ENV
-/* afs_syscall_ilistinode64
- * Gathers up all required info for ListViceInodes in one system call.
- */
-int
-afs_syscall_ilistinode64(int dev, int inode_hi, int inode_lo, int datap,
- int datalenp)
-{
- int code = 0;
- ino_t inode;
- xfs_inode_t *ip;
- vfs_t *vfsp;
- vnode_t *vp;
- struct vattr vattr;
- afs_xfs_attr_t attrs;
- int length;
- i_list_inode_t data;
- int idatalen;
-
- if (!afs_suser())
- return EPERM;
-#ifdef AFS_SGI65_ENV
- vfsp = vfs_devsearch(dev, xfs_fstype);
-#else
- vfsp = vfs_devsearch(dev);
-#endif
- if (!vfsp) {
- return ENXIO;
- }
-#ifndef AFS_SGI65_ENV
- if (vfsp->vfs_fstype != xfs_fstype)
- return ENOSYS;
-#endif
-
- AFS_COPYIN((char *)datalenp, &idatalen, sizeof(int), code);
- if (idatalen < sizeof(i_list_inode_t)) {
- idatalen = sizeof(i_list_inode_t);
- AFS_COPYOUT((char *)datalenp, (char *)&idatalen, sizeof(int), code);
- return E2BIG;
- }
- idatalen = sizeof(i_list_inode_t);
- AFS_COPYOUT((char *)datalenp, (char *)&idatalen, sizeof(int), code);
-
- AFS_COPYIN((char *)datap, (char *)&data, sizeof(i_list_inode_t), code);
- if (data.ili_version != AFS_XFS_ILI_VERSION) {
- data.ili_version = AFS_XFS_ILI_VERSION;
- AFS_COPYOUT((char *)&data, (char *)datap, sizeof(i_list_inode_t),
- code);
- return EINVAL;
- }
-
-
- inode = inode_hi;
- inode <<= 32;
- inode |= inode_lo;
- code =
- xfs_iget((((struct mount *)((vfsp)->vfs_bh.bh_first)->bd_pdata)),
- (void *)0, (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
- (daddr_t) 0);
- if (code)
- return code;
-
- vp = XFS_ITOV(ip);
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
- length = SIZEOF_XFS_ATTR_T;
-
- AFS_VOP_ATTR_GET(vp, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT,
- OSI_GET_CURRENT_CRED(), code);
- if (code) {
- code = EPERM;
- }
-
- if (!code) {
- if (attrs.at_attr_version != AFS_XFS_ATTR_VERS)
- code = EINVAL;
- }
-
- if (!code) {
- vattr.va_mask = AT_STAT;
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- }
-
- if (!code) {
- memset((char *)&data, 0, sizeof(data));
- data.ili_info.inodeNumber = inode;
- data.ili_info.byteCount = vattr.va_size;
- data.ili_info.linkCount = (vattr.va_mode & AFS_XFS_MODE_LINK_MASK);
- memcpy((char *)data.ili_info.param, (char *)attrs.at_param,
- sizeof(data.ili_info.param));
- data.ili_attr_version = attrs.at_attr_version;
- data.ili_name_version = attrs.at_name_version;
- data.ili_tag = attrs.at_tag;
- data.ili_pino = attrs.at_pino;
- data.ili_vno = vattr.va_uid;
- data.ili_magic = vattr.va_gid;
- AFS_COPYOUT((char *)&data, (char *)datap, sizeof(data), code);
- }
- VN_RELE(vp);
- return code;
-}
-#endif /* AFS_SGI_XFS_IOPS_ENV */
+++ /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
- */
-
-/*
- * Inode information required for IRIX servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0x84fa1cb6
-/* chown can't set the high bit - used for XFS based filesystem */
-#define XFS_VICEMAGIC 0x74fa1cb6
-
-/* These exist because HP requires more work to extract uid. */
-#define DI_VICEP3(p) ( (p)->di_vicep3 )
-#define I_VICE3(p) ( (p)->i_vicep3 )
-
-
-/*
- * We use the 12 8-bit unused ex_magic fields!
- * Plus 2 values of di_version
- * di_version = 0 - current EFS
- * 1 - AFS INODESPECIAL
- * 2 - AFS inode
- * AFS inode:
- * magic[0-3] - VOLid
- * magic[4-6] - vnode number (24 bits)
- * magic[7-9] - disk uniqifier
- * magic[10-11]+di_spare - data version
- *
- * INODESPECIAL:
- * magic[0-3] - VOLid
- * magic[4-7] - parent
- * magic[8] - type
- */
-#define SGI_UNIQMASK 0xffffff
-#define SGI_DATAMASK 0xffffff
-#define SGI_DISKMASK 0xffffff
-
-/* we hang this struct off of the incore inode */
-struct afsparms {
- afs_int32 vicep1;
- afs_int32 vicep2;
- afs_int32 vicep3;
- afs_int32 vicep4;
-};
-
-#define dmag(p,n) ((p)->di_u.di_extents[n].ex_magic)
-
-#define IS_VICEMAGIC(ip) (((ip)->i_version == EFS_IVER_AFSSPEC || \
- (ip)->i_version == EFS_IVER_AFSINO) \
- ? 1 : 0)
-#define IS_DVICEMAGIC(dp) (((dp)->di_version == EFS_IVER_AFSSPEC || \
- (dp)->di_version == EFS_IVER_AFSINO) \
- ? 1 : 0)
-
-#define CLEAR_VICEMAGIC(ip) (ip)->i_version = EFS_IVER_EFS
-#define CLEAR_DVICEMAGIC(dp) dp->di_version = EFS_IVER_EFS
-
-#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
- */
-
-/*
- * IRIX 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/sema.h>
-#include <sys/pda.h>
-extern kmutex_t afs_global_lock;
-
-
-#undef osi_Time
-extern time_t time;
-#define osi_Time() (time)
-
-/* This gets redefined from ucred to cred in osi_vfs.h, just do it right */
-#define AFS_UCRED cred
-
-#define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0)
-
-#undef afs_osi_Alloc_NoSleep
-extern void *afs_osi_Alloc_NoSleep(size_t size);
-
-
-#ifdef AFS_SGI64_ENV
-#include <sys/flock.h>
-extern flid_t osi_flid;
-#define v_op v_bh.bh_first->bd_ops
-#define v_data v_bh.bh_first->bd_pdata
-#define vfs_data vfs_bh.bh_first->bd_pdata
-#endif /* AFS_SGI64_ENV */
-
-
-/*
- * Global lock, semaphore, mutex and state vector support.
- */
-#define SV_INIT(cv, nm, t, c) cv_init(cv, nm, t, c)
-/* Spinlock macros */
-#define SV_TYPE sv_t
-#define SV_SIGNAL(cv) sv_signal(cv)
-#define SPINLOCK_INIT(l, nm) spinlock_init((l),(nm))
-#define SPLOCK(l) mp_mutex_spinlock(&(l))
-#define SPUNLOCK(l,s) mp_mutex_spinunlock(&(l),s)
-#define SP_WAIT(l, s, cv, p) mp_sv_wait_sig(cv, p, (void*)(&(l)), s)
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
-/* Add PLTWAIT for afsd's to wait so we don't rack up the load average. */
-#define AFSD_PRI() ((kt_basepri(curthreadp) == PTIME_SHARE) ? PZERO : (PZERO|PLTWAIT))
-#undef AFS_MUTEX_ENTER
-#define AFS_MUTEX_ENTER(mp) \
- MACRO_BEGIN \
- register struct kthread *_kthreadP; \
- while(mutex_tryenter(mp) == 0) { \
- _kthreadP = (struct kthread*)mutex_owner(mp); \
- if (_kthreadP != NULL && _kthreadP->k_sonproc == CPU_NONE) { \
- mutex_lock(mp, AFSD_PRI()); \
- break; \
- } \
- } \
- MACRO_END
-
-#else /* AFS_SGI65_ENV */
-/* Add PLTWAIT for afsd's to wait so we don't rack up the load average. */
-#define AFSD_PRI() ((curprocp && curprocp->p_rss==0) ? (PZERO|PLTWAIT) : PZERO)
-
-#define AFS_MUTEX_ENTER(mp) \
- MACRO_BEGIN \
- kthread_t *kt; \
- while(mutex_tryenter(mp) == 0) { \
- kt = mutex_owner(mp); \
- if (kt != NULL && kt->k_sonproc == CPU_NONE) { \
- mutex_lock(mp, AFSD_PRI()); \
- break; \
- } \
- } \
- MACRO_END
-#endif /* AFS_SGI65_ENV */
-
-#define cv_timedwait(cv, l, t) { \
- sv_timedwait(cv, AFSD_PRI(), l, 0, 0, &(t), \
- (struct timespec*)0); \
- AFS_MUTEX_ENTER(l); \
- }
-#ifdef cv_wait
-#undef cv_wait
-#endif
-#define cv_wait(cv, l) { \
- sv_wait(cv, AFSD_PRI(), l, 0); \
- AFS_MUTEX_ENTER(l); \
- }
-#else /* AFS_SGI64_ENV */
-#ifdef AFS_SGI62_ENV
-
-#define AFS_MUTEX_ENTER(mp) \
- MACRO_BEGIN \
- register struct proc *_procP; \
- while(mutex_tryenter(mp) == 0) { \
- _procP = mutex_owner(mp); \
- if (_procP != NULL && _procP->p_sonproc == CPU_NONE) { \
- mutex_enter(mp); \
- break; \
- } \
- } \
- MACRO_END
-
-#else /* AFS_SGI62_ENV */
-
-#define AFS_MUTEX_ENTER(mp) mutex_enter(mp)
-
-#endif /* AFS_SGI62_ENV */
-
-#define cv_timedwait(cv, l, t) { \
- sv_timedwait(cv, l, t); \
- AFS_GLOCK(); \
- }
-#endif /* AFS_SGI64_ENV */
-
-#if defined(KERNEL)
-#if defined(MP)
-#define _MP_NETLOCKS /* to get sblock to work right */
-
-/* On SGI mutex_owned doesn't work, so simulate this by remembering the owning
- * thread explicitly. This is only used for debugging so could be disabled for
- * production builds.
- *
- * CAUTION -- The ISAFS_(RX)?GLOCK macros are not safe to use when the lock is
- * not held if the test may be made at interrupt level as the code may
- * appear to be running as the process that is (or last was) running at
- * non-interrupt level. Worse yet, the interrupt may occur just as the
- * process is exiting, in which case, the pid may change from the start
- * of the interrupt to the end, since the u area has been changed. So,
- * at interrupt level, I'm using the base of the current interrupt stack.
- * Note that afs_osinet.c also modifies afs_global_owner for osi_Sleep and
- * afs_osi_Wakeup. Changes made here should be reflected there as well.
- * NOTE - As of 6.2, we can no longer use mutexes in interrupts, so the above
- * concern no longer exists.
- */
-
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
-/* Irix does not check for deadlocks unless it's a debug kernel. */
-#define AFS_ASSERT_GNOTME() \
- (!ISAFS_GLOCK() || (panic("afs global lock held be me"), 0))
-#define AFS_GLOCK() \
- { AFS_ASSERT_GNOTME(); AFS_MUTEX_ENTER(&afs_global_lock); }
-#else
-#define AFS_GLOCK() AFS_MUTEX_ENTER(&afs_global_lock)
-#endif
-#define AFS_GUNLOCK() (AFS_ASSERT_GLOCK(), mutex_exit(&afs_global_lock))
-#define ISAFS_GLOCK() mutex_mine(&afs_global_lock)
-#else
-extern long afs_global_owner;
-#define AFS_GLOCK() \
- MACRO_BEGIN \
- AFS_MUTEX_ENTER(&afs_global_lock) ; \
- afs_global_owner = osi_ThreadUnique(); \
- MACRO_END
-#define AFS_GUNLOCK() \
- (AFS_ASSERT_GLOCK(), afs_global_owner = 0, mutex_exit(&afs_global_lock))
-#define ISAFS_GLOCK() (osi_ThreadUnique() == afs_global_owner)
-#endif /* AFS_SGI64_ENV */
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-
-#else /* MP */
-#define AFS_GLOCK()
-#define AFS_GUNLOCK()
-#define ISAFS_GLOCK() 1
-
-#define SPLVAR register int splvar
-#define NETPRI splvar=splnet()
-#define USERPRI splx(splvar)
-
-
-#endif /* MP */
-
-#endif /* KERNEL */
-
-
-
-#ifdef AFS_SGI64_ENV
-#define gop_rdwr(rw,gp,base,len,offset,segflg,ioflag,ulimit,cr,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(ioflag),(ulimit),(cr),\
- (int *)(aresid), &osi_flid)
-#else
-#define gop_rdwr(rw,gp,base,len,offset,segflg,ioflag,ulimit,cr,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(ioflag),(ulimit),(cr), \
- (int *)(aresid))
-#endif
-
-#ifdef AFS_SGI64_ENV
-#undef suser
-#define suser() cap_able(CAP_DEVICE_MGT)
-#define afs_suser() suser()
-#else
-#define afs_suser suser
-#endif
-
-#define afs_hz HZ
-
-#ifdef PAGESIZE
-#undef PAGESIZE
-#endif
-#define PAGESIZE 4096
-
-#ifdef AFS_SGI64_ENV
-#undef setuerror
-#undef getuerror
-#endif
-
-
-/* OS independent user structure stuff */
-/*
- * OSI_GET_CURRENT_PID
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_PID() (u.u_procp->p_pid)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_PID() current_pid()
-#endif /* AFS_SGI64_ENV */
-
-#if defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_PID() proc_pid(curproc())
-#endif
-
-#define getpid() OSI_GET_CURRENT_PID()
-
-/*
- * OSI_GET_CURRENT_PROCP
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_PROCP() (u.u_procp)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_PROCP() curprocp
-#endif /* AFS_SGI64_ENV */
-
-#if defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_PROCP() UT_TO_PROC(curuthread)
-#endif
-
-
-/*
- * OSI_GET_LOCKID
- *
- * Prior to IRIX 6.4, pid sufficed, now we need kthread.
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_LOCKID() (u.u_procp->p_pid)
-#define OSI_NO_LOCKID (-1)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-/* IRIX returns k_id, but this way, we've got the thread address for debugging. */
-#define OSI_GET_LOCKID() \
- (private.p_curkthread ? (uint64_t)private.p_curkthread : (uint64_t)0)
-#define OSI_NO_LOCKID ((uint64_t)-1)
-#endif /* AFS_SGI64_ENV */
-
-/*
- * OSI_GET_CURRENT_CRED
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_CRED() (u.u_cred)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_CRED() get_current_cred()
-#endif /* AFS_SGI64_ENV */
-
-#define osi_curcred() OSI_GET_CURRENT_CRED()
-
-/*
- * OSI_SET_CURRENT_CRED
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_SET_CURRENT_CRED(x) u.u_cred=x
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-#define OSI_SET_CURRENT_CRED(C) set_current_cred((C))
-#endif /* AFS_SGI64_ENV */
-
-/*
- * OSI_GET_CURRENT_ABI
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_ABI() (u.u_procp->p_abi)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_ABI() get_current_abi()
-#endif /* AFS_SGI64_ENV */
-
-/*
- * OSI_GET_CURRENT_SYSID
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_SYSID() (u.u_procp->p_sysid)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_SYSID() (curprocp->p_flid.fl_sysid)
-#endif /* AFS_SGI64_ENV */
-
-/*
- * OSI_GET_CURRENT_COMM
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_COMM() (u.u_comm)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_COMM() (curprocp->p_comm)
-#endif /* AFS_SGI64_ENV */
-
-/*
- * OSI_GET_CURRENT_CDIR
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_CDIR() (u.u_cdir)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_CDIR() (curprocp->p_cdir)
-#endif /* AFS_SGI64_ENV */
-
-#if defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_CDIR() (curuthread->ut_cdir)
-#endif /* AFS_SGI65_ENV */
-
-
-/*
- * OSI_GET_CURRENT_RDIR
- */
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-#define OSI_GET_CURRENT_RDIR() (u.u_rdir)
-#endif /* AFS_SGI_ENV but not AFS_SGI64_ENV */
-
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_RDIR() (curprocp->p_rdir)
-#endif /* AFS_SGI64_ENV */
-
-#if defined(AFS_SGI65_ENV)
-#define OSI_GET_CURRENT_RDIR() (curuthread->ut_rdir)
-#endif /* AFS_SGI65_ENV */
-
-
-
-/* Macros for vcache/vnode and vfs arguments to vnode and vfs ops.
- *
- * Note that the _CONVERT routines get the ";" here so that argument lists
- * can have arguments after the OSI_x_CONVERT macro is called.
- */
-#ifdef AFS_SGI64_ENV
-#undef OSI_VN_ARG
-#define OSI_VN_ARG(V) bhv_##V
-#undef OSI_VN_DECL
-#define OSI_VN_DECL(V) bhv_desc_t *bhv_##V
-#undef OSI_VN_CONVERT
-#define OSI_VN_CONVERT(V) struct vnode * V = (struct vnode*)BHV_TO_VNODE(bhv_##V);
-#undef OSI_VC_ARG
-#define OSI_VC_ARG(V) bhv_##V
-#undef OSI_VC_DECL
-#define OSI_VC_DECL(V) bhv_desc_t *bhv_##V
-#undef OSI_VC_CONVERT
-#define OSI_VC_CONVERT(V) struct vcache * V = VTOAFS(BHV_TO_VNODE(bhv_##V));
-#undef OSI_VFS_ARG
-#define OSI_VFS_ARG(V) bhv_##V
-#undef OSI_VFS_DECL
-#define OSI_VFS_DECL(V) bhv_desc_t *bhv_##V
-#undef OSI_VFS_CONVERT
-#define OSI_VFS_CONVERT(V) struct vfs * V = (struct vfs*)bhvtovfs(bhv_##V);
-#endif /* AFS_SGI64_ENV */
-
-
-
-
-#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
- */
-
-/*
- * Implementation of miscellaneous Irix routines.
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_misc.c,v 1.7 2003/07/15 23:14:23 shadow Exp $");
-
-#ifdef AFS_SGI62_ENV
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-
-
-
-/*
- * various special purpose routines
- */
-void
-afs_mpservice(void *a)
-{
-}
-
-#ifdef AFS_SGI_VNODE_GLUE
-#include <sys/invent.h>
-extern mutex_t afs_init_kern_lock;
-
-/* afs_init_kernel_config
- *
- * initialize vnode glue layer by testing for NUMA.
- * Argument: flag
- * 0 = no numa, 1 = has numa, -1 = test for numa.
- */
-int
-afs_init_kernel_config(int flag)
-{
- static int afs_kern_inited = 0;
- int code = 0;
-
- mutex_enter(&afs_init_kern_lock);
- if (!afs_kern_inited) {
- afs_kern_inited = 1;
-
- if (flag == -1) {
- inventory_t *pinv;
- /* test for numa arch. */
- /* Determine if thisis a NUMA platform. Currently, this is true
- * only if it's an IP27 or IP35.
- */
- pinv =
- find_inventory((inventory_t *) NULL, INV_PROCESSOR,
- INV_CPUBOARD, -1, -1, -1);
- if (!pinv)
- code = ENODEV;
- else
- afs_is_numa_arch = ((pinv->inv_state == INV_IP27BOARD)
- || (pinv->inv_state == INV_IP35BOARD))
- ? 1 : 0;
- } else
- afs_is_numa_arch = flag;
- }
- mutex_exit(&afs_init_kern_lock);
- return code;
-}
-#endif /* AFS_SGI_VNODE_GLUE */
-
-/* And just so we know what someone is _really_ running */
-#ifdef IP19
-int afs_ipno = 19;
-#elif defined(IP20)
-int afs_ipno = 20;
-#elif defined(IP21)
-int afs_ipno = 21;
-#elif defined(IP25)
-int afs_ipno = 25;
-#elif defined(IP26)
-int afs_ipno = 26;
-#elif defined(IP27)
-int afs_ipno = 27;
-#elif defined(IP28)
-int afs_ipno = 28;
-#elif defined(IP30)
-int afs_ipno = 30;
-#elif defined(IP35)
-int afs_ipno = 35;
-#else
-int afs_ipno = -1;
-#endif
-
-
-#endif /* AFS_SGI62_ENV */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_sleep.c,v 1.9 2003/07/15 23:14:23 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-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) curthreadp;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = 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 */
- kcondvar_t cond; /* Currently associated condition variable */
-} afs_event_t;
-
-#define HASHSIZE 128
-afs_event_t *afs_evhasht[HASHSIZE]; /* Hash table for events */
-#if (_MIPS_SZPTR == 64)
-#define afs_evhash(event) (afs_uint32) ((((long)event)>>3) & (HASHSIZE-1));
-#else
-#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
-#endif
-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;
- cv_init(&newp->cond, "event cond var", CV_DEFAULT, NULL);
- 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();
- cv_wait(&evp->cond, &afs_global_lock);
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- afs_osi_Sleep(event);
- return 0;
-}
-
-/* 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.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- struct timespec ticks;
-
- ticks.tv_sec = ams / 1000;
- ticks.tv_nsec = (ams - (ticks.tv_sec * 1000)) * 1000000;
-
-
- evp = afs_getevent(event);
-
- AFS_ASSERT_GLOCK();
- if (aintok) {
- if (sv_timedwait_sig
- (&evp->cond, AFSD_PRI(), &afs_global_lock, 0, 0, &ticks,
- (struct timespec *)0))
- code = EINTR;
- AFS_MUTEX_ENTER(&afs_global_lock);
- } else {
- cv_timedwait(&evp->cond, &afs_global_lock, ticks);
- }
-
- 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++;
- cv_broadcast(&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
- */
-
-/*
- * SGI specific vfs related defines
- */
-#ifndef _SGI_VFS_H_
-#define _SGI_VFS_H_
-
-#if !defined(AFS_SGI65_ENV)
-/* In Irix 6.5, the r/w-vops rwlocks the vnode if not already locked. */
-#define IO_ISLOCKED 0
-#endif
-
-/*
- * UFS -> EFS/XFS translations
- */
-#ifdef AFS_SGI62_ENV
-#ifdef AFS_SGI64_ENV
-#define EFS_VTOI(vp) bhvtoi(VNODE_TO_FIRST_BHV(vp))
-/* Note: If SGI ever has more than one behavior per vnode, we'll have
- * to search for the one we want.
- */
-#define XFS_VTOI(V) ((xfs_inode_t*)((V)->v_fbhv->bd_pdata))
-#define vfstom(V) (bhvtom((V)->vfs_fbhv))
-#else
-#define EFS_VTOI(vp) vtoi(vp)
-#endif
-#define EFS_ITOV(ip) itov(ip)
-#else
-#define ITOV(ip) itov(ip)
-#define VTOI(vp) vtoi(vp)
-#define EFS_ITOV ITOV
-#define EFS_VTOI VTOI
-#endif
-
-#ifdef AFS_SGI62_ENV
-struct xfs_inode;
-typedef struct xfs_inode xfs_inode_t;
-#define xfs_ino_t uint64_t
-#define XFS_ILOCK_SHARED 0x08
-struct xfs_trans;
-struct xfs_mount;
-extern int xfs_iget(struct mount *, struct xfs_trans *, xfs_ino_t, uint,
- xfs_inode_t **, daddr_t);
-
-#ifdef AFS_SGI64_ENV
-#define XFS_ITOV(ip) BHV_TO_VNODE((struct bhv_desc *)(((char*)(ip)) + 6*sizeof(void*)))
-#else
-#define XFS_ITOV(ip) (*((vnode_t**)((((char*)(ip)) + 6*sizeof(void*)))))
-#endif
-
-/* When we have XFS only clients, then these macros will be defined in
- * terms of the XFS inode only.
- */
-#ifdef AFS_SGI_DUAL_FS_CACHE
-#define AFS_SGI_EFS_CACHE 0
-#define AFS_SGI_XFS_CACHE 1
-extern int afs_CacheFSType;
-extern vnode_t *(*afs_IGetVnode) (ino_t);
-extern struct vnodeops *afs_efs_vnodeopsp;
-extern struct vnodeops *afs_xfs_vnodeopsp;
-
-#define AFS_SGI_IGETVNODE(INO) (*afs_IGetVnode)(INO)
-/* These need to be functions to wrap the vnode op calls. */
-extern ino_t VnodeToIno(vnode_t * vp);
-extern dev_t VnodeToDev(vnode_t * vp);
-extern off_t VnodeToSize(vnode_t * vp);
-#else
-/* Just the EFS variants exist for now. */
-#define VnodeToIno(vp) ((ino_t)(EFS_VTOI((vp))->i_number))
-#define VnodeToDev(vp) EFS_VTOI((vp))->i_dev
-#define VnodeToSize(vp) EFS_VTOI((vp))->i_size
-#define AFS_SGI_IGETVNODE(INO) afs_EFSIGetVnode(INO)
-#endif
-#else /* AFS_SGI62_ENV */
-#define AFS_SGI_IGETVNODE(INO) afs_EFSIGetVnode(INO)
-#endif
-
-/* Page routines are vnode ops in Irix 6.5. These macros paper over the
- * differences.
- */
-#ifdef AFS_SGI65_ENV
-#define PTOSSVP(vp, off, len) VOP_TOSS_PAGES((vp), (off), (len), 0)
-#define PFLUSHINVALVP(vp, off, len) VOP_FLUSHINVAL_PAGES((vp), (off), (len), 0)
-#define PFLUSHVP(vp, len, flags, code) \
- VOP_FLUSH_PAGES((vp), 0, (len), (flags), 0, code)
-#define PINVALFREE(vp, off) VOP_INVALFREE_PAGES((vp), (off))
-#else
-#define PTOSSVP ptossvp
-#define PFLUSHINVALVP pflushinvalp
-#define PFLUSHVP(vp, len, flags, code) code = pflushvp(vp, len, flags)
-#define PINVALFREE pinvalfree
-#endif
-
-
-/*
- * VFS translations
- */
-#ifdef AFS_SGI_VNODE_GLUE
-/* The Octane does not have the mrlock_t in the bvh_head_t. So we should
- * not lock it.
- */
-extern int afs_is_numa_arch;
-#define BHV_IPREVENT(BHP) afs_is_numa_arch ? BHV_INSERT_PREVENT(BHP) : (void)0
-#define BHV_IALLOW(BHP) afs_is_numa_arch ? BHV_INSERT_ALLOW(BHP) : (void)0
-
-/* similar definition in /usr/include/sys/vfs.h (sgi_64) */
-#define VFS_STATFS(vfsp,sp,vp)\
- (*((vfsops_t *)(vfsp)->vfs_fops)->vfs_statvfs)((vfsp)->vfs_fbhv,sp,vp)
-#define AFS_VOP_ATTR_SET(vp, name, value, valuelen, flags, cred, rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_attr_set)((vp)->v_fbhv,name,value,valuelen,flags,cred); \
- BHV_IALLOW(&(vp)->v_bh); \
-}
-
-#define AFS_VOP_ATTR_GET(vp, name, value, valuelenp, flags, cred, rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_attr_get)((vp)->v_fbhv,name,value,valuelenp,flags,cred); \
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_SETATTR(vp, vap, f, cr, rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_setattr)((vp)->v_fbhv, vap, f, cr); \
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_GETATTR(vp, vap, f, cr, rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_getattr)((vp)->v_fbhv, vap, f, cr); \
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_REMOVE(dvp,p,cr,rv) \
-{ \
- BHV_IPREVENT(&(dvp)->v_bh); \
- rv = (*((vnodeops_t *)(dvp)->v_fops)->vop_remove)((dvp)->v_fbhv,p,cr); \
- BHV_IALLOW(&(dvp)->v_bh); \
-}
-#define AFS_VOP_LOOKUP(vp,cp,vpp,pnp,f,rdir,cr,rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_lookup)((vp)->v_fbhv,cp,vpp,pnp,f,rdir,cr); \
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_RMDIR(dp,p,cdir,cr,rv) \
-{ \
- BHV_IPREVENT(&(dp)->v_bh); \
- rv = (*((vnodeops_t *)(dp)->v_fops)->vop_rmdir)((dp)->v_fbhv,p,cdir,cr); \
- BHV_IALLOW(&(dp)->v_bh); \
-}
-#define AFS_VOP_WRITE(vp,uiop,iof,cr,rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_write)((vp)->v_fbhv,uiop,iof,cr,&(curprocp->p_flid));\
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_READ(vp,uiop,iof,cr,rv) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- rv = (*((vnodeops_t *)(vp)->v_fops)->vop_read)((vp)->v_fbhv,uiop,iof,cr,&(curprocp->p_flid));\
- BHV_IALLOW(&(vp)->v_bh); \
-}
-#define AFS_VOP_RWLOCK(vp,i) \
-{ \
- BHV_IPREVENT(&(vp)->v_bh); \
- (void)(*((vnodeops_t *)(vp)->v_fops)->vop_rwlock)((vp)->v_fbhv, i); \
- /* "allow" is done by rwunlock */ \
-}
-#define AFS_VOP_RWUNLOCK(vp,i) \
-{ /* "prevent" was done by rwlock */ \
- (void)(*((vnodeops_t *)(vp)->v_fops)->vop_rwunlock)((vp)->v_fbhv, i);\
- BHV_IALLOW(&(vp)->v_bh); \
-}
-
-/* VOP_RECLAIM remains as is, since it doesn't do the PREVENT/ALLOW */
-
-#define AFS_VN_OPEN(path, seg, mode, perm, dvp, why) \
- vn_open((path), (seg), (mode), (perm), (dvp), (why), 0)
-#else /* AFS_SGI_VNODE_GLUE */
-#define VFS_STATFS VFS_STATVFS
-#ifdef AFS_SGI65_ENV
-#define AFS_VOP_ATTR_SET VOP_ATTR_SET
-#define AFS_VOP_ATTR_GET VOP_ATTR_GET
-#define AFS_VOP_SETATTR VOP_SETATTR
-#define AFS_VOP_GETATTR VOP_GETATTR
-#define AFS_VOP_REMOVE VOP_REMOVE
-#define AFS_VOP_LOOKUP VOP_LOOKUP
-#define AFS_VOP_RMDIR VOP_RMDIR
-#define AFS_VOP_READ(vp, uiop, iof, cr, code) \
- VOP_READ((vp), (uiop), (iof), (cr), &curuthread->ut_flid, code)
-#define AFS_VOP_WRITE(vp, uiop, iof, cr, code) \
- VOP_WRITE((vp), (uiop), (iof), (cr), &curuthread->ut_flid, code)
-
-#define AFS_VN_OPEN(path, seg, mode, perm, dvp, why) \
- vn_open((path), (seg), (mode), (perm), (dvp), (why), 0, NULL)
-#else
-#define AFS_VOP_ATTR_SET(dvp, name, attr, size, flags, cred, code) \
- code = VOP_ATTR_SET((dvp), (name), (attr), (size), (flags), (cred))
-#define AFS_VOP_ATTR_GET(dvp, name, attr, sizep, flags, cred, code) \
- code = VOP_ATTR_GET((dvp), (name), (attr), (sizep), (flags), (cred))
-#define AFS_VOP_SETATTR(vp, vattr, flags, cred, code) \
- code = VOP_SETATTR((vp), (vattr), (flags), (cred))
-#define AFS_VOP_GETATTR(vp, vattr, flags, cred, code) \
- code = VOP_GETATTR((vp), (vattr), (flags), (cred))
-#define AFS_VOP_REMOVE(dvp, path, cred, code) \
- code = VOP_REMOVE((dvp), (path), (cred))
-#define AFS_VOP_LOOKUP(dvp, name, dvpp, path, flags, rdir, cred, code) \
- code = VOP_LOOKUP((dvp), (name), (dvpp), (path), (flags), \
- (rdir), (cred))
-#define AFS_VOP_RMDIR(ddvp, path, cdir, cred, code) \
- code = VOP_RMDIR((ddvp), (path), (cdir), (cred))
-#define AFS_VOP_READ(vp,uiop,iof,cr,code) \
- code = VOP_READ((vp), (uiop), (iof), (cr))
-#define AFS_VOP_WRITE(vp,uiop,iof,cr,code) \
- code = VOP_WRITE((vp), (uiop), (iof), (cr))
-#define AFS_VN_OPEN vn_open
-#endif /* AFS_SGI65_ENV */
-
-#define AFS_VOP_RWLOCK(vp, flag) VOP_RWLOCK((vp), (flag))
-#define AFS_VOP_RWUNLOCK(vp, flag) VOP_RWUNLOCK((vp), (flag))
-
-#endif /* AFS_SGI_VNODE_GLUE */
-#define devtovfs vfs_devsearch
-#define va_blocksize va_blksize
-#define va_blocks va_nblocks
-#define MAXNAMLEN 256
-
-/* These macros hide the shape change inthe vnode for sgi_64 w/o NUMA.
- * They call routines so that if statements do not contain complex
- * expressions.
- */
-#ifdef AFS_SGI_VNODE_GLUE
-extern int afs_is_numa_arch;
-typedef struct bhv_head1 {
- struct bhv_desc *bh_first; /* first behavior in chain */
-#ifdef notdef
- /* This is not present in the non NUMA machines. */
- mrlock_t bh_mrlock; /* lock for ops-in-progress synch. */
-#endif
-} bhv_head1_t;
-
-typedef struct vnode1 {
- struct vnlist v_list; /* freelist linkage */
- uint v_flag; /* vnode flags (see below) */
- cnt_t v_count; /* reference count */
- u_short v_namecap; /* name cache capability */
- enum vtype v_type; /* vnode type */
- dev_t v_rdev; /* device (VCHR, VBLK) */
- struct vfs *v_vfsmountedhere; /* ptr to vfs mounted here */
- struct vfs *v_vfsp; /* ptr to containing VFS */
- struct stdata *v_stream; /* associated stream */
- struct filock *v_filocks; /* ptr to filock list */
- mutex_t *v_filocksem; /* ptr to mutex for list */
- vnumber_t v_number; /* in-core vnode number */
- short v_listid; /* free list id */
- cnt_t v_intpcount; /* interp. refcount for imon */
- bhv_head1_t v_bh; /* behavior head */
-
- /*
- * Used only by global cache.
- */
- struct vnode *v_hashp; /* hash list for lookup */
- struct vnode *v_hashn; /* hash list for lookup */
-
- /*
- * Values manipulated only by VM and
- * the page/buffer caches.
- */
- struct pregion *v_mreg; /* mapped file region pointer */
- int v_dbuf; /* delwri buffer count */
- pgno_t v_pgcnt; /* pages hashed to vnode */
- struct pfdat *v_dpages; /* delwri pages */
- struct buf *v_buf; /* vnode buffer tree head */
- unsigned int v_bufgen; /* buf list generation number */
- mutex_t v_buf_lock; /* mutex for buffer tree */
-
- vnode_pcache_t v_pc; /* Page cache structure.
- * per vnode. Refer to
- * vnode_pcache.h
- * for details.
- */
-#ifdef VNODE_TRACING
- struct ktrace *v_trace; /* trace header structure */
-#endif
-#ifdef CKPT
- ckpt_handle_t v_ckpt; /* ckpt lookup info */
-#endif
-} vnode1_t;
-
-extern struct pfdat *vnode_get_dpages(vnode_t *);
-extern int vnode_get_dbuf(vnode_t *);
-extern pgno_t vnode_get_pgcnt(vnode_t *);
-extern struct pregion *vnode_get_mreg(vnode_t *);
-#define VN_GET_DPAGES(V) (afs_is_numa_arch ? \
- ((V)->v_dpages) : \
- (((vnode1_t*)(V))->v_dpages))
-#define VN_SET_DPAGES(V, D) (afs_is_numa_arch ? \
- ((V)->v_dpages = (D)) : \
- (((vnode1_t*)(V))->v_dpages = (D)))
-#define VN_GET_DBUF(V) (afs_is_numa_arch ? \
- ((V)->v_dbuf) : (((vnode1_t*)(V))->v_dbuf))
-#define VN_GET_PGCNT(V) (afs_is_numa_arch ? \
- ((V)->v_pgcnt) : (((vnode1_t*)(V))->v_pgcnt))
-#define VN_GET_MREG(V) (afs_is_numa_arch ? \
- ((V)->v_mreg) : (((vnode1_t*)(V))->v_mreg))
-#define AFS_VN_MAPPED(V) (VN_GET_MREG(V) != NULL)
-#define AFS_VN_DIRTY(V) (VN_GET_DBUF(V) || VN_GET_DPAGES(V))
-#define AFS_VN_INIT_BUF_LOCK(V) \
- (afs_is_numa_arch ? \
- init_mutex(&((V)->v_buf_lock), MUTEX_DEFAULT, "vn_buf_lock", \
- (long)(V) ) : \
- init_mutex(&(((vnode1_t*)(V))->v_buf_lock), MUTEX_DEFAULT, \
- "vn_buf_lock", \
- (long)(V) ))
-#define AFS_VN_DESTROY_BUF_LOCK(V) \
- (afs_is_numa_arch ? \
- mutex_destroy(&((V)->v_buf_lock)) : \
- mutex_destroy(&(((vnode1_t*)(V))->v_buf_lock)))
-
-#else
-#define VN_GET_DPAGES(V) ((V)->v_dpages)
-#define VN_SET_DPAGES(V, D) (V)->v_dpages = (D)
-#define VN_GET_DBUF(V) ((V)->v_dbuf)
-#define VN_GET_PGCNT(V) ((V)->v_pgcnt)
-#define VN_GET_MREG(V) ((V)->v_mreg)
-#define AFS_VN_MAPPED VN_MAPPED
-#define AFS_VN_DIRTY VN_DIRTY
-#define AFS_VN_INIT_BUF_LOCK(V) \
- init_mutex(&((V)->v_buf_lock), MUTEX_DEFAULT, "vn_buf_lock", (long)(V))
-#define AFS_VN_DESTROY_BUF_LOCK(V) \
- mutex_destroy(&((V)->v_buf_lock))
-#endif /* AFS_SGI_VNODE_GLUE */
-
-/*
- * Misc
- */
-#define ucred cred
-#define uprintf printf
-#define d_fileno d_ino
-
-#define CLBYTES NBPC
-/*
- * Flock(3) call. (from sys/file.h)
- */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* don't block when locking */
-#define LOCK_UN 8 /* unlock */
-
-#endif
-
-
-#if defined(AFS_SGI64_ENV) && defined(CKPT)
-/* This is a fid for checkpoint restart. Note that the length will be
- * greater than 10 and so afs_vget can distinguish this fid.
- */
-typedef struct {
- u_short af_len;
- u_short af_cell;
- u_int af_volid;
- u_int af_vno;
- u_int af_uniq;
-} afs_fid2_t;
-#endif /* _SGI_VFS_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_vfsops.c for IRIX
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_vfsops.c,v 1.13 2003/07/15 23:14:23 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-#include "sys/syssgi.h"
-
-
-struct vfs *afs_globalVFS = 0;
-struct vcache *afs_globalVp = 0;
-
-#ifdef AFS_SGI_VNODE_GLUE
-#include <sys/invent.h>
-int afs_is_numa_arch;
-mutex_t afs_init_kern_lock;
-#endif
-
-
-#define SYS_setgroups SGI_SETGROUPS
-
-int (*nfs_rfsdisptab_v2) () = NULL;
-
-int afs_fstype;
-lock_t afs_rxlock;
-
-#include "sys/mload.h"
-char *Afs_mversion = M_VERSION;
-
-extern int (*setgroupsp) (int, gid_t *);
-extern struct afs_lock afs_xvcache;
-extern int idbg_afsuser();
-extern void afs_mpservice(void *);
-
-/*
- * AFS fs initialization - we also plug system calls here
- */
-#define NewSystemCall(n,f,a) \
- syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_narg = a; \
- syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_call = f; \
- syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_flags = 0;
-extern struct vfsops Afs_vfsops, *afs_vfsopsp;
-extern struct vnodeops Afs_vnodeops, *afs_vnodeopsp;
-extern void (*afsidestroyp) (struct inode *);
-extern void (*afsdptoipp) (struct efs_dinode *, struct inode *);
-extern void (*afsiptodpp) (struct inode *, struct efs_dinode *);
-extern void afsidestroy(struct inode *);
-extern void afsdptoip(struct efs_dinode *, struct inode *);
-extern void afsiptodp(struct inode *, struct efs_dinode *);
-extern int (*idbg_prafsnodep) (vnode_t *);
-extern int (*idbg_afsvfslistp) (void);
-extern int idbg_prafsnode(vnode_t *);
-extern int idbg_afsvfslist(void);
-
-
-int
-Afs_init(struct vfssw *vswp, int fstype)
-{
- extern int Afs_syscall(), Afs_xsetgroups(), afs_pioctl(), afs_setpag();
- extern int icreate(), iopen(), iinc(), idec();
-#ifdef AFS_SGI_XFS_IOPS_ENV
- extern int iopen64();
-#else
- extern int iread(), iwrite();
-#endif
-
- AFS_STATCNT(afsinit);
- osi_Init();
- afs_fstype = fstype;
-
-#ifdef AFS_SGI_VNODE_GLUE
- /* Synchronize doing NUMA test. */
- mutex_init(&afs_init_kern_lock, MUTEX_DEFAULT, "init_kern_lock");
-#endif
- /*
- * set up pointers from main kernel into us
- */
- afs_vnodeopsp = &Afs_vnodeops;
- afs_vfsopsp = &Afs_vfsops;
- afsidestroyp = afsidestroy;
- afsiptodpp = afsiptodp;
- afsdptoipp = afsdptoip;
- idbg_prafsnodep = idbg_prafsnode;
- idbg_afsvfslistp = idbg_afsvfslist;
- NewSystemCall(AFS_SYSCALL, Afs_syscall, 6);
- NewSystemCall(AFS_PIOCTL, afs_pioctl, 4);
- NewSystemCall(AFS_SETPAG, afs_setpag, 0);
- NewSystemCall(AFS_IOPEN, iopen, 3);
- NewSystemCall(AFS_ICREATE, icreate, 6);
- NewSystemCall(AFS_IINC, iinc, 3);
- NewSystemCall(AFS_IDEC, idec, 3);
-#ifdef AFS_SGI_XFS_IOPS_ENV
- NewSystemCall(AFS_IOPEN64, iopen64, 4);
-#else
- NewSystemCall(AFS_IREAD, iread, 6);
- NewSystemCall(AFS_IWRITE, iwrite, 6);
-#endif
-
- /* last replace these */
- setgroupsp = Afs_xsetgroups;
-
- idbg_addfunc("afsuser", idbg_afsuser);
- return (0);
-}
-
-
-extern int afs_mount(), afs_unmount(), afs_root(), afs_statfs();
-#ifdef AFS_SGI65_ENV
-extern int afs_sync(OSI_VFS_DECL(afsp), int flags, struct cred *cr);
-#else
-extern int afs_sync(OSI_VFS_DECL(afsp), short flags, struct cred *cr);
-#endif
-extern int afs_vget(OSI_VFS_DECL(afsp), vnode_t ** vpp, struct fid *afidp);
-#ifdef MP
-struct vfsops afs_lockedvfsops =
-#else
-struct vfsops Afs_vfsops =
-#endif
-{
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
-#else
- VFS_POSITION_BASE,
-#endif
-#endif
- afs_mount,
-#ifdef AFS_SGI64_ENV
- fs_nosys, /* rootinit */
- fs_nosys, /* mntupdate */
- fs_dounmount,
-#endif
- afs_unmount,
- afs_root,
- afs_statfs,
- afs_sync,
- afs_vget,
- fs_nosys, /* mountroot */
-#ifdef AFS_SGI65_ENV
- fs_nosys, /* realvfsops */
- fs_import, /* import */
- fs_nosys, /* quotactl */
-#else
- fs_nosys, /* swapvp */
-#endif
-};
-extern struct afs_q VLRU; /*vcache LRU */
-
-#ifdef AFS_SGI64_ENV
-static bhv_desc_t afs_vfs_bhv;
-#endif
-afs_mount(struct vfs *afsp, vnode_t * mvp, struct mounta *uap,
-#ifdef AFS_SGI65_ENV
- char *attrs,
-#endif
- cred_t * cr)
-{
- AFS_STATCNT(afs_mount);
-
- if (!suser())
- return EPERM;
-
- if (mvp->v_type != VDIR)
- return ENOTDIR;
-
- if (afs_globalVFS) { /* Don't allow remounts. */
- return EBUSY;
- }
-
- afs_globalVFS = afsp;
- afsp->vfs_bsize = 8192;
- afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
- afsp->vfs_fsid.val[1] = afs_fstype;
-#ifdef AFS_SGI64_ENV
- vfs_insertbhv(afsp, &afs_vfs_bhv, &Afs_vfsops, &afs_vfs_bhv);
-#else
- afsp->vfs_data = NULL;
-#endif
- afsp->vfs_fstype = afs_fstype;
- afsp->vfs_dev = 0xbabebabe; /* XXX this should be unique */
-
-#ifndef AFS_NONFSTRANS
- if (nfs_rfsdisptab_v2)
- afs_xlatorinit_v2(nfs_rfsdisptab_v2);
- afs_xlatorinit_v3();
-#endif
- return 0;
-}
-
-afs_unmount(OSI_VFS_ARG(afsp), flags, cr)
- OSI_VFS_DECL(afsp);
- int flags;
- cred_t *cr;
-{
- extern int afs_afs_cold_shutdown;
- struct vcache *tvc;
- vnode_t *vp, *rootvp = NULL;
- register struct afs_q *tq;
- struct afs_q *uq;
- int error, fv_slept;
- OSI_VFS_CONVERT(afsp)
-
- AFS_STATCNT(afs_unmount);
-
- if (!suser())
- return EPERM;
-
- /*
- * flush all pages from inactive vnodes - return
- * EBUSY if any still in use
- */
- ObtainWriteLock(&afs_xvcache, 172);
- for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
- vp = (vnode_t *) tvc;
- if (error = afs_FlushVCache(tvc, &fv_slept))
- if (vp->v_flag & VROOT) {
- rootvp = vp;
- continue;
- } else {
- ReleaseWriteLock(&afs_xvcache);
- return error;
- }
- }
-
- /*
- * rootvp gets lots of ref counts
- */
- if (rootvp) {
- tvc = VTOAFS(rootvp);
- if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
- ReleaseWriteLock(&afs_xvcache);
- return EBUSY;
- }
- ReleaseWriteLock(&afs_xvcache);
- rootvp->v_count = 1;
- AFS_RELE(rootvp);
- ObtainWriteLock(&afs_xvcache, 173);
- afs_FlushVCache(tvc, &fv_slept);
- }
- ReleaseWriteLock(&afs_xvcache);
- afs_globalVFS = 0;
- afs_shutdown();
-#ifdef AFS_SGI65_ENV
- VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
-#endif
- return 0;
-}
-
-
-
-afs_root(OSI_VFS_ARG(afsp), avpp)
- OSI_VFS_DECL(afsp);
- struct vnode **avpp;
-{
- register afs_int32 code = 0;
- struct vrequest treq;
- register struct vcache *tvp = 0;
- OSI_VFS_CONVERT(afsp)
-
- AFS_STATCNT(afs_root);
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_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) {
- int s;
- VN_HOLD(AFSTOV(tvp));
- s = VN_LOCK(AFSTOV(tvp));
- AFSTOV(tvp)->v_flag |= VROOT;
- VN_UNLOCK(AFSTOV(tvp), s);
-
- afs_globalVFS = afsp;
- *avpp = AFSTOV(tvp);
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
- ICL_TYPE_INT32, code);
- return code;
-}
-
-afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
- OSI_VFS_DECL(afsp);
- struct statvfs *abp;
- struct vnode *avp; /* unused */
-{
- OSI_VFS_CONVERT(afsp)
-
- AFS_STATCNT(afs_statfs);
- abp->f_bsize = afsp->vfs_bsize;
- abp->f_frsize = 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 = abp->f_favail = 900000;
-
- abp->f_fsid = AFS_VFSMAGIC; /* magic */
- strcpy(abp->f_basetype, AFS_MOUNT_AFS);
- abp->f_flag = 0;
- abp->f_namemax = 256;
- return 0;
-}
-
-
-
-/*
- * sync's responsibilities include pushing back DELWRI pages
- * Things to watch out for:
- * 1) don't want to hold off new vnodes in the file system
- * while pushing back pages
- * 2) since we can deal with un-referenced vndoes need to watch
- * races with folks who recycle vnodes
- * Flags:
- * SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
- * when pushing DELWRI - only push old ones.
- * SYNC_PDFLUSH - push v_dpages.
- * SYNC_ATTR - sync attributes - note that ordering considerations
- * dictate that we also flush dirty pages
- * SYNC_WAIT - do synchronouse writes - inode & delwri
- * SYNC_NOWAIT - start delayed writes.
- * SYNC_DELWRI - look at inodes w/ delwri pages. Other flags
- * decide how to deal with them.
- * SYNC_CLOSE - flush delwri and invalidate others.
- * SYNC_FSDATA - push fs data (e.g. superblocks)
- */
-
-extern afs_int32 vcachegen;
-#define PREEMPT_MASK 0x7f
-#ifdef AFS_SGI64_ENV
-#define PREEMPT()
-#endif
-
-int
-afs_sync(OSI_VFS_DECL(afsp),
-#ifdef AFS_SGI65_ENV
- int flags,
-#else
- short flags,
-#endif
- struct cred *cr)
-{
- /* Why enable the vfs sync operation?? */
- int error, lasterr, preempt;
- struct vcache *tvc;
- struct vnode *vp;
- afs_uint32 lvcachegen;
- register struct afs_q *tq;
- struct afs_q *uq;
- int s;
- OSI_VFS_CONVERT(afsp)
-
- error = lasterr = 0;
- /*
- * if not interested in vnodes, skip all this
- */
-#ifdef AFS_SGI61_ENV
- if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_PDFLUSH)) == 0)
- goto end;
-#else /* AFS_SGI61_ENV */
- if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_ATTR)) == 0)
- goto end;
-#endif /* AFS_SGI61_ENV */
- loop:
- ObtainReadLock(&afs_xvcache);
- for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
- vp = (vnode_t *) tvc;
- /*
- * Since we push all dirty pages on last close/VOP_INACTIVE
- * we are only concerned with vnodes with
- * active reference counts.
- */
- s = VN_LOCK(vp);
- if (vp->v_count == 0) {
- VN_UNLOCK(vp, s);
- continue;
- }
- if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
- VN_UNLOCK(vp, s);
- continue;
- }
-
- /*
- * ignore vnodes which need no flushing
- */
- if (flags & SYNC_DELWRI) {
- if (!AFS_VN_DIRTY(vp)) {
- VN_UNLOCK(vp, s);
- continue;
- }
- }
-#ifdef AFS_SGI61_ENV
- else if (flags & SYNC_PDFLUSH) {
- if (!VN_GET_DPAGES(vp)) {
- VN_UNLOCK(vp, s);
- continue;
- }
- }
-#endif /* AFS_SGI61_ENV */
-
- vp->v_count++;
- VN_UNLOCK(vp, s);
- lvcachegen = vcachegen;
- ReleaseReadLock(&afs_xvcache);
-
- /*
- * Try to lock rwlock without sleeping. If we can't, we must
- * sleep for rwlock.
- */
- if (afs_rwlock_nowait(vp, 1) == 0) {
-#ifdef AFS_SGI61_ENV
- if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
-#else /* AFS_SGI61_ENV */
- if (flags & SYNC_BDFLUSH)
-#endif /* AFS_SGI61_ENV */
- {
- AFS_RELE(vp);
- ObtainReadLock(&afs_xvcache);
- if (vcachegen != lvcachegen) {
- ReleaseReadLock(&afs_xvcache);
- goto loop;
- }
- continue;
- }
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- }
-
- AFS_GUNLOCK();
- if (flags & SYNC_CLOSE) {
- PFLUSHINVALVP(vp, (off_t) 0, (off_t) tvc->m.Length);
- }
-#ifdef AFS_SGI61_ENV
- else if (flags & SYNC_PDFLUSH) {
- if (VN_GET_DPAGES(vp)) {
- pdflush(vp, B_ASYNC);
- }
- }
-#endif /* AFS_SGI61_ENV */
-
-
- if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
-#ifdef AFS_SGI61_ENV
- PFLUSHVP(vp, (off_t) tvc->m.Length,
- (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
-#else /* AFS_SGI61_ENV */
- if (flags & SYNC_WAIT)
- /* push all and wait */
- PFLUSHVP(vp, (off_t) tvc->m.Length, (off_t) 0, error);
- else if (flags & SYNC_BDFLUSH) {
- /* push oldest */
- error = pdflush(vp, B_ASYNC);
- } else {
- /* push all but don't wait */
- PFLUSHVP(vp, (off_t) tvc->m.Length, (off_t) B_ASYNC, error);
- }
-#endif /* AFS_SGI61_ENV */
- }
-
- /*
- * Release vp, check error and whether to preempt, and if
- * we let go of xvcache lock and someone has changed the
- * VLRU, restart the loop
- */
- AFS_GLOCK();
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- AFS_RELE(vp);
- if (error)
- lasterr = error;
- if ((++preempt & PREEMPT_MASK) == 0) {
- AFS_GUNLOCK();
- PREEMPT();
- AFS_GLOCK();
- }
- ObtainReadLock(&afs_xvcache);
- if (vcachegen != lvcachegen) {
- ReleaseReadLock(&afs_xvcache);
- goto loop;
- }
- }
- ReleaseReadLock(&afs_xvcache);
- end:
- return lasterr;
-}
-
-
-afs_vget(OSI_VFS_DECL(afsp), vnode_t ** avcp, struct fid * fidp)
-{
- struct VenusFid vfid;
- struct vrequest treq;
- register struct cell *tcell;
- register afs_int32 code = 0;
- afs_int32 ret;
-
-#if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
- afs_fid2_t *afid2;
-#endif
-
- OSI_VFS_CONVERT(afsp)
-
- AFS_STATCNT(afs_vget);
-
- *avcp = NULL;
-
-#if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
- afid2 = (afs_fid2_t *) fidp;
- if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
- /* It's a checkpoint restart fid. */
- tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
- if (!tcell) {
- code = ENOENT;
- goto out;
- }
- vfid.Cell = tcell->cellNum;
- afs_PutCell(tcell, READ_LOCK);
- vfid.Fid.Volume = afid2->af_volid;
- vfid.Fid.Vnode = afid2->af_vno;
- vfid.Fid.Unique = afid2->af_uniq;
-
- if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
- goto out;
- *avcp =
- (vnode_t *) afs_GetVCache(&vfid, &treq, NULL, (struct vcache *)0);
- if (!*avcp) {
- code = ENOENT;
- }
- goto out;
- }
-#endif
-
- if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
- goto out;
- code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
-
- out:
- afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
- ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
- code = afs_CheckCode(code, &treq, 42);
- return code;
-}
-
-
-#ifdef MP /* locked versions of vfs operations. */
-
-/* wrappers for vfs calls */
-#ifdef AFS_SGI64_ENV
-#define AFS_MP_VFS_ARG(A) bhv_desc_t A
-#else
-#define AFS_MP_VFS_ARG(A) struct vfs A
-#endif
-
-int
-mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
-#ifdef AFS_SGI65_ENV
- char *d,
-#endif
- struct cred *e)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_mount(a, b, c, d
-#ifdef AFS_SGI65_ENV
- , e
-#endif
- );
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_unmount(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_root(a, b);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_sync(AFS_MP_VFS_ARG(*a),
-#ifdef AFS_SGI65_ENV
- int b,
-#else
- short b,
-#endif
- struct cred *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_sync(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvfsops.vfs_vget(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-struct vfsops Afs_vfsops = {
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
-#else
- VFS_POSITION_BASE,
-#endif
-#endif
- mp_afs_mount,
-#ifdef AFS_SGI64_ENV
- fs_nosys, /* rootinit */
- fs_nosys, /* mntupdate */
- fs_dounmount,
-#endif
- mp_afs_unmount,
- mp_afs_root,
- mp_afs_statvfs,
- mp_afs_sync,
- mp_afs_vget,
- fs_nosys, /* mountroot */
-#ifdef AFS_SGI65_ENV
- fs_nosys, /* realvfsops */
- fs_import, /* import */
- fs_nosys, /* quotactl */
-#else
- fs_nosys, /* swapvp */
-#endif
-};
-
-#endif /* MP */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_vm.c,v 1.8 2003/07/15 23:14:23 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "sys/flock.h" /* for IGN_PID */
-
-extern struct vnodeops Afs_vnodeops;
-
-/* 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.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- int s, code;
- vnode_t *vp = &avc->v;
-
- if (avc->vrefCount != 0)
- return EBUSY;
-
- if (avc->opens != 0)
- return EBUSY;
-
- /*
- * Just in case someone is still referring to the vnode we give up
- * trying to get rid of this guy.
- */
- if (CheckLock(&avc->lock) || LockWaiters(&avc->lock))
- return EBUSY;
-
- s = VN_LOCK(vp);
-
- /*
- * we just need to avoid the race
- * in vn_rele between the ref count going to 0 and VOP_INACTIVE
- * finishing up.
- * Note that although we checked vcount above, we didn't have the lock
- */
- if (vp->v_count > 0 || (vp->v_flag & VINACT)) {
- VN_UNLOCK(vp, s);
- return EBUSY;
- }
- VN_UNLOCK(vp, s);
-
- /*
- * Since we store on last close and on VOP_INACTIVE
- * there should be NO dirty pages
- * Note that we hold the xvcache lock the entire time.
- */
- AFS_GUNLOCK();
- PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
- AFS_GLOCK();
-
- /* afs_chkpgoob will drop and re-acquire the global lock. */
- afs_chkpgoob(vp, 0);
- osi_Assert(!VN_GET_PGCNT(vp));
- osi_Assert(!AFS_VN_MAPPED(vp));
- osi_Assert(!AFS_VN_DIRTY(&avc->v));
-
-#if defined(AFS_SGI65_ENV)
- if (vp->v_filocks)
- cleanlocks(vp, IGN_PID, 0);
- mutex_destroy(&vp->v_filocksem);
-#else /* AFS_SGI65_ENV */
- if (vp->v_filocksem) {
- if (vp->v_filocks)
-#ifdef AFS_SGI64_ENV
- cleanlocks(vp, &curprocp->p_flid);
-#else
- cleanlocks(vp, IGN_PID, 0);
-#endif
- osi_Assert(vp->v_filocks == NULL);
- mutex_destroy(vp->v_filocksem);
- kmem_free(vp->v_filocksem, sizeof *vp->v_filocksem);
- vp->v_filocksem = NULL;
- }
-#endif /* AFS_SGI65_ENV */
-
- if (avc->vrefCount)
- osi_Panic("flushVcache: vm race");
-#ifdef AFS_SGI64_ENV
- AFS_GUNLOCK();
- vnode_pcache_reclaim(vp); /* this can sleep */
- vnode_pcache_free(vp);
- if (vp->v_op != &Afs_vnodeops) {
- VOP_RECLAIM(vp, FSYNC_WAIT, code);
- }
- AFS_GLOCK();
-#ifdef AFS_SGI65_ENV
-#ifdef VNODE_TRACING
- ktrace_free(vp->v_trace);
-#endif /* VNODE_TRACING */
- vn_bhv_remove(VN_BHV_HEAD(vp), &(avc->vc_bhv_desc));
- vn_bhv_head_destroy(&(vp->v_bh));
- destroy_bitlock(&vp->v_pcacheflag);
- mutex_destroy(&vp->v_buf_lock);
-#else
- bhv_remove(VN_BHV_HEAD(vp), &(avc->vc_bhv_desc));
- bhv_head_destroy(&(vp->v_bh));
-#endif
- vp->v_flag = 0; /* debug */
-#if defined(DEBUG) && defined(VNODE_INIT_BITLOCK)
- destroy_bitlock(&vp->v_flag);
-#endif
-#ifdef INTR_KTHREADS
- AFS_VN_DESTROY_BUF_LOCK(vp);
-#endif
-#endif /* AFS_SGI64_ENV */
-
- return 0;
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- /* current remapf restriction - cannot have VOP_RWLOCK */
- osi_Assert(OSI_GET_LOCKID() != avc->vc_rwlockid);
- if (((vnode_t *) avc)->v_type == VREG && AFS_VN_MAPPED(((vnode_t *) avc)))
- remapf(((vnode_t *) avc), 0, 0);
- PTOSSVP(AFSTOV(avc), (off_t) 0, (off_t) MAXLONG);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 62);
-}
-
-/* Flush and invalidate pages, for fsync() with INVAL flag
- *
- * Locking: only the global lock is held.
- */
-void
-osi_VM_FSyncInval(struct vcache *avc)
-{
- AFS_GUNLOCK();
- PFLUSHINVALVP((vnode_t *) avc, (off_t) 0, (off_t) avc->m.Length);
- AFS_GLOCK();
-}
-
-/* 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)
-{
- int error;
- osi_Assert(valusema(&avc->vc_rwlock) <= 0);
- osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
- osi_Assert(avc->vrefCount > 0);
- ReleaseWriteLock(&avc->lock);
- /* We may call back into AFS via:
- * pflushvp->chunkpush->do_pdflush->mp_afs_bmap
- */
- AFS_GUNLOCK();
-
- /* Write out dirty pages list to avoid B_DELWRI buffers. */
- while (VN_GET_DPAGES((vnode_t *) avc)) {
- pdflush(AFSTOV(avc), 0);
- }
-
- PFLUSHVP(AFSTOV(avc), (off_t) avc->m.Length, (off_t) 0, error);
- AFS_GLOCK();
- if (error) {
- /*
- * If this fails (due to quota overage, etc.)
- * what can we do?? we need to sure that
- * that the VM cache is cleared of dirty pages
- * We note that pinvalfree ignores write errors & otherwise
- * does what we want (we don't use this normally since
- * it also unhashes pages ..)
- */
- PINVALFREE((vnode_t *) avc, avc->m.Length);
- }
- ObtainWriteLock(&avc->lock, 121);
- if (error && avc->m.LinkCount)
- cmn_err(CE_WARN,
- "AFS:Failed to push back pages for vnode 0x%x error %d (from afs_StoreOnLastReference)",
- avc, error);
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- vnode_t *vp = (vnode_t *) avc;
-
- remapf(vp, /*avc->m.Length */ 0, 0);
-
- /* Used to grab locks and recheck avc->m.DataVersion and
- * avc->execsOrWriters here, but we have to drop locks before calling
- * ptossvp() anyway, so why bother.
- */
-
- /*
- * ptossvp tosses all pages associated with this vnode
- * All in-use pages are marked BAD
- */
- PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
- PTOSSVP(&avc->v, (off_t) alen, (off_t) MAXLONG);
-}
+++ /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
- */
-
-/*
- * SGI specific vnodeops + other misc interface glue
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/IRIX/osi_vnodeops.c,v 1.14 2003/07/15 23:14:23 shadow Exp $");
-
-#ifdef AFS_SGI62_ENV
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "sys/flock.h"
-#include "afs/nfsclient.h"
-
-/* AFSBSIZE must be at least the size of a page, else the client will hang.
- * For 64 bit platforms, the page size is more than 8K.
- */
-#define AFSBSIZE _PAGESZ
-extern struct afs_exporter *root_exported;
-extern void afs_chkpgoob(vnode_t *, pgno_t);
-
-static void afs_strategy();
-static int afs_xread(), afs_xwrite();
-static int afs_xbmap(), afs_map(), afs_reclaim();
-#ifndef AFS_SGI65_ENV
-static int afs_addmap(), afs_delmap();
-#endif
-extern int afs_open(), afs_close(), afs_ioctl(), afs_getattr(), afs_setattr();
-extern int afs_access(), afs_lookup();
-extern int afs_create(), afs_remove(), afs_link(), afs_rename();
-extern int afs_mkdir(), afs_rmdir(), afs_readdir();
-extern int afs_symlink(), afs_readlink(), afs_fsync(), afs_fid(),
-afs_frlock();
-static int afs_seek(OSI_VC_DECL(a), off_t b, off_t * c);
-#ifdef AFS_SGI64_ENV
-extern int afs_xinactive();
-#else
-extern void afs_xinactive();
-#endif
-
-extern void afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b);
-extern void afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T b);
-
-extern int afs_fid2();
-
-static int afsrwvp(register struct vcache *avc, register struct uio *uio,
- enum uio_rw rw, int ioflag,
-#ifdef AFS_SGI64_ENV
- struct cred *cr, struct flid *flp);
-#else
- struct cred *cr);
-#endif
-#ifdef MP
-static void mp_afs_rwlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
-static void mp_afs_rwunlock(OSI_VN_DECL(a), AFS_RWLOCK_T b);
-struct vnodeops afs_lockedvnodeops =
-#else
-struct vnodeops Afs_vnodeops =
-#endif
-{
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
-#else
- VNODE_POSITION_BASE,
-#endif
-#endif
- afs_open,
- afs_close,
- afs_xread,
- afs_xwrite,
- afs_ioctl,
- fs_setfl,
- afs_getattr,
- afs_setattr,
- afs_access,
- afs_lookup,
- afs_create,
- afs_remove,
- afs_link,
- afs_rename,
- afs_mkdir,
- afs_rmdir,
- afs_readdir,
- afs_symlink,
- afs_readlink,
- afs_fsync,
- afs_xinactive,
- afs_fid,
- afs_fid2,
- afs_rwlock,
- afs_rwunlock,
- afs_seek,
- fs_cmp,
- afs_frlock,
- fs_nosys, /* realvp */
- afs_xbmap,
- afs_strategy,
- afs_map,
-#ifdef AFS_SGI65_ENV
- fs_noerr, /* addmap - devices only */
- fs_noerr, /* delmap - devices only */
-#else
- afs_addmap,
- afs_delmap,
-#endif
- fs_poll, /* poll */
- fs_nosys, /* dump */
- fs_pathconf,
- fs_nosys, /* allocstore */
- fs_nosys, /* fcntl */
- afs_reclaim, /* reclaim */
- fs_nosys, /* attr_get */
- fs_nosys, /* attr_set */
- fs_nosys, /* attr_remove */
- fs_nosys, /* attr_list */
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- fs_cover,
- (vop_link_removed_t) fs_noval,
- fs_vnode_change,
- fs_tosspages,
- fs_flushinval_pages,
- fs_flush_pages,
- fs_invalfree_pages,
- fs_pages_sethole,
- (vop_commit_t) fs_nosys,
- (vop_readbuf_t) fs_nosys,
- fs_strgetmsg,
- fs_strputmsg,
-#else
- fs_mount,
-#endif
-#endif
-};
-
-#ifndef MP
-struct vnodeops *afs_ops = &Afs_vnodeops;
-#endif
-
-int
-afs_frlock(OSI_VN_DECL(vp), int cmd, struct flock *lfp, int flag,
- off_t offset,
-#ifdef AFS_SGI65_ENV
- vrwlock_t vrwlock,
-#endif
- cred_t * cr)
-{
- int error;
- OSI_VN_CONVERT(vp)
-#ifdef AFS_SGI65_ENV
- struct flid flid;
- int pid;
- get_current_flid(&flid);
- pid = flid.fl_pid;
-#endif
-
- /*
- * Since AFS doesn't support byte-wise locks (and simply
- * says yes! we handle byte locking locally only.
- * This makes lots of things work much better
- * XXX This doesn't properly handle moving from a
- * byte-wise lock up to a full file lock (we should
- * remove the byte locks ..) Of course neither did the
- * regular AFS way ...
- *
- * For GETLK we do a bit more - we first check any byte-wise
- * locks - if none then check for full AFS file locks
- */
- if (cmd == F_GETLK || lfp->l_whence != 0 || lfp->l_start != 0
- || (lfp->l_len != MAXEND && lfp->l_len != 0)) {
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- AFS_GUNLOCK();
-#ifdef AFS_SGI65_ENV
- error =
- fs_frlock(OSI_VN_ARG(vp), cmd, lfp, flag, offset, vrwlock, cr);
-#else
- error = fs_frlock(vp, cmd, lfp, flag, offset, cr);
-#endif
- AFS_GLOCK();
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- if (error || cmd != F_GETLK)
- return error;
- if (lfp->l_type != F_UNLCK)
- /* found some blocking lock */
- return 0;
- /* fall through to check for full AFS file locks */
- }
-
- /* map BSD style to plain - we don't call reclock()
- * and its only there that the difference is important
- */
- switch (cmd) {
- case F_GETLK:
- case F_RGETLK:
- break;
- case F_SETLK:
- case F_RSETLK:
- break;
- case F_SETBSDLK:
- cmd = F_SETLK;
- break;
- case F_SETLKW:
- case F_RSETLKW:
- break;
- case F_SETBSDLKW:
- cmd = F_SETLKW;
- break;
- default:
- return EINVAL;
- }
-
- AFS_GUNLOCK();
-
- error = convoff(vp, lfp, 0, offset, SEEKLIMIT
-#ifdef AFS_SGI64_ENV
- , OSI_GET_CURRENT_CRED()
-#endif /* AFS_SGI64_ENV */
- );
-
- AFS_GLOCK();
- if (!error) {
-#ifdef AFS_SGI65_ENV
- error = afs_lockctl(vp, lfp, cmd, cr, pid);
-#else
- error = afs_lockctl(vp, lfp, cmd, cr, OSI_GET_CURRENT_PID());
-#endif
- }
- return error;
-}
-
-
-/*
- * We need to get the cache hierarchy right.
- * First comes the page cache - pages are hashed based on afs
- * vnode and offset. It is important to have things hashed here
- * for the VM/paging system to work.
- * Note that the paging system calls VOP_READ with the UIO_NOSPACE -
- * it simply requires that somehow the page is hashed
- * upon successful return.
- * This means in afs_read we
- * must call the 'chunk' code that handles page insertion. In order
- * to actually get the data, 'chunk' calls the VOP_STRATEGY routine.
- * This is basically the std afs_read routine - validating and
- * getting the info into the Dcache, then calling VOP_READ.
- * The only bad thing here is that by calling VOP_READ (and VOP_WRITE
- * to fill the cache) we will get 2 copies of these pages into the
- * page cache - one hashed on afs vnode and one on efs vnode. THis
- * is wasteful but does no harm. A potential solution involves
- * causing an ASYNC flush of the newly fetched cache data and
- * doing direct I/O on the read side....
- */
-/* ARGSUSED */
-#ifdef AFS_SGI64_ENV
-static int
-afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
- struct flid *flp;
-#else
-static int
-afs_xread(OSI_VC_ARG(avc), uiop, ioflag, cr)
-#endif
-OSI_VC_DECL(avc);
- struct uio *uiop;
- int ioflag;
- struct cred *cr;
-{
- int code;
- OSI_VC_CONVERT(avc)
-
- osi_Assert(avc->v.v_count > 0);
- if (avc->v.v_type != VREG)
- return EISDIR;
-
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- if (!(ioflag & IO_ISLOCKED))
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_READ);
-#endif
- code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr, flp);
-#ifdef AFS_SGI65_ENV
- if (!(ioflag & IO_ISLOCKED))
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_READ);
-#endif
-#else
- code = afsrwvp(avc, uiop, UIO_READ, ioflag, cr);
-#endif
- return code;
-}
-
-/* ARGSUSED */
-#ifdef AFS_SGI64_ENV
-static int
-afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr, flp)
- struct flid *flp;
-#else
-static int
-afs_xwrite(OSI_VC_ARG(avc), uiop, ioflag, cr)
-#endif
-OSI_VC_DECL(avc);
- struct uio *uiop;
- int ioflag;
- struct cred *cr;
-{
- int code;
- OSI_VC_CONVERT(avc)
-
- osi_Assert(avc->v.v_count > 0);
- if (avc->v.v_type != VREG)
- return EISDIR;
-
- if (ioflag & IO_APPEND)
- uiop->uio_offset = avc->m.Length;
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- if (!(ioflag & IO_ISLOCKED))
- AFS_RWLOCK(((vnode_t *) avc), VRWLOCK_WRITE);
-#endif
- code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr, flp);
-#ifdef AFS_SGI65_ENV
- if (!(ioflag & IO_ISLOCKED))
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
-#else
- code = afsrwvp(avc, uiop, UIO_WRITE, ioflag, cr);
-#endif
- return code;
-}
-
-static int prra = 0;
-static int prnra = 0;
-static int acchk = 0;
-static int acdrop = 0;
-
-static int
-afsrwvp(register struct vcache *avc, register struct uio *uio, enum uio_rw rw,
- int ioflag,
-#ifdef AFS_SGI64_ENV
- struct cred *cr, struct flid *flp)
-#else
- struct cred *cr)
-#endif
-{
- register struct vnode *vp = AFSTOV(avc);
- struct buf *bp;
- daddr_t bn;
- size_t acnt, cnt;
- int off, newoff;
- ssize_t bsize, rem, len;
- int error;
- struct bmapval bmv[2];
- int nmaps, didFakeOpen = 0;
- struct vrequest treq;
- struct dcache *tdc;
- int counter = 0;
-
- osi_Assert((valusema(&avc->vc_rwlock) <= 0)
- && (OSI_GET_LOCKID() == avc->vc_rwlockid));
-
-
- newoff = uio->uio_resid + uio->uio_offset;
- if (uio->uio_resid <= 0) {
- return (0);
- }
- if (uio->uio_offset < 0 || (signed long)newoff < 0) {
- return (EINVAL);
- }
- if (ioflag & IO_DIRECT)
- return EINVAL;
-
- if (rw == UIO_WRITE && vp->v_type == VREG && newoff > uio->uio_limit) {
- return (EFBIG);
- }
-
- afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32, 0);
-
- /* get a validated vcache entry */
- afs_InitReq(&treq, cr);
- error = afs_VerifyVCache(avc, &treq);
- if (error)
- return afs_CheckCode(error, &treq, 51);
-
- /*
- * flush any stale pages - this will unmap
- * and invalidate all pages for vp (NOT writing them back!)
- */
- osi_FlushPages(avc, cr);
-
- if (cr && AFS_NFSXLATORREQ(cr) && rw == UIO_READ) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ))
- return EACCES;
- }
- /*
- * To handle anonymous calls to VOP_STRATEGY from afs_sync/sync/bdflush
- * we need better than the callers credentials. So we squirrel away
- * the last writers credentials
- */
- if (rw == UIO_WRITE || (rw == UIO_READ && avc->cred == NULL)) {
- ObtainWriteLock(&avc->lock, 92);
- if (avc->cred)
- crfree(avc->cred);
- crhold(cr);
- avc->cred = cr;
- ReleaseWriteLock(&avc->lock);
- }
-
- /*
- * We have to bump the open/exwriters field here
- * courtesy of the nfs xlator
- * because there're no open/close nfs rpc's to call our afs_open/close.
- */
- if (root_exported && rw == UIO_WRITE) {
- ObtainWriteLock(&avc->lock, 234);
- if (root_exported) {
- didFakeOpen = 1;
- afs_FakeOpen(avc);
- }
- ReleaseWriteLock(&avc->lock);
- }
- error = 0;
-
- if (rw == UIO_WRITE) {
- ObtainWriteLock(&avc->lock, 330);
- avc->states |= CDirty;
- ReleaseWriteLock(&avc->lock);
- }
-
- AFS_GUNLOCK();
-
- do {
- /* If v_dpages is set SGI 5.3 will convert those pages to
- * B_DELWRI in chunkread and getchunk. Write the pages out
- * before we trigger that behavior. For 6.1, dirty pages stay
- * around too long and we should get rid of them as quickly
- * as possible.
- */
- while (VN_GET_DPAGES(vp))
- pdflush(vp, 0);
-
- if (avc->vc_error) {
- error = avc->vc_error;
- break;
- }
- bsize = AFSBSIZE; /* why not?? */
- off = uio->uio_offset % bsize;
- bn = BTOBBT(uio->uio_offset - off);
- /*
- * decrease bsize - otherwise we will
- * get 'extra' pages in the cache for this
- * vnode that we would need to flush when
- * calling e.g. ptossvp.
- * So we can use Length in ptossvp,
- * we make sure we never go more than to the file size
- * rounded up to a page boundary.
- * That doesn't quite work, since we may get a page hashed to
- * the vnode w/o updating the length. Thus we always use
- * MAXLONG in ptossvp to be safe.
- */
- if (rw == UIO_READ) {
- /*
- * read/paging in a normal file
- */
- rem = avc->m.Length - (afs_int32) uio->uio_offset;
- if (rem <= 0)
- /* EOF */
- break;
- /*
- * compute minimum of rest of block and rest of file
- */
- cnt = MIN(bsize - off, rem);
- osi_Assert((off + cnt) <= bsize);
- bsize = ctob(btoc(off + cnt));
- len = BTOBBT(bsize);
- nmaps = 1;
- bmv[0].bn = bmv[0].offset = bn;
- bmv[0].length = len;
- bmv[0].bsize = bsize;
- bmv[0].pboff = off;
- bmv[0].pbsize = MIN(cnt, uio->uio_resid);
- bmv[0].eof = 0;
-#ifdef AFS_SGI64_ENV
- bmv[0].pbdev = vp->v_rdev;
- bmv[0].pmp = uio->uio_pmp;
-#endif
- osi_Assert(cnt > 0);
- /*
- * initiate read-ahead if it looks like
- * we are reading sequentially OR they want
- * more than one 'bsize' (==AFSBSIZE) worth
- * XXXHack - to avoid DELWRI buffers we can't
- * do read-ahead on any file that has potentially
- * dirty mmap pages.
- */
- if ((avc->lastr + BTOBB(AFSBSIZE) == bn
- || uio->uio_resid > AFSBSIZE)
-#ifdef AFS_SGI61_ENV
- && (!AFS_VN_MAPPED(vp))
-#else /* AFS_SGI61_ENV */
- && ((vp->v_flag & VWASMAP) == 0)
-#endif /* AFS_SGI61_ENV */
- ) {
- rem -= cnt;
- if (rem > 0) {
- bsize = AFSBSIZE;
- bmv[1].bn = bmv[1].offset = bn + len;
- osi_Assert((BBTOB(bn + len) % bsize) == 0);
- acnt = MIN(bsize, rem);
- bsize = ctob(btoc(acnt));
- len = BTOBBT(bsize);
- nmaps = 2;
- bmv[1].length = len;
- bmv[1].eof = 0;
- bmv[1].bsize = bsize;
- bmv[1].pboff = 0;
- bmv[1].pbsize = acnt;
-#ifdef AFS_SGI64_ENV
- bmv[1].pmp = uio->uio_pmp;
- bmv[1].pbdev = vp->v_rdev;
-#endif
- }
- }
-#ifdef DEBUG
- else if (prnra)
- printf
- ("NRA:vp 0x%x lastr %d bn %d len %d cnt %d bsize %d rem %d resid %d\n",
- vp, avc->lastr, bn, len, cnt, bsize, rem,
- uio->uio_resid);
-#endif
-
- avc->lastr = bn;
- bp = chunkread(vp, bmv, nmaps, cr);
- /*
- * If at a chunk boundary, start prefetch of next chunk.
- */
- if (counter == 0 || AFS_CHUNKOFFSET(off) == 0) {
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 562);
- tdc = afs_FindDCache(avc, off);
- if (tdc) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, cr, &treq);
- afs_PutDCache(tdc);
- }
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- }
- counter++;
- } else {
- /*
- * writing a normal file
- */
- /*
- * 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 (counter > 0 && AFS_CHUNKOFFSET(uio->uio_offset) == 0) {
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 90);
- error = afs_DoPartialWrite(avc, &treq);
- if (error == 0)
- avc->states |= CDirty;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- if (error)
- break;
- }
- counter++;
-
- cnt = MIN(bsize - off, uio->uio_resid);
- bsize = ctob(btoc(off + cnt));
- len = BTOBBT(bsize);
- bmv[0].bn = bn;
- bmv[0].offset = bn;
- bmv[0].length = len;
- bmv[0].eof = 0;
- bmv[0].bsize = bsize;
- bmv[0].pboff = off;
- bmv[0].pbsize = cnt;
-#ifdef AFS_SGI64_ENV
- bmv[0].pmp = uio->uio_pmp;
-#endif
-
- if (cnt == bsize)
- bp = getchunk(vp, bmv, cr);
- else
- bp = chunkread(vp, bmv, 1, cr);
-
- avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
- }
- if (bp->b_flags & B_ERROR) {
- /*
- * Since we compile -signed, b_error is a signed
- * char when it should ba an unsigned char.
- * This can cause some errors codes to be interpreted
- * as negative #s
- */
- error = (unsigned char)(bp->b_error);
- if (!error)
- error = EIO;
-#ifdef DEBUG
- if (acchk && error) {
- cmn_err(CE_WARN, "bp 0x%x has error %d\n", bp, error);
- if (acdrop)
- debug("AFS");
- }
-#endif
- brelse(bp);
- break;
- }
-
- osi_Assert(bp->b_error == 0);
-
- if (uio->uio_segflg != UIO_NOSPACE)
- (void)bp_mapin(bp);
- AFS_UIOMOVE(bp->b_un.b_addr + bmv[0].pboff, cnt, rw, uio, error);
- if (rw == UIO_READ || error) {
- if (bp->b_flags & B_DELWRI) {
- bawrite(bp);
- } else
- brelse(bp);
- } else {
- /*
- * m.Length is the maximum number of bytes known to be in the file.
- * Make sure it is at least as high as the last byte we just wrote
- * into the buffer.
- */
- if (avc->m.Length < (afs_int32) uio->uio_offset) {
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 235);
- avc->m.Length = uio->uio_offset;
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- }
- if (uio->uio_fmode & FSYNC) {
- error = bwrite(bp);
- } else if (off + cnt < bsize) {
- bawrite(bp); /* was bdwrite */
- } else {
- bp->b_flags |= B_AGE;
- bawrite(bp);
- }
- /*
- * Since EIO on an unlinked file is non-intuitive - give some
- * explanation
- */
- if (error) {
- if (avc->m.LinkCount == 0)
- cmn_err(CE_WARN,
- "AFS: Process pid %d write error %d writing to unlinked file.",
- OSI_GET_CURRENT_PID(), error);
- }
- }
- } while (!error && uio->uio_resid > 0);
- afs_chkpgoob(&avc->v, btoc(avc->m.Length));
-
- AFS_GLOCK();
-
- if (rw == UIO_WRITE && error == 0 && (avc->states & CDirty)) {
- ObtainWriteLock(&avc->lock, 405);
- error = afs_DoPartialWrite(avc, &treq);
- ReleaseWriteLock(&avc->lock);
- }
-
- if (!error) {
-#ifdef AFS_SGI61_ENV
- if (((ioflag & IO_SYNC) || (ioflag & IO_DSYNC)) && (rw == UIO_WRITE)
- && !AFS_NFSXLATORREQ(cr)) {
- error = afs_fsync(avc, 0, cr);
- }
-#else /* AFS_SGI61_ENV */
- if ((ioflag & IO_SYNC) && (rw == UIO_WRITE) && !AFS_NFSXLATORREQ(cr)) {
- error = afs_fsync(avc, 0, cr);
- }
-#endif /* AFS_SGI61_ENV */
- }
- if (didFakeOpen) {
- ObtainWriteLock(&avc->lock, 236);
- afs_FakeClose(avc, cr); /* XXXX For nfs trans XXXX */
- ReleaseWriteLock(&avc->lock);
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_GRDWR, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, ioflag, ICL_TYPE_INT32, rw, ICL_TYPE_INT32,
- error);
-
- return (error);
-}
-
-int
-afs_xbmap(OSI_VC_ARG(avc), offset, count, flag, cr, bmv, nbmv)
-OSI_VC_DECL(avc);
- off_t offset;
- ssize_t count;
- int flag;
- struct cred *cr;
- struct bmapval *bmv;
- int *nbmv;
-{
- int bsize; /* server's block size in bytes */
- off_t off;
- size_t rem, cnt;
- OSI_VC_CONVERT(avc)
-
- bsize = AFSBSIZE;
- off = offset % bsize; /* offset into block */
- bmv->bn = BTOBBT(offset - off);
- bmv->offset = bmv->bn;
- bmv->pboff = off;
- rem = avc->m.Length - offset;
- if (rem <= 0)
- cnt = 0; /* EOF */
- else
- cnt = MIN(bsize - off, rem);
-
- /*
- * It is benign to ignore *nbmv > 1, since it is only for requesting
- * readahead.
- */
-
- /*
- * Don't map more than up to next page if at end of file
- * See comment in afsrwvp
- */
- osi_Assert((off + cnt) <= bsize);
- bsize = ctob(btoc(off + cnt));
- bmv->pbsize = MIN(cnt, count);
- bmv->eof = 0;
-#ifdef AFS_SGI64_ENV
- bmv->pmp = NULL;
- bmv->pbdev = avc->v.v_rdev;
-#endif
- bmv->bsize = bsize;
- bmv->length = BTOBBT(bsize);
- *nbmv = 1;
- return (0);
-}
-
-/*
- * called out of chunkread from afs_xread & clusterwrite to push dirty
- * pages back - this routine
- * actually does the reading/writing by calling afs_read/afs_write
- * bp points to a set of pages that have been inserted into
- * the page cache hashed on afs vp.
- */
-static void
-afs_strategy(OSI_VC_ARG(avc), bp)
-OSI_VC_DECL(avc);
- struct buf *bp;
-{
- uio_t auio;
- uio_t *uio = &auio;
- iovec_t aiovec;
- int error;
- struct cred *cr;
- OSI_VC_CONVERT(avc)
- vnode_t *vp = (vnode_t *) avc;
-
- /*
- * We can't afford DELWRI buffers for 2 reasons:
- * 1) Since we can call underlying EFS, we can require a
- * buffer to flush a buffer. This leads to 2 potential
- * recursions/deadlocks
- * a) if all buffers are DELWRI afs buffers, then
- * ngeteblk -> bwrite -> afs_strategy -> afs_write ->
- * UFS_Write -> efs_write -> ngeteblk .... could
- * recurse a long ways!
- * b) brelse -> chunkhold which can call dchunkpush
- * will look for any DELWRI buffers and call strategy
- * on them. This can then end up via UFS_Write
- * recursing
- * Current hack:
- * a) We never do bdwrite(s) on AFS buffers.
- * b) We call pdflush with B_ASYNC
- * c) in chunkhold where it can set a buffer DELWRI
- * we immediatly do a clusterwrite for AFS vp's
- * XXX Alas, 'c' got dropped in 5.1 so its possible to get DELWRI
- * buffers if someone has mmaped the file and dirtied it then
- * reads/faults it again.
- * Instead - wherever we call chunkread/getchunk we check for a
- * returned bp with DELWRI set, and write it out immediately
- */
- if (CheckLock(&avc->lock) && VN_GET_DBUF(vp)) {
- printf("WARN: afs_strategy vp=%x, v_dbuf=%x bp=%x\n", vp,
- VN_GET_DBUF(vp), bp);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- iodone(bp);
- return;
- }
- if (bp->b_error != 0)
- printf("WARNING: afs_strategy3 vp=%x, bp=%x, err=%x\n", vp, bp,
- bp->b_error);
-
- /*
- * To get credentials somewhat correct (we may be called from bdflush/
- * sync) we use saved credentials in Vcache.
- * We must hold them since someone else could change them
- */
- ObtainReadLock(&avc->lock);
- if (bp->b_flags & B_READ) {
- if (BBTOB(bp->b_blkno) >= avc->m.Length) {
- /* we are responsible for zero'ing the page */
- caddr_t c;
- c = bp_mapin(bp);
- memset(c, 0, bp->b_bcount);
- iodone(bp);
- ReleaseReadLock(&avc->lock);
- return;
- }
- } else if ((avc->states & CWritingUFS) && (bp->b_flags & B_DELWRI)) {
- bp->b_ref = 3;
- ReleaseReadLock(&avc->lock);
- iodone(bp);
- return;
- }
- cr = avc->cred;
- osi_Assert(cr);
- crhold(cr);
- ReleaseReadLock(&avc->lock);
-
- aiovec.iov_base = bp_mapin(bp);
- uio->uio_iov = &aiovec;
- uio->uio_iovcnt = 1;
- uio->uio_resid = aiovec.iov_len = bp->b_bcount;
- uio->uio_offset = BBTOB(bp->b_blkno);
- uio->uio_segflg = UIO_SYSSPACE;
- uio->uio_limit = RLIM_INFINITY; /* we checked the limit earlier */
-#ifdef AFS_SGI64_ENV
- uio->uio_pmp = NULL;
-#endif
-
- if (bp->b_flags & B_READ) {
- uio->uio_fmode = FREAD;
- error = afs_read(vp, uio, cr, 0, 0, 0);
- } else {
- uio->uio_fmode = FWRITE;
- error = afs_write(vp, uio, 0, cr, 0);
- }
- crfree(cr);
-
-#ifdef DEBUG
- if (acchk && error) {
- cmn_err(CE_WARN, "vp 0x%x has error %d\n", vp, error);
- if (acdrop)
- debug("AFS");
- }
-#endif
- if (error) {
- bp->b_error = error;
- bp->b_flags |= B_ERROR;
- if ((uio->uio_fmode == FWRITE) && !avc->vc_error)
- avc->vc_error = error;
- }
- iodone(bp);
- return;
-}
-
-/* ARGSUSED */
-static int
-afs_seek(OSI_VC_ARG(avc), ooff, noffp)
-OSI_VC_DECL(avc);
- off_t ooff;
- off_t *noffp;
-{
- return *noffp < 0 ? EINVAL : 0;
-}
-
-#if !defined(AFS_SGI65_ENV)
-/* Irix 6.5 uses addmap/delmap only for devices. */
-/* ARGSUSED */
-static int
-afs_addmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, cr)
- off_t off;
-OSI_VC_DECL(avc);
- struct pregion *prp;
- addr_t addr;
- size_t len;
- u_int prot, maxprot;
- u_int flags;
- struct cred *cr;
-{
- OSI_VC_CONVERT(avc)
- struct vnode *vp = AFSTOV(avc);
-
- if (vp->v_flag & VNOMAP)
- return ENOSYS;
- if (len == 0)
- return 0;
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- if (avc->mapcnt == 0) {
- /* on first mapping add a open reference */
- ObtainWriteLock(&avc->lock, 237);
- avc->execsOrWriters++;
- avc->opens++;
- ReleaseWriteLock(&avc->lock);
- }
- avc->mapcnt += btoc(len);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- return 0;
-}
-
- /*ARGSUSED*/ static int
-afs_delmap(OSI_VC_ARG(avc), off, prp, addr, len, prot, maxprot, flags, acred)
- off_t off;
-OSI_VC_DECL(avc);
- struct pregion *prp;
- addr_t addr;
- size_t len;
- u_int prot, maxprot;
- u_int flags;
- struct cred *acred;
-{
- OSI_VC_CONVERT(avc)
- struct vnode *vp = AFSTOV(avc);
- register struct brequest *tb;
- struct vrequest treq;
- afs_int32 code;
-
- if (vp->v_flag & VNOMAP)
- return ENOSYS;
- if (len == 0)
- return 0;
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- osi_Assert(avc->mapcnt > 0);
- avc->mapcnt -= btoc(len);
- osi_Assert(avc->mapcnt >= 0);
- if (avc->mapcnt == 0) {
- /* on last mapping push back and remove our reference */
- osi_Assert(avc->execsOrWriters > 0);
- osi_Assert(avc->opens > 0);
- if (avc->m.LinkCount == 0) {
- ObtainWriteLock(&avc->lock, 238);
- AFS_GUNLOCK();
- PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
- AFS_GLOCK();
- ReleaseWriteLock(&avc->lock);
- }
- /*
- * mimic afs_close
- */
- afs_InitReq(&treq, acred);
- if (afs_BBusy()) {
- /* do it yourself if daemons are all busy */
- ObtainWriteLock(&avc->lock, 239);
- code = afs_StoreOnLastReference(avc, &treq);
- ReleaseWriteLock(&avc->lock);
- /* BStore does CheckCode so we should also */
- /* VNOVNODE is "acceptable" error code from close, since
- * may happen when deleting a file on another machine while
- * it is open here. */
- if (code == VNOVNODE)
- code = 0;
- if (code) {
- afs_StoreWarn(code, avc->fid.Fid.Volume, /* /dev/console */
- 1);
- }
- code = afs_CheckCode(code, &treq, 52);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- } else {
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- /* at least one daemon is idle, so ask it to do the store.
- * Also, note that we don't lock it any more... */
- tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred,
- (afs_size_t) acred->cr_uid, 0L, (void *)0);
- /* sleep waiting for the store to start, then retrieve error code */
- while ((tb->flags & BUVALID) == 0) {
- tb->flags |= BUWAIT;
- afs_osi_Sleep(tb);
- }
- code = tb->code;
- afs_BRelease(tb);
- }
- } else {
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- }
- return 0;
-}
-#endif /* ! AFS_SGI65_ENV */
-
-
-/* ARGSUSED */
-/*
- * Note - if mapping in an ELF interpreter, one can get called without vp
- * ever having been 'opened'
- */
-#ifdef AFS_SGI65_ENV
-static int
-afs_map(OSI_VC_ARG(avc), off, len, prot, flags, cr, vpp)
- off_t off;
-OSI_VC_DECL(avc);
- size_t len;
- mprot_t prot;
- u_int flags;
- struct cred *cr;
- vnode_t **vpp;
-#else
-static int
-afs_map(OSI_VC_ARG(avc), off, prp, addrp, len, prot, maxprot, flags, cr)
- off_t off;
-OSI_VC_DECL(avc);
- struct pregion *prp;
- addr_t *addrp;
- size_t len;
- u_int prot, maxprot;
- u_int flags;
- struct cred *cr;
-#endif
-{
- OSI_VC_CONVERT(avc)
- struct vnode *vp = AFSTOV(avc);
- struct vrequest treq;
- int error;
-
- /* get a validated vcache entry */
- afs_InitReq(&treq, cr);
- error = afs_VerifyVCache(avc, &treq);
- if (error)
- return afs_CheckCode(error, &treq, 53);
-
- osi_FlushPages(avc, cr); /* ensure old pages are gone */
-#ifdef AFS_SGI65_ENV
- /* If the vnode is currently opened for write, there's the potential
- * that this mapping might (now or in the future) have PROT_WRITE.
- * So assume it does and we'll have to call afs_StoreOnLastReference.
- */
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- ObtainWriteLock(&avc->lock, 501);
- if (avc->execsOrWriters > 0) {
- avc->execsOrWriters++;
- avc->opens++;
- avc->mapcnt++; /* count eow's due to mappings. */
- }
- ReleaseWriteLock(&avc->lock);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
-#else
- AFS_RWLOCK(vp, VRWLOCK_WRITE);
- AFS_GUNLOCK();
- error =
- fs_map_subr(vp, (off_t) avc->m.Length, (u_int) avc->m.Mode, off, prp,
- *addrp, len, prot, maxprot, flags, cr);
- AFS_GLOCK();
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
-#endif /* AFS_SGI65_ENV */
- afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vp,
-#ifdef AFS_SGI65_ENV
- ICL_TYPE_POINTER, NULL,
-#else
- ICL_TYPE_POINTER, *addrp,
-#endif
- ICL_TYPE_INT32, len, ICL_TYPE_INT32, off);
- return error;
-}
-
-
-extern afs_rwlock_t afs_xvcache;
-extern afs_lock_t afs_xdcache;
-#ifdef AFS_SGI64_ENV
-int
-#else
-void
-#endif
-afs_xinactive(OSI_VC_ARG(avc), acred)
-OSI_VC_DECL(avc);
- struct ucred *acred;
-{
- int s;
- OSI_VC_CONVERT(avc)
- vnode_t *vp = (vnode_t *) avc;
- int mapcnt = avc->mapcnt; /* We just clear off this many. */
-
- AFS_STATCNT(afs_inactive);
-
- s = VN_LOCK(vp);
- if (!(vp->v_flag & VINACT) || (vp->v_count > 0)) {
- /* inactive was already done, or someone did a VN_HOLD; just return */
- vp->v_flag &= ~VINACT;
- VN_UNLOCK(vp, s);
-#ifdef AFS_SGI64_ENV
- return VN_INACTIVE_CACHE;
-#else
- return;
-#endif
- }
- osi_Assert((vp->v_flag & VSHARE) == 0);
- vp->v_flag &= ~VINACT;
- /* Removed broadcast to waiters, since no one ever will. Only for vnodes
- * in common pool.
- */
- VN_UNLOCK(vp, s);
-
-#ifdef AFS_SGI65_ENV
- /* In Irix 6.5, the last unmap of a dirty mmap'd file does not
- * get an explicit vnode op. Instead we only find out at VOP_INACTIVE.
- */
- if (!afs_rwlock_nowait((vnode_t *) avc, VRWLOCK_WRITE)) {
- return VN_INACTIVE_CACHE;
- }
- if (NBObtainWriteLock(&avc->lock, 502)) {
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- return VN_INACTIVE_CACHE;
- }
- if (avc->states & CUnlinked) {
- if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
- avc->states |= CUnlinkedDel;
- ReleaseWriteLock(&avc->lock);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- } else {
- ReleaseWriteLock(&avc->lock);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- afs_remunlink(avc, 1); /* ignore any return code */
- }
- return VN_INACTIVE_CACHE;
- }
- if ((avc->states & CDirty) || (avc->execsOrWriters > 0)) {
- /* File either already has dirty chunks (CDirty) or was mapped at
- * time in its life with the potential for being written into.
- * Note that afs_close defers storebacks if the vnode's ref count
- * if more than 1.
- */
- int code;
- struct vrequest treq;
- if (!afs_InitReq(&treq, acred)) {
- int s;
-
- VN_HOLD(vp);
- avc->execsOrWriters -= mapcnt - 1;
- avc->opens -= mapcnt - 1;
- avc->mapcnt -= mapcnt;
- code = afs_StoreOnLastReference(avc, &treq);
- /* The following behavior mimics the behavior in afs_close. */
- if (code == VNOVNODE || code == ENOENT)
- code = 0;
- if (code) {
- if (mapcnt) {
- cmn_err(CE_WARN,
- "AFS: Failed to store FID (%x:%lu.%lu.%lu) in VOP_INACTIVE, error = %d\n",
- (int)(avc->fid.Cell) & 0xffffffff,
- avc->fid.Fid.Volume, avc->fid.Fid.Vnode,
- avc->fid.Fid.Unique, code);
- }
- afs_InvalidateAllSegments(avc);
- }
- s = VN_LOCK(vp);
- vp->v_count--;
- code = (vp->v_count == 0);
- VN_UNLOCK(vp, s);
- /* If the vnode is now in use by someone else, return early. */
- if (!code) {
- ReleaseWriteLock(&avc->lock);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
- return VN_INACTIVE_CACHE;
- }
- }
- }
-#endif
-
- osi_Assert((avc->states & (CCore | CMAPPED)) == 0);
-
- if (avc->cred) {
- crfree(avc->cred);
- avc->cred = NULL;
- }
- ReleaseWriteLock(&avc->lock);
- AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
-
- /*
- * If someone unlinked a file and this is the last hurrah -
- * nuke all the pages.
- */
- if (avc->m.LinkCount == 0) {
- AFS_GUNLOCK();
- PTOSSVP(vp, (off_t) 0, (off_t) MAXLONG);
- AFS_GLOCK();
- }
-#ifndef AFS_SGI65_ENV
- osi_Assert(avc->mapcnt == 0);
- afs_chkpgoob(&avc->v, btoc(avc->m.Length));
-
- avc->states &= ~CDirty; /* Give up on store-backs */
- if (avc->states & CUnlinked) {
- if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
- avc->states |= CUnlinkedDel;
- } else {
- afs_remunlink(avc, 1); /* ignore any return code */
- }
- }
-#endif
-#ifdef AFS_SGI64_ENV
- return VN_INACTIVE_CACHE;
-#endif
-}
-
-static int
-afs_reclaim(OSI_VC_DECL(avc), int flag)
-{
-#ifdef AFS_SGI64_ENV
- /* Get's called via VOP_RELCAIM in afs_FlushVCache to clear repl_vnodeops */
- return 0;
-#else
- panic("afs_reclaim");
-#endif
-}
-
-void
-afs_rwlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
-{
- OSI_VN_CONVERT(vp)
- struct vcache *avc = VTOAFS(vp);
-
- if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
- avc->vc_locktrips++;
- return;
- }
- AFS_GUNLOCK();
- psema(&avc->vc_rwlock, PINOD);
- AFS_GLOCK();
- avc->vc_rwlockid = OSI_GET_LOCKID();
-}
-
-void
-afs_rwunlock(OSI_VN_DECL(vp), AFS_RWLOCK_T flag)
-{
- OSI_VN_CONVERT(vp)
- struct vcache *avc = VTOAFS(vp);
-
- AFS_ASSERT_GLOCK();
- osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
- if (avc->vc_locktrips > 0) {
- --avc->vc_locktrips;
- return;
- }
- avc->vc_rwlockid = OSI_NO_LOCKID;
- vsema(&avc->vc_rwlock);
-}
-
-
-/* The flag argument is for symmetry with the afs_rwlock and afs_rwunlock
- * calls. SGI currently only uses the flag to assert if the unlock flag
- * does not match the corresponding lock flag. But they may start using this
- * flag for a real rw lock at some time.
- */
-int
-afs_rwlock_nowait(vnode_t * vp, AFS_RWLOCK_T flag)
-{
- struct vcache *avc = VTOAFS(vp);
-
- AFS_ASSERT_GLOCK();
- if (OSI_GET_LOCKID() == avc->vc_rwlockid) {
- avc->vc_locktrips++;
- return 1;
- }
- if (cpsema(&avc->vc_rwlock)) {
- avc->vc_rwlockid = OSI_GET_LOCKID();
- return 1;
- }
- return 0;
-}
-
-#if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
-int
-afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
-{
- struct cell *tcell;
- afs_fid2_t *afid = (afs_fid2_t *) fidp;
- OSI_VC_CONVERT(avc)
-
- osi_Assert(sizeof(fid_t) >= sizeof(afs_fid2_t));
- afid->af_len = sizeof(afs_fid2_t) - sizeof(afid->af_len);
-
- tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
- afid->af_cell = tcell->cellIndex & 0xffff;
- afs_PutCell(tcell, READ_LOCK);
-
- afid->af_volid = avc->fid.Fid.Volume;
- afid->af_vno = avc->fid.Fid.Vnode;
- afid->af_uniq = avc->fid.Fid.Unique;
-
- return 0;
-}
-#else
-/* Only use so far is in checkpoint/restart for IRIX 6.4. In ckpt_fid, a
- * return of ENOSYS would make the code fail over to VOP_FID. We can't let
- * that happen, since we do a VN_HOLD there in the expectation that
- * posthandle will be called to release the vnode.
- *
- * afs_fid2 is used to support the R5000 workarounds (_R5000_CVT_WAR)
- */
-int
-afs_fid2(OSI_VC_DECL(avc), struct fid *fidp)
-{
-#if defined(_R5000_CVT_WAR)
- extern int R5000_cvt_war;
-
- if (R5000_cvt_war)
- return ENOSYS;
- else
- return EINVAL;
-#else
- return EINVAL;
-#endif
-}
-#endif /* AFS_SGI64_ENV && CKPT */
-
-
-/*
- * check for any pages hashed that shouldn't be!
- * Only valid if PGCACHEDEBUG is set in os/page.c
- * Drop the global lock here, since we may not actually do the call.
- */
-void
-afs_chkpgoob(vnode_t * vp, pgno_t pgno)
-{
-#undef PGDEBUG
-#ifdef PGDEBUG
- AFS_GUNLOCK();
- pfindanyoob(vp, pgno);
- AFS_GLOCK();
-#endif
-}
-
-
-#ifdef MP
-
-#ifdef AFS_SGI64_ENV
-#define AFS_MP_VC_ARG(A) bhv_desc_t A
-#else
-#define AFS_MP_VC_ARG(A) vnode_t A
-#endif
-
-#ifdef AFS_SGI64_ENV
-int
-mp_afs_open(bhv_desc_t * bhp, vnode_t ** a, mode_t b, struct cred *c)
-#else
-int
-mp_afs_open(vnode_t ** a, mode_t b, struct cred *c)
-#endif
-{
- int rv;
- AFS_GLOCK();
-#ifdef AFS_SGI64_ENV
- rv = afs_lockedvnodeops.vop_open(bhp, a, b, c);
-#else
- rv = afs_lockedvnodeops.vop_open(a, b, c);
-#endif
- AFS_GUNLOCK();
- return rv;
-}
-
-#if defined(AFS_SGI64_ENV)
-#if defined(AFS_SGI65_ENV)
-int
-mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, struct cred *d)
-#else
-int
-mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e,
- struct flid *f)
-#endif
-#else
-int
-mp_afs_close(AFS_MP_VC_ARG(*a), int b, lastclose_t c, off_t d, struct cred *e)
-#endif
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_close(a, b, c, d
-#if !defined(AFS_SGI65_ENV)
- , e
-#if defined(AFS_SGI64_ENV)
- , f
-#endif
-#endif
- );
-
- AFS_GUNLOCK();
- return rv;
-}
-
-#ifdef AFS_SGI64_ENV
-int
-mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
- struct flid *f)
-#else
-int
-mp_afs_read(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
-#endif
-{
- int rv;
- AFS_GLOCK();
-#ifdef AFS_SGI64_ENV
- rv = afs_lockedvnodeops.vop_read(a, b, c, d, f);
-#else
- rv = afs_lockedvnodeops.vop_read(a, b, c, d);
-#endif
- AFS_GUNLOCK();
- return rv;
-}
-
-
-#ifdef AFS_SGI64_ENV
-int
-mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d,
- struct flid *f)
-#else
-int
-mp_afs_write(AFS_MP_VC_ARG(*a), struct uio *b, int c, struct cred *d)
-#endif
-{
- int rv;
- AFS_GLOCK();
-#ifdef AFS_SGI64_ENV
- rv = afs_lockedvnodeops.vop_write(a, b, c, d, f);
-#else
- rv = afs_lockedvnodeops.vop_write(a, b, c, d);
-#endif
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_ioctl(AFS_MP_VC_ARG(*a), int b, void *c, int d, struct cred *e, int *f
-#ifdef AFS_SGI65_ENV
- , struct vopbd *vbds
-#endif
- )
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_ioctl(a, b, c, d, e, f
-#ifdef AFS_SGI65_ENV
- , vbds
-#endif
- );
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_fs_setfl(AFS_MP_VC_ARG(*a), int b, int c, struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_setfl(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_getattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_getattr(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_setattr(AFS_MP_VC_ARG(*a), struct vattr *b, int c, struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_setattr(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_access(AFS_MP_VC_ARG(*a), int b,
-#ifndef AFS_SGI65_ENV
- int c,
-#endif
- struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_access(a, b,
-#ifndef AFS_SGI65_ENV
- c,
-#endif
- d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_lookup(AFS_MP_VC_ARG(*a), char *b, vnode_t ** c, struct pathname *d,
- int e, vnode_t * f, struct cred *g)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_lookup(a, b, c, d, e, f, g);
- AFS_GUNLOCK();
- return rv;
-}
-
-#ifdef AFS_SGI64_ENV
-int
-mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, int d, int e,
- vnode_t ** f, struct cred *g)
-#else
-int
-mp_afs_create(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, enum vcexcl d,
- int e, vnode_t ** f, struct cred *g)
-#endif
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_create(a, b, c, d, e, f, g);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_remove(AFS_MP_VC_ARG(*a), char *b, struct cred *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_remove(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_link(AFS_MP_VC_ARG(*a), vnode_t * b, char *c, struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_link(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_rename(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, char *d,
- struct pathname *e, struct cred *f)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_rename(a, b, c, d, e, f);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_mkdir(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, vnode_t ** d,
- struct cred *e)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_mkdir(a, b, c, d, e);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_rmdir(AFS_MP_VC_ARG(*a), char *b, vnode_t * c, struct cred *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_rmdir(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_readdir(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c, int *d)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_readdir(a, b, c, d);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_symlink(AFS_MP_VC_ARG(*a), char *b, struct vattr *c, char *d,
- struct cred *e)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_symlink(a, b, c, d, e);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_readlink(AFS_MP_VC_ARG(*a), struct uio *b, struct cred *c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_readlink(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_fsync(AFS_MP_VC_ARG(*a), int b, struct cred *c
-#ifdef AFS_SGI65_ENV
- , off_t start, off_t stop
-#endif
- )
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_fsync(a, b, c
-#ifdef AFS_SGI65_ENV
- , start, stop
-#endif
- );
- AFS_GUNLOCK();
- return rv;
-}
-
-void
-mp_afs_inactive(AFS_MP_VC_ARG(*a), struct cred *b)
-{
- AFS_GLOCK();
- afs_lockedvnodeops.vop_inactive(a, b);
- AFS_GUNLOCK();
- return;
-}
-
-int
-mp_afs_fid(AFS_MP_VC_ARG(*a), struct fid **b)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_fid(a, b);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_fid2(AFS_MP_VC_ARG(*a), struct fid *b)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_fid2(a, b);
- AFS_GUNLOCK();
- return rv;
-}
-
-void
-mp_afs_rwlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
-{
- AFS_GLOCK();
- afs_rwlock(a, VRWLOCK_WRITE);
- AFS_GUNLOCK();
-}
-
-void
-mp_afs_rwunlock(AFS_MP_VC_ARG(*a), AFS_RWLOCK_T b)
-{
- AFS_GLOCK();
- afs_rwunlock(a, VRWLOCK_WRITE);
- AFS_GUNLOCK();
-}
-
-int
-mp_afs_seek(AFS_MP_VC_ARG(*a), off_t b, off_t * c)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_seek(a, b, c);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_fs_cmp(AFS_MP_VC_ARG(*a), vnode_t * b)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_cmp(a, b);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_frlock(AFS_MP_VC_ARG(*a), int b, struct flock *c, int d, off_t e,
-#ifdef AFS_SGI65_ENV
- vrwlock_t vrwlock,
-#endif
- struct cred *f)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_frlock(a, b, c, d, e,
-#ifdef AFS_SGI65_ENV
- vrwlock,
-#endif
- f);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_realvp(AFS_MP_VC_ARG(*a), vnode_t ** b)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_realvp(a, b);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_bmap(AFS_MP_VC_ARG(*a), off_t b, ssize_t c, int d, struct cred *e,
- struct bmapval *f, int *g)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_bmap(a, b, c, d, e, f, g);
- AFS_GUNLOCK();
- return rv;
-}
-
-void
-mp_afs_strategy(AFS_MP_VC_ARG(*a), struct buf *b)
-{
- int rv;
- AFS_GLOCK();
- afs_lockedvnodeops.vop_strategy(a, b);
- AFS_GUNLOCK();
- return;
-}
-
-#ifdef AFS_SGI65_ENV
-int
-mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, size_t c, mprot_t d, u_int e,
- struct cred *f, vnode_t ** g)
-#else
-int
-mp_afs_map(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, char **d, size_t e,
- u_int f, u_int g, u_int h, struct cred *i)
-#endif
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_map(a, b, c, d, e, f, g
-#ifndef AFS_SGI65_ENV
- , h, i
-#endif
- );
- AFS_GUNLOCK();
- return rv;
-}
-
-
-#ifndef AFS_SGI65_ENV
-/* As of Irix 6.5, addmap and delmap are only for devices */
-int
-mp_afs_addmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
- size_t e, u_int f, u_int g, u_int h, struct cred *i)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_addmap(a, b, c, d, e, f, g, h, i);
- AFS_GUNLOCK();
- return rv;
-}
-
-int
-mp_afs_delmap(AFS_MP_VC_ARG(*a), off_t b, struct pregion *c, addr_t d,
- size_t e, u_int f, u_int g, u_int h, struct cred *i)
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_delmap(a, b, c, d, e, f, g, h, i);
- AFS_GUNLOCK();
- return rv;
-}
-#endif /* ! AFS_SGI65_ENV */
-
-int
-mp_fs_poll(AFS_MP_VC_ARG(*a), short b, int c, short *d, struct pollhead **e
-#ifdef AFS_SGI65_ENV
- , unsigned int *f
-#endif
- )
-{
- int rv;
- AFS_GLOCK();
- rv = afs_lockedvnodeops.vop_poll(a, b, c, d, e
-#ifdef AFS_SGI65_ENV
- , f
-#endif
- );
- AFS_GUNLOCK();
- return rv;
-}
-
-
-struct vnodeops Afs_vnodeops = {
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- BHV_IDENTITY_INIT_POSITION(VNODE_POSITION_BASE),
-#else
- VNODE_POSITION_BASE,
-#endif
-#endif
- mp_afs_open,
- mp_afs_close,
- mp_afs_read,
- mp_afs_write,
- mp_afs_ioctl,
- mp_fs_setfl,
- mp_afs_getattr,
- mp_afs_setattr,
- mp_afs_access,
- mp_afs_lookup,
- mp_afs_create,
- mp_afs_remove,
- mp_afs_link,
- mp_afs_rename,
- mp_afs_mkdir,
- mp_afs_rmdir,
- mp_afs_readdir,
- mp_afs_symlink,
- mp_afs_readlink,
- mp_afs_fsync,
- mp_afs_inactive,
- mp_afs_fid,
- mp_afs_fid2,
- mp_afs_rwlock,
- mp_afs_rwunlock,
- mp_afs_seek,
- mp_fs_cmp,
- mp_afs_frlock,
- fs_nosys, /* realvp */
- mp_afs_bmap,
- mp_afs_strategy,
- mp_afs_map,
-#ifdef AFS_SGI65_ENV
- fs_noerr, /* addmap - devices only */
- fs_noerr, /* delmap - devices only */
-#else
- mp_afs_addmap,
- mp_afs_delmap,
-#endif
- mp_fs_poll, /* poll */
- fs_nosys, /* dump */
- fs_pathconf,
- fs_nosys, /* allocstore */
- fs_nosys, /* fcntl */
- afs_reclaim, /* reclaim */
- fs_nosys, /* attr_get */
- fs_nosys, /* attr_set */
- fs_nosys, /* attr_remove */
- fs_nosys, /* attr_list */
-#ifdef AFS_SGI64_ENV
-#ifdef AFS_SGI65_ENV
- fs_cover,
- (vop_link_removed_t) fs_noval,
- fs_vnode_change,
- fs_tosspages,
- fs_flushinval_pages,
- fs_flush_pages,
- fs_invalfree_pages,
- fs_pages_sethole,
- (vop_commit_t) fs_nosys,
- (vop_readbuf_t) fs_nosys,
- fs_strgetmsg,
- fs_strputmsg,
-#else
- fs_mount,
-#endif
-#endif
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-#endif /* MP */
-
-
-#if defined(AFS_SGI62_ENV) && defined(AFS_SGI_DUAL_FS_CACHE)
-/* Support for EFS and XFS caches. The assumption here is that the size of
- * a cache file also does not exceed 32 bits.
- */
-
-/* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
-int afs_CacheFSType = -1;
-vnodeops_t *afs_efs_vnodeopsp;
-vnodeops_t *afs_xfs_vnodeopsp;
-vnode_t *(*afs_IGetVnode) (ino_t);
-
-extern vnode_t *afs_EFSIGetVnode(ino_t); /* defined in osi_file.c */
-extern vnode_t *afs_XFSIGetVnode(ino_t); /* defined in osi_file.c */
-
-extern afs_lock_t afs_xosi; /* lock is for tvattr */
-
-/* Initialize the cache operations. Called while initializing cache files. */
-void
-afs_InitDualFSCacheOps(struct vnode *vp)
-{
- static int inited = 0;
- struct vfssw *swp;
- int found = 0;
-
- if (inited)
- return;
- inited = 1;
-
-
-#ifdef AFS_SGI_EFS_IOPS_ENV
- swp = vfs_getvfssw("efs");
- if (swp) {
- afs_efs_vnodeopsp = swp->vsw_vnodeops;
- if (vp && vp->v_op == afs_efs_vnodeopsp) {
- afs_CacheFSType = AFS_SGI_EFS_CACHE;
- afs_IGetVnode = afs_EFSIGetVnode;
- found = 1;
- }
- }
-#endif /* AFS_SGI_EFS_IOPS_ENV */
-
- swp = vfs_getvfssw("xfs");
- if (swp) {
- afs_xfs_vnodeopsp = swp->vsw_vnodeops;
- if (!found) {
- if (vp && vp->v_op == afs_xfs_vnodeopsp) {
- afs_CacheFSType = AFS_SGI_XFS_CACHE;
- afs_IGetVnode = afs_XFSIGetVnode;
- found = 1;
- }
- }
- }
-
- if (vp && !found)
- osi_Panic("osi_InitCacheFSType: Can't find fstype for vnode 0x%llx\n",
- vp);
-}
-
-ino_t
-VnodeToIno(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- MObtainWriteLock(&afs_xosi, 579);
- vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
- AFS_GUNLOCK();
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- AFS_GLOCK();
- if (code) {
- osi_Panic("VnodeToIno");
- }
- MReleaseWriteLock(&afs_xosi);
- return vattr.va_nodeid;
-}
-
-dev_t
-VnodeToDev(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- MObtainWriteLock(&afs_xosi, 580);
- vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
- AFS_GUNLOCK();
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- AFS_GLOCK();
- if (code) {
- osi_Panic("VnodeToDev");
- }
- MReleaseWriteLock(&afs_xosi);
- return (dev_t) vattr.va_fsid;
-}
-
-off_t
-VnodeToSize(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- MObtainWriteLock(&afs_xosi, 581);
- vattr.va_mask = AT_SIZE;
- AFS_GUNLOCK();
- AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
- AFS_GLOCK();
- if (code) {
- osi_Panic("VnodeToSize");
- }
- MReleaseWriteLock(&afs_xosi);
- return vattr.va_size;
-}
-#endif /* 6.2 and dual fs cache */
-#endif /* AFS_SGI62_ENV */
+++ /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_alloc.c - Linux memory allocation routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_alloc.c,v 1.21 2004/04/12 16:04:32 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "h/mm.h"
-#include "h/slab.h"
-
-#include "afs_atomlist.h"
-#include "afs_lhash.h"
-
-#define MAX_KMALLOC_SIZE PAGE_SIZE /* Max we should alloc with kmalloc */
-#define MAX_BUCKET_LEN 30 /* max. no. of entries per buckets we expect to see */
-#define STAT_INTERVAL 8192 /* we collect stats once every STAT_INTERVAL allocs */
-
-/* types of alloc */
-#define KM_TYPE 1 /* kmalloc */
-#define VM_TYPE 2 /* vmalloc */
-
-struct osi_linux_mem {
- void *chunk;
-};
-
-/* These assume 32-bit pointers */
-#define MEMTYPE(A) (((unsigned long)A) & 0x3)
-#define MEMADDR(A) (void *)((unsigned long)(A) & (~0x3))
-
-/* globals */
-afs_atomlist *al_mem_pool; /* pool of osi_linux_mem structures */
-afs_lhash *lh_mem_htab; /* mem hash table */
-unsigned int allocator_init = 0; /* has the allocator been initialized? */
-unsigned int afs_linux_cur_allocs = 0;
-unsigned int afs_linux_total_allocs = 0;
-unsigned int afs_linux_hash_verify_count = 0; /* used by hash_verify */
-struct afs_lhash_stat afs_linux_lsb; /* hash table statistics */
-unsigned int afs_linux_hash_bucket_dist[MAX_BUCKET_LEN]; /* bucket population distribution in our hash table */
-
-#if defined(AFS_LINUX24_ENV)
-#include "h/vmalloc.h"
-#else
-/* externs : can we do this in a better way. Including vmalloc.h causes other
- * problems.*/
-extern void vfree(void *addr);
-extern void *vmalloc(unsigned long size);
-#endif
-
-/* Allocator support functions (static) */
-
-static int
-hash_equal(const void *a, const void *b)
-{
- return (MEMADDR(((struct osi_linux_mem *)a)->chunk) ==
- MEMADDR(((struct osi_linux_mem *)b)->chunk));
-
-}
-
-/* linux_alloc : Allocates memory from the linux kernel. It uses
- * kmalloc if possible. Otherwise, we use vmalloc.
- * Input:
- * asize - size of memory required in bytes
- * Return Values:
- * returns NULL if we failed to allocate memory.
- * or pointer to memory if we succeeded.
- */
-static void *
-linux_alloc(unsigned int asize, int drop_glock)
-{
- void *new = NULL;
- int max_retry = 10;
- int haveGlock = ISAFS_GLOCK();
-
- /* if we can use kmalloc use it to allocate the required memory. */
- while (!new && max_retry) {
- if (asize <= MAX_KMALLOC_SIZE) {
- new = (void *)(unsigned long)kmalloc(asize,
-#ifdef GFP_NOFS
- GFP_NOFS
-#else
- GFP_KERNEL
-#endif
- );
- if (new) /* piggy back alloc type */
- (unsigned long)new |= KM_TYPE;
- } else {
- new = (void *)vmalloc(asize);
- if (new) /* piggy back alloc type */
- (unsigned long)new |= VM_TYPE;
- }
-
- if (!new) {
-#ifdef set_current_state
- set_current_state(TASK_INTERRUPTIBLE);
-#else
- current->state = TASK_INTERRUPTIBLE;
-#endif
- if (drop_glock && haveGlock)
- AFS_GUNLOCK();
- schedule_timeout(HZ);
- if (drop_glock && haveGlock)
- AFS_GLOCK();
-#ifdef set_current_state
- set_current_state(TASK_RUNNING);
-#else
- current->state = TASK_RUNNING;
-#endif
- --max_retry;
- }
- }
- if (new)
- memset(MEMADDR(new), 0, asize);
-
- return new;
-}
-
-static void
-linux_free(void *p)
-{
-
- /* mask out the type information from the pointer and
- * use the appropriate free routine to free the chunk.
- */
- switch (MEMTYPE(p)) {
- case KM_TYPE:
- kfree(MEMADDR(p));
- break;
- case VM_TYPE:
- vfree(MEMADDR(p));
- break;
- default:
- printf("afs_osi_Free: Asked to free unknown type %d at 0x%x\n",
- MEMTYPE(p), MEMADDR(p));
- break;
- }
-
-}
-
-/* hash_chunk() receives a pointer to a chunk and hashes it to produce a
- * key that the hashtable can use. The key is obtained by
- * right shifting out the 2 LSBs and then multiplying the
- * result by a constant no. and dividing it with a large prime.
- */
-#define HASH_CONST 32786
-#define HASH_PRIME 79367
-static unsigned
-hash_chunk(void *p)
-{
- unsigned int key;
-
- key = (unsigned int)(long)p >> 2;
- key = (key * HASH_CONST) % HASH_PRIME;
-
- return key;
-}
-
-/* hash_free() : Invoked by osi_linux_free_afs_memory(), thru
- * afs_lhash_iter(), this function is called by the lhash
- * module for every entry in the hash table. hash_free
- * frees the memory associated with the entry as well
- * as returning the osi_linux_mem struct to its pool.
- */
-static void
-hash_free(size_t index, unsigned key, void *data)
-{
- linux_free(((struct osi_linux_mem *)data)->chunk);
- afs_atomlist_put(al_mem_pool, data);
-}
-
-/* hash_verify() is invoked by osi_linux_verify_alloced_memory() thru
- * afs_lhash_iter() and is called by the lhash module for every element
- * in the hash table.
- * hash_verify() verifies (within limits) that the memory passed to it is
- * valid.
- */
-static void
-hash_verify(size_t index, unsigned key, void *data)
-{
- struct osi_linux_mem *lmp = (struct osi_linux_mem *)data;
- int memtype;
-
- memtype = MEMTYPE(lmp->chunk);
- if (memtype != KM_TYPE && memtype != VM_TYPE) {
- printf
- ("osi_linux_verify_alloced_memory: unknown type %d at 0x%x, index=%d\n",
- memtype, lmp->chunk, index);
- }
- afs_linux_hash_verify_count++;
-}
-
-
-/* local_free() : wrapper for vfree(), to deal with incompatible protoypes */
-static void
-local_free(void *p, size_t n)
-{
- vfree(p);
-}
-
-/* linux_alloc_init(): Initializes the kernel memory allocator. As part
- * of this process, it also initializes a pool of osi_linux_mem
- * structures as well as the hash table itself.
- * Return values:
- * 0 - failure
- * 1 - success
- */
-static int
-linux_alloc_init()
-{
- /* initiate our pool of osi_linux_mem structs */
- al_mem_pool =
- afs_atomlist_create(sizeof(struct osi_linux_mem), sizeof(long) * 1024,
- (void *)vmalloc, local_free);
- if (!al_mem_pool) {
- printf("afs_osi_Alloc: Error in initialization(atomlist_create)\n");
- return 0;
- }
-
- /* initialize the hash table to hold references to alloc'ed chunks */
- lh_mem_htab = afs_lhash_create(hash_equal, (void *)vmalloc, local_free);
- if (!lh_mem_htab) {
- printf("afs_osi_Alloc: Error in initialization(lhash_create)\n");
- return 0;
- }
-
- return 1;
-
-}
-
-/* hash_bucket_stat() : Counts the no. of elements in each bucket and
- * stores results in our bucket stats vector.
- */
-static unsigned int cur_bucket, cur_bucket_len;
-static void
-hash_bucket_stat(size_t index, unsigned key, void *data)
-{
- if (index == cur_bucket) {
- /* while still on the same bucket, inc len & return */
- cur_bucket_len++;
- return;
- } else { /* if we're on the next bucket, store the distribution */
- if (cur_bucket_len < MAX_BUCKET_LEN)
- afs_linux_hash_bucket_dist[cur_bucket_len]++;
- else
- printf
- ("afs_get_hash_stats: Warning! exceeded max bucket len %d\n",
- cur_bucket_len);
- cur_bucket = index;
- cur_bucket_len = 1;
- }
-}
-
-/* get_hash_stats() : get hash table statistics */
-static void
-get_hash_stats()
-{
- int i;
-
- afs_lhash_stat(lh_mem_htab, &afs_linux_lsb);
-
- /* clear out the bucket stat vector */
- for (i = 0; i < MAX_BUCKET_LEN; i++, afs_linux_hash_bucket_dist[i] = 0);
- cur_bucket = cur_bucket_len = 00;
-
- /* populate the bucket stat vector */
- afs_lhash_iter(lh_mem_htab, hash_bucket_stat);
-}
-
-/************** Linux memory allocator interface functions **********/
-
-#if defined(AFS_LINUX24_ENV)
-DECLARE_MUTEX(afs_linux_alloc_sem);
-#else
-struct semaphore afs_linux_alloc_sem = MUTEX;
-#endif
-
-void *
-osi_linux_alloc(unsigned int asize, int drop_glock)
-{
- void *new = NULL;
- struct osi_linux_mem *lmem;
-
- new = linux_alloc(asize, drop_glock); /* get a chunk of memory of size asize */
-
- if (!new) {
- printf("afs_osi_Alloc: Can't vmalloc %d bytes.\n", asize);
- return new;
- }
-
- down(&afs_linux_alloc_sem);
-
- /* allocator hasn't been initialized yet */
- if (allocator_init == 0) {
- if (linux_alloc_init() == 0) {
- goto error;
- }
- allocator_init = 1; /* initialization complete */
- }
-
- /* get an atom to store the pointer to the chunk */
- lmem = (struct osi_linux_mem *)afs_atomlist_get(al_mem_pool);
- if (!lmem) {
- printf("afs_osi_Alloc: atomlist_get() failed.");
- goto free_error;
- }
- /* store the chunk reference */
- lmem->chunk = new;
-
- /* hash in the chunk */
- if (afs_lhash_enter(lh_mem_htab, hash_chunk(new), lmem) != 0) {
- printf("afs_osi_Alloc: lhash_enter failed\n");
- goto free_error;
- }
- afs_linux_cur_allocs++; /* no. of current allocations */
- afs_linux_total_allocs++; /* total no. of allocations done so far */
- if ((afs_linux_cur_allocs % STAT_INTERVAL) == 0) {
- get_hash_stats();
- }
- error:
- up(&afs_linux_alloc_sem);
- return MEMADDR(new);
-
- free_error:
- if (new) {
- up(&afs_linux_alloc_sem);
- linux_free(new);
- down(&afs_linux_alloc_sem);
- }
- new = NULL;
- goto error;
-
-
-}
-
-/* osi_linux_free() - free chunk of memory passed to us.
- */
-void
-osi_linux_free(void *addr)
-{
- struct osi_linux_mem lmem, *lmp;
-
- down(&afs_linux_alloc_sem);
-
- lmem.chunk = addr;
- /* remove this chunk from our hash table */
- if ((lmp =
- (struct osi_linux_mem *)afs_lhash_remove(lh_mem_htab,
- hash_chunk(addr), &lmem))) {
- linux_free(lmp->chunk); /* this contains the piggybacked type info */
- afs_atomlist_put(al_mem_pool, lmp); /* return osi_linux_mem struct to pool */
- afs_linux_cur_allocs--;
- } else {
- printf("osi_linux_free: failed to remove chunk from hashtable\n");
- }
-
- up(&afs_linux_alloc_sem);
-}
-
-/* osi_linux_free_afs_memory() - free all chunks of memory allocated.
- */
-void
-osi_linux_free_afs_memory(void)
-{
- down(&afs_linux_alloc_sem);
-
- if (allocator_init) {
- /* iterate through all elements in the hash table and free both
- * the chunk and the atom associated with it.
- */
- afs_lhash_iter(lh_mem_htab, hash_free);
-
- /* free the atomlist. */
- afs_atomlist_destroy(al_mem_pool);
-
- /* free the hashlist. */
- afs_lhash_destroy(lh_mem_htab);
-
- /* change the state so that the allocator is now uninitialized. */
- allocator_init = 0;
- }
- up(&afs_linux_alloc_sem);
-}
-
-/* osi_linux_verify_alloced_memory(): verify all chunks of alloced memory in
- * our hash table.
- */
-void
-osi_linux_verify_alloced_memory()
-{
- down(&afs_linux_alloc_sem);
-
- /* count of times hash_verify was called. reset it to 0 before iteration */
- afs_linux_hash_verify_count = 0;
-
- /* iterate thru elements in the hash table */
- afs_lhash_iter(lh_mem_htab, hash_verify);
-
- if (afs_linux_hash_verify_count != afs_linux_cur_allocs) {
- /* hmm, some pieces of memory are missing. */
- printf
- ("osi_linux_verify_alloced_memory: %d chunks of memory are not accounted for during verify!\n",
- afs_linux_hash_verify_count - afs_linux_cur_allocs);
- }
-
- up(&afs_linux_alloc_sem);
- return;
-}
+++ /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_cred.c - Linux cred handling routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_cred.c,v 1.10 2004/04/21 02:20:23 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-
-/* Setup a pool for creds. Allocate several at a time. */
-#define CRED_ALLOC_STEP 29 /* at 140 bytes/cred = 4060 bytes. */
-
-
-static cred_t *cred_pool = NULL;
-int cred_allocs = 0;
-int ncreds_inuse = 0;
-
-/* Cred locking assumes current single threaded non-preemptive kernel.
- * Also assuming a fast path through both down and up if no waiters. Otherwise,
- * test if no creds in pool before grabbing lock in crfree().
- */
-#if defined(AFS_LINUX24_ENV)
-static DECLARE_MUTEX(linux_cred_pool_lock);
-#else
-static struct semaphore linux_cred_pool_lock = MUTEX;
-#endif
-#define CRED_LOCK() down(&linux_cred_pool_lock)
-#define CRED_UNLOCK() up(&linux_cred_pool_lock)
-
-cred_t *
-crget(void)
-{
- cred_t *tmp;
- int i;
-
- CRED_LOCK();
- if (!cred_pool) {
- cred_allocs++;
- cred_pool = (cred_t *) osi_Alloc(CRED_ALLOC_STEP * sizeof(cred_t));
- if (!cred_pool)
- osi_Panic("crget: No more memory for creds!\n");
-
- for (i = 0; i < CRED_ALLOC_STEP - 1; i++)
- cred_pool[i].cr_ref = (long)&cred_pool[i + 1];
- cred_pool[i].cr_ref = 0;
- }
- tmp = cred_pool;
- cred_pool = (cred_t *) tmp->cr_ref;
- ncreds_inuse++;
- CRED_UNLOCK();
-
- memset(tmp, 0, sizeof(cred_t));
-#if defined(AFS_LINUX26_ENV)
- tmp->cr_group_info = groups_alloc(0);
-#endif
- tmp->cr_ref = 1;
- return tmp;
-}
-
-void
-crfree(cred_t * cr)
-{
- if (cr->cr_ref > 1) {
-#if defined(AFS_LINUX26_ENV)
- put_group_info(cr->cr_group_info);
-#endif
- cr->cr_ref--;
- return;
- }
-
- CRED_LOCK();
- cr->cr_ref = (long)cred_pool;
- cred_pool = cr;
- CRED_UNLOCK();
- ncreds_inuse--;
-}
-
-
-/* Return a duplicate of the cred. */
-cred_t *
-crdup(cred_t * cr)
-{
- cred_t *tmp = crget();
-
- tmp->cr_uid = cr->cr_uid;
- tmp->cr_ruid = cr->cr_ruid;
- tmp->cr_gid = cr->cr_gid;
-#if defined(AFS_LINUX26_ENV)
-{
- struct group_info *old_info;
-
- old_info = tmp->cr_group_info;
- get_group_info(cr->cr_group_info);
- tmp->cr_group_info = cr->cr_group_info;
- put_group_info(old_info);
-}
-#else
- memcpy(tmp->cr_groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- tmp->cr_ngroups = cr->cr_ngroups;
-#endif
-
- tmp->cr_ref = 1;
- return tmp;
-}
-
-cred_t *
-crref(void)
-{
- cred_t *cr = crget();
-
- cr->cr_uid = current->fsuid;
- cr->cr_ruid = current->uid;
- cr->cr_gid = current->fsgid;
- cr->cr_rgid = current->gid;
-#if defined(AFS_LINUX26_ENV)
-{
- struct group_info *old_info;
-
- old_info = cr->cr_group_info;
- get_group_info(current->group_info);
- cr->cr_group_info = current->group_info;
- put_group_info(old_info);
-}
-#else
- memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
- cr->cr_ngroups = current->ngroups;
-#endif
- return cr;
-}
-
-
-/* Set the cred info into the current task */
-void
-crset(cred_t * cr)
-{
- current->fsuid = cr->cr_uid;
- current->uid = cr->cr_ruid;
- current->fsgid = cr->cr_gid;
- current->gid = cr->cr_rgid;
-#if defined(AFS_LINUX26_ENV)
-{
- struct group_info *old_info;
-
- /* using set_current_groups() will sort the groups */
- old_info = current->group_info;
- get_group_info(cr->cr_group_info);
- current->group_info = cr->cr_group_info;
- put_group_info(old_info);
-}
-#else
- memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- current->ngroups = cr->cr_ngroups;
-#endif
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_file.c,v 1.19 2004/04/12 16:04:32 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "h/smp_lock.h"
-#include "h/module.h"
-
-
-int afs_osicred_initialized = 0;
-struct AFS_UCRED afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct super_block *afs_cacheSBp;
-
-void *
-osi_UFSOpen(afs_int32 ainode)
-{
- struct inode *ip;
- register struct osi_file *afile = NULL;
- extern int cacheDiskType;
- afs_int32 code = 0;
- int dummy;
- struct inode *tip = NULL;
- struct file *filp = NULL;
- AFS_STATCNT(osi_UFSOpen);
- if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
- osi_Panic("UFSOpen called for non-UFS cache\n");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
- afile = (struct osi_file *)osi_AllocLargeSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- if (!afile) {
- osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
- sizeof(struct osi_file));
- }
- memset(afile, 0, sizeof(struct osi_file));
- filp = &afile->file;
- filp->f_dentry = &afile->dentry;
- tip = iget(afs_cacheSBp, (u_long) ainode);
- if (!tip)
- osi_Panic("Can't get inode %d\n", ainode);
- FILE_INODE(filp) = tip;
- tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
- filp->f_flags = O_RDWR;
-#if defined(AFS_LINUX26_ENV)
- filp->f_mapping = tip->i_mapping;
-#endif
-#if defined(AFS_LINUX24_ENV)
- filp->f_op = fops_get(tip->i_fop);
-#else
- filp->f_op = tip->i_op->default_file_ops;
-#endif
- if (filp->f_op && filp->f_op->open)
- code = filp->f_op->open(tip, filp);
- if (code)
- osi_Panic("Can't open inode %d\n", ainode);
- afile->size = tip->i_size;
- AFS_GLOCK();
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- return (void *)afile;
-}
-
-int
-afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat)
-{
- register afs_int32 code;
- AFS_STATCNT(osi_Stat);
- MObtainWriteLock(&afs_xosi, 320);
- astat->size = FILE_INODE(&afile->file)->i_size;
- astat->blksize = FILE_INODE(&afile->file)->i_blksize;
-#if defined(AFS_LINUX26_ENV)
- astat->mtime = FILE_INODE(&afile->file)->i_mtime.tv_sec;
- astat->atime = FILE_INODE(&afile->file)->i_atime.tv_sec;
-#else
- astat->mtime = FILE_INODE(&afile->file)->i_mtime;
- astat->atime = FILE_INODE(&afile->file)->i_atime;
-#endif
- code = 0;
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-int
-osi_UFSClose(register struct osi_file *afile)
-{
- AFS_STATCNT(osi_Close);
- if (afile) {
- if (FILE_INODE(&afile->file)) {
- struct file *filp = &afile->file;
- if (filp->f_op && filp->f_op->release)
- filp->f_op->release(FILE_INODE(filp), filp);
- iput(FILE_INODE(filp));
- }
- }
-
- osi_FreeLargeSpace(afile);
- return 0;
-}
-
-int
-osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- register afs_int32 code;
- struct osi_stat tstat;
- struct iattr newattrs;
- struct inode *inode = FILE_INODE(&afile->file);
- 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;
- MObtainWriteLock(&afs_xosi, 321);
- AFS_GUNLOCK();
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- down_write(&inode->i_alloc_sem);
-#endif
- down(&inode->i_sem);
- inode->i_size = newattrs.ia_size = asize;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-#if defined(AFS_LINUX24_ENV)
- newattrs.ia_ctime = CURRENT_TIME;
-
- /* avoid notify_change() since it wants to update dentry->d_parent */
- lock_kernel();
- code = inode_change_ok(inode, &newattrs);
- if (!code)
-#ifdef INODE_SETATTR_NOT_VOID
- code = inode_setattr(inode, &newattrs);
-#else
- inode_setattr(inode, &newattrs);
-#endif
- unlock_kernel();
- if (!code)
- truncate_inode_pages(&inode->i_data, asize);
-#else
- if (inode->i_sb->s_op && inode->i_sb->s_op->notify_change) {
- code = inode->i_sb->s_op->notify_change(&afile->dentry, &newattrs);
- }
- if (!code) {
- truncate_inode_pages(inode, asize);
- if (inode->i_op && inode->i_op->truncate)
- inode->i_op->truncate(inode);
- }
-#endif
- code = -code;
- up(&inode->i_sem);
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- up_write(&inode->i_alloc_sem);
-#endif
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
- size_t 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 = osi_rdwr(UIO_READ, afile, (caddr_t) aptr, asize, &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } 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)
-{
- struct AFS_UCRED *oldCred;
- size_t resid;
- register afs_int32 code;
- AFS_STATCNT(osi_Write);
- if (!afile) {
- if (!afs_shuttingdown)
- osi_Panic("afs_osi_Write called with null param");
- else
- return EIO;
- }
- if (offset != -1)
- afile->offset = offset;
- AFS_GUNLOCK();
- code = osi_rdwr(UIO_WRITE, afile, (caddr_t) aptr, asize, &resid);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - resid;
- afile->offset += code;
- } else {
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
- 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) (struct buf * bp), register struct buf *bp)
-{
- afs_int32 returnCode;
-
- AFS_STATCNT(osi_MapStrategy);
- returnCode = (*aproc) (bp);
-
- return returnCode;
-}
-
-void
-shutdown_osifile(void)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * setgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_groups.c,v 1.22 2004/04/21 02:20:23 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-#ifdef AFS_LINUX22_ENV
-#include "h/smp_lock.h"
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-static int
-afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent)
-{
- struct group_info *old_info;
-
- AFS_STATCNT(afs_setgroups);
-
- old_info = (*cr)->cr_group_info;
- get_group_info(group_info);
- (*cr)->cr_group_info = group_info;
- put_group_info(old_info);
-
- crset(*cr);
-
- if (change_parent) {
- old_info = current->parent->group_info;
- get_group_info(group_info);
- current->parent->group_info = group_info;
- put_group_info(old_info);
- }
-
- return (0);
-}
-#else
-static int
-afs_setgroups(cred_t **cr, int ngroups, gid_t * gidset, int change_parent)
-{
- int ngrps;
- int i;
- gid_t *gp;
-
- AFS_STATCNT(afs_setgroups);
-
- if (ngroups > NGROUPS)
- return EINVAL;
-
- gp = (*cr)->cr_groups;
- if (ngroups < NGROUPS)
- gp[ngroups] = (gid_t) NOGROUP;
-
- for (i = ngroups; i > 0; i--) {
- *gp++ = *gidset++;
- }
-
- (*cr)->cr_ngroups = ngroups;
- crset(*cr);
- return (0);
-}
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-static struct group_info *
-afs_getgroups(cred_t * cr)
-{
- AFS_STATCNT(afs_getgroups);
-
- get_group_info(cr->cr_group_info);
- return cr->cr_group_info;
-}
-#else
-/* Returns number of groups. And we trust groups to be large enough to
- * hold all the groups.
- */
-static int
-afs_getgroups(cred_t *cr, gid_t *groups)
-{
- int i;
- AFS_STATCNT(afs_getgroups);
-
- gid_t *gp = cr->cr_groups;
- int n = cr->cr_ngroups;
-
- for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++)
- *groups++ = *gp++;
- return i;
-}
-#endif
-
-#if !defined(AFS_LINUX26_ENV)
-/* Only propogate the PAG to the parent process. Unix's propogate to
- * all processes sharing the cred.
- */
-int
-set_pag_in_parent(int pag, int g0, int g1)
-{
- int i;
-#ifdef STRUCT_TASK_STRUCT_HAS_PARENT
- gid_t *gp = current->parent->groups;
- int ngroups = current->parent->ngroups;
-#else
- gid_t *gp = current->p_pptr->groups;
- int ngroups = current->p_pptr->ngroups;
-#endif
-
- if ((ngroups < 2) || (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG)) {
- /* We will have to shift grouplist to make room for pag */
- if (ngroups + 2 > NGROUPS) {
- return EINVAL;
- }
- for (i = ngroups - 1; i >= 0; i--) {
- gp[i + 2] = gp[i];
- }
- ngroups += 2;
- }
- gp[0] = g0;
- gp[1] = g1;
- if (ngroups < NGROUPS)
- gp[ngroups] = NOGROUP;
-
-#ifdef STRUCT_TASK_STRUCT_HAS_PARENT
- current->parent->ngroups = ngroups;
-#else
- current->p_pptr->ngroups = ngroups;
-#endif
- return 0;
-}
-#endif
-
-int
-setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
- int change_parent)
-{
-#if defined(AFS_LINUX26_ENV)
- struct group_info *group_info;
- gid_t g0, g1;
-
- AFS_STATCNT(setpag);
-
- group_info = afs_getgroups(*cr);
- g0 = GROUP_AT(group_info, 0);
- g1 = GROUP_AT(group_info, 1);
-
- if (afs_get_pag_from_groups(g0, g1) == NOPAG) {
- /* We will have to make sure group_info is big enough for pag */
- struct group_info *tmp;
- int i;
-
- tmp = groups_alloc(group_info->ngroups + 2);
- for (i = 0; i < group_info->ngroups; ++i)
- GROUP_AT(tmp, i + 2) = GROUP_AT(group_info, i);
- put_group_info(group_info);
- group_info = tmp;
- }
-
- *newpag = (pagvalue == -1 ? genpag() : pagvalue);
- afs_get_groups_from_pag(*newpag, &g0, &g1);
- GROUP_AT(group_info, 0) = g0;
- GROUP_AT(group_info, 1) = g1;
-
- afs_setgroups(cr, group_info, change_parent);
-
- put_group_info(group_info);
-
- return 0;
-#else
- gid_t *gidset;
- afs_int32 ngroups, code = 0;
- int j;
-
- AFS_STATCNT(setpag);
-
- gidset = (gid_t *) osi_Alloc(NGROUPS * sizeof(gidset[0]));
- ngroups = afs_getgroups(*cr, 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) {
- osi_Free((char *)gidset, NGROUPS * sizeof(int));
- return EINVAL;
- }
- 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(cr, ngroups, gidset, change_parent);
-
- /* If change_parent is set, then we should set the pag in the parent as
- * well.
- */
- if (change_parent && !code) {
- code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
- }
-
- osi_Free((char *)gidset, NGROUPS * sizeof(int));
- return code;
-#endif
-}
-
-
-/* Intercept the standard system call. */
-extern long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
-asmlinkage long
-afs_xsetgroups(int gidsetsize, gid_t * grouplist)
-{
- long code;
- cred_t *cr = crref();
- afs_uint32 junk;
- int old_pag;
-
- lock_kernel();
- old_pag = PagInCred(cr);
- crfree(cr);
- unlock_kernel();
-
- code = (*sys_setgroupsp) (gidsetsize, grouplist);
- if (code) {
- return code;
- }
-
- lock_kernel();
- cr = crref();
- if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
- /* re-install old pag if there's room. */
- code = setpag(&cr, old_pag, &junk, 0);
- }
- crfree(cr);
- unlock_kernel();
-
- /* Linux syscall ABI returns errno as negative */
- return (-code);
-}
-
-#if defined(AFS_LINUX24_ENV)
-/* Intercept the standard uid32 system call. */
-extern long (*sys_setgroups32p) (int gidsetsize, gid_t * grouplist);
-asmlinkage long
-afs_xsetgroups32(int gidsetsize, gid_t * grouplist)
-{
- long code;
- cred_t *cr = crref();
- afs_uint32 junk;
- int old_pag;
-
- lock_kernel();
- old_pag = PagInCred(cr);
- crfree(cr);
- unlock_kernel();
-
- code = (*sys_setgroups32p) (gidsetsize, grouplist);
-
- if (code) {
- return code;
- }
-
- lock_kernel();
- cr = crref();
- if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
- /* re-install old pag if there's room. */
- code = setpag(&cr, old_pag, &junk, 0);
- }
- crfree(cr);
- unlock_kernel();
-
- /* Linux syscall ABI returns errno as negative */
- return (-code);
-}
-#endif
-
-#if defined(AFS_PPC64_LINUX20_ENV)
-/* Intercept the uid16 system call as used by 32bit programs. */
-extern long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
-asmlinkage long afs32_xsetgroups(int gidsetsize, gid_t *grouplist)
-{
- long code;
- cred_t *cr = crref();
- afs_uint32 junk;
- int old_pag;
-
- lock_kernel();
- old_pag = PagInCred(cr);
- crfree(cr);
- unlock_kernel();
-
- code = (*sys32_setgroupsp)(gidsetsize, grouplist);
- if (code) {
- return code;
- }
-
- lock_kernel();
- cr = crref();
- if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
- /* re-install old pag if there's room. */
- code = setpag(&cr, old_pag, &junk, 0);
- }
- crfree(cr);
- unlock_kernel();
-
- /* Linux syscall ABI returns errno as negative */
- return (-code);
-}
-#endif
-
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_AMD64_LINUX20_ENV)
-/* Intercept the uid16 system call as used by 32bit programs. */
-extern long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
-asmlinkage long
-afs32_xsetgroups(int gidsetsize, u16 * grouplist)
-{
- long code;
- cred_t *cr = crref();
- afs_uint32 junk;
- int old_pag;
-
- lock_kernel();
- old_pag = PagInCred(cr);
- crfree(cr);
- unlock_kernel();
-
- code = (*sys32_setgroupsp) (gidsetsize, grouplist);
- if (code) {
- return code;
- }
-
- lock_kernel();
- cr = crref();
- if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
- /* re-install old pag if there's room. */
- code = setpag(&cr, old_pag, &junk, 0);
- }
- crfree(cr);
- unlock_kernel();
-
- /* Linux syscall ABI returns errno as negative */
- return (-code);
-}
-
-#ifdef AFS_LINUX24_ENV
-/* Intercept the uid32 system call as used by 32bit programs. */
-extern long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
-asmlinkage long
-afs32_xsetgroups32(int gidsetsize, gid_t * grouplist)
-{
- long code;
- cred_t *cr = crref();
- afs_uint32 junk;
- int old_pag;
-
- lock_kernel();
- old_pag = PagInCred(cr);
- crfree(cr);
- unlock_kernel();
-
- code = (*sys32_setgroups32p) (gidsetsize, grouplist);
- if (code) {
- return code;
- }
-
- lock_kernel();
- cr = crref();
- if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
- /* re-install old pag if there's room. */
- code = setpag(&cr, old_pag, &junk, 0);
- }
- crfree(cr);
- unlock_kernel();
-
- /* Linux syscall ABI returns errno as negative */
- return (-code);
-}
-#endif
-#endif
-
+++ /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
- */
-
-/*
- * LINUX inode operations
- *
- * Implements:
- * afs_syscall_icreate
- * afs_syscall_iopen
- * afs_syscall_iincdec
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_inode.c,v 1.7 2004/04/05 22:39:53 shadow Exp $");
-
-#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 */
-
-int
-afs_syscall_icreate(void)
-{
- return 0;
-}
-
-int
-afs_syscall_iopen(void)
-{
- return 0;
-}
-
-int
-afs_syscall_iincdec(void)
-{
- 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
- */
-
-/*
- * Linux implementation.
- *
- */
-
-#ifndef OSI_MACHDEP_H_
-#define OSI_MACHDEP_H_
-
-/* Only needed for xdr.h in glibc 2.1.x */
-#ifndef quad_t
-#define quad_t __quad_t
-#define u_quad_t __u_quad_t
-#endif
-
-#undef getuerror
-
-#define getpid() current->pid
-#ifdef STRUCT_TASK_STRUCT_HAS_REAL_PARENT
-#define getppid() current->real_parent->pid
-#else
-#define getppid() current->p_opptr->pid
-#endif
-
-#ifdef RECALC_SIGPENDING_TAKES_VOID
-#define RECALC_SIGPENDING(X) recalc_sigpending()
-#else
-#define RECALC_SIGPENDING(X) recalc_sigpending(X)
-#endif
-
-#if defined (STRUCT_TASK_STRUCT_HAS_SIGMASK_LOCK)
-#define SIG_LOCK(X) spin_lock_irq(&X->sigmask_lock)
-#define SIG_UNLOCK(X) spin_unlock_irq(&X->sigmask_lock)
-#elif defined (STRUCT_TASK_STRUCT_HAS_SIGHAND)
-#define SIG_LOCK(X) spin_lock_irq(&X->sighand->siglock)
-#define SIG_UNLOCK(X) spin_unlock_irq(&X->sighand->siglock)
-#else
-#define SIG_LOCK(X) spin_lock_irq(&X->sig->siglock)
-#define SIG_UNLOCK(X) spin_unlock_irq(&X->sig->siglock)
-#endif
-
-
-#define afs_hz HZ
-#include "h/sched.h"
-#define osi_Time() (xtime.tv_sec)
-#define osi_GetTime(V) do_gettimeofday((V))
-
-#undef gop_lookupname
-#define gop_lookupname osi_lookupname
-
-#define osi_vnhold(v, n) do { VN_HOLD(AFSTOV(v)); } while (0)
-
-#if defined(AFS_LINUX24_ENV)
-#define VN_HOLD(V) atomic_inc(&((vnode_t *) V)->i_count)
-#else
-#define VN_HOLD(V) ((vnode_t *) V)->i_count++
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-#define VN_RELE(V) iput((struct inode *) V)
-#else
-#define VN_RELE(V) osi_iput((struct inode *) V)
-#endif
-
-#define osi_AllocSmall afs_osi_Alloc
-#define osi_FreeSmall afs_osi_Free
-
-#define afs_suser(x) capable(CAP_SYS_ADMIN)
-#define wakeup afs_osi_Wakeup
-
-#undef vType
-#define vType(V) ((( vnode_t *)V)->v_type & S_IFMT)
-
-/* IsAfsVnode relies on the fast that there is only one vnodeop table for AFS.
- * Use the same type of test as other OS's for compatibility.
- */
-#undef IsAfsVnode
-extern struct vnodeops afs_file_iops, afs_dir_iops, afs_symlink_iops;
-#define IsAfsVnode(v) (((v)->v_op == &afs_file_iops) ? 1 : \
- ((v)->v_op == &afs_dir_iops) ? 1 : \
- ((v)->v_op == &afs_symlink_iops))
-#undef SetAfsVnode
-#define SetAfsVnode(v)
-
-/* We often need to pretend we're in user space to get memory transfers
- * right for the kernel calls we use.
- */
-#ifdef KERNEL_SPACE_DECL
-#undef KERNEL_SPACE_DECL
-#undef TO_USER_SPACE
-#undef TO_KERNEL_SPACE
-#endif
-#define KERNEL_SPACE_DECL mm_segment_t _fs_space_decl
-#define TO_USER_SPACE() { _fs_space_decl = get_fs(); set_fs(get_ds()); }
-#define TO_KERNEL_SPACE() set_fs(_fs_space_decl)
-
-/* Backwards compatibilty macros - copyin/copyout are redone because macro
- * inside parentheses is not evalutated.
- */
-#define memcpy_fromfs copy_from_user
-#define memcpy_tofs copy_to_user
-#define copyin(F, T, C) (copy_from_user ((char*)(T), (char*)(F), (C)), 0)
-#define copyinstr(F, T, C, L) (copyin(F, T, C), *(L)=strlen(T), 0)
-#define copyout(F, T, C) (copy_to_user ((char*)(T), (char*)(F), (C)), 0)
-
-/* kernel print statements */
-#define printf printk
-#define uprintf printk
-
-
-#define PAGESIZE PAGE_SIZE
-#ifndef NGROUPS
-#define NGROUPS NGROUPS_SMALL
-#endif
-
-/* cred struct */
-typedef struct cred { /* maps to task field: */
-#if (CPU == sparc64)
- long cr_ref;
-#else
- int cr_ref;
-#endif
- uid_t cr_uid; /* euid */
- uid_t cr_ruid; /* uid */
- gid_t cr_gid; /* egid */
- gid_t cr_rgid; /* gid */
-#if defined(AFS_LINUX26_ENV)
- struct group_info *cr_group_info;
-#else
- gid_t cr_groups[NGROUPS]; /* 32 groups - empty set to NOGROUP */
- int cr_ngroups;
-#endif
-} cred_t;
-#define AFS_UCRED cred
-#define AFS_PROC struct task_struct
-#define crhold(c) (c)->cr_ref++
-
-/* UIO manipulation */
-typedef enum { AFS_UIOSYS, AFS_UIOUSER } uio_seg_t;
-typedef enum { UIO_READ, UIO_WRITE } uio_flag_t;
-typedef struct uio {
- struct iovec *uio_iov;
- int uio_iovcnt;
- afs_offs_t uio_offset;
- uio_seg_t uio_seg;
- int uio_resid;
- uio_flag_t uio_flag;
-} uio_t;
-#define afsio_iov uio_iov
-#define afsio_iovcnt uio_iovcnt
-#define afsio_offset uio_offset
-#define afsio_seg uio_segflg
-#define afsio_fmode uio_fmode
-#define afsio_resid uio_resid
-
-/* Get/set the inode in the osifile struct. */
-#define FILE_INODE(F) (F)->f_dentry->d_inode
-
-
-/* page offset is obtained and stored here during module initialization
- * We need a variable to do this because, the PAGE_OFFSET macro defined in
- * include/asm/page.h can change from kernel to kernel and we cannot use
- * the hardcoded version.
- */
-extern unsigned long afs_linux_page_offset;
-
-/* function to help with the page offset stuff */
-#define afs_linux_page_address(page) (afs_linux_page_offset + PAGE_SIZE * (page - mem_map))
-
-#if defined(__KERNEL__) && defined(CONFIG_SMP)
-#include "../h/sched.h"
-#include "linux/wait.h"
-
-extern struct semaphore afs_global_lock;
-extern int afs_global_owner;
-
-#define AFS_GLOCK() \
-do { \
- down(&afs_global_lock); \
- if (afs_global_owner) \
- osi_Panic("afs_global_lock already held by pid %d", \
- afs_global_owner); \
- afs_global_owner = current->pid; \
-} while (0)
-
-#define ISAFS_GLOCK() (afs_global_owner == current->pid)
-
-#define AFS_GUNLOCK() \
-do { \
- if (!ISAFS_GLOCK()) \
- osi_Panic("afs global lock not held at %s:%d", __FILE__, __LINE__); \
- afs_global_owner = 0; \
- up(&afs_global_lock); \
-} while (0)
-
-
-#else
-#define AFS_GLOCK()
-#define AFS_GUNLOCK()
-#define ISAFS_GLOCK() 1
-#define AFS_ASSERT_GLOCK()
-#define AFS_ASSERT_RXGLOCK()
-#endif
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-#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
- */
-
-/*
- * Linux support routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_misc.c,v 1.33 2004/05/08 03:58:27 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-#if defined(AFS_LINUX26_ENV)
-#include "h/namei.h"
-#endif
-
-#if defined(AFS_LINUX24_ENV)
-/* Lookup name and return vnode for same. */
-int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- vnode_t ** dirvpp, struct dentry **dpp)
-{
- int code;
- extern struct nameidata afs_cacheNd;
- struct nameidata *nd = &afs_cacheNd;
-
- code = ENOENT;
- if (seg == AFS_UIOUSER) {
- code =
- followlink ? user_path_walk(aname,
- nd) : user_path_walk_link(aname, nd);
- } else {
-#if defined(AFS_LINUX26_ENV)
- code = path_lookup(aname, followlink ? LOOKUP_FOLLOW : 0, nd);
-#else
- if (path_init(aname, followlink ? LOOKUP_FOLLOW : 0, nd))
- code = path_walk(aname, nd);
-#endif
- }
-
- if (!code) {
- if (nd->dentry->d_inode) {
- *dpp = dget(nd->dentry);
- code = 0;
- } else {
- code = ENOENT;
- path_release(nd);
- }
- }
- return code;
-}
-#else
-int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink, vnode_t ** dirvpp,
- struct dentry **dpp)
-{
- struct dentry *dp = NULL;
- int code;
-
- code = ENOENT;
- if (seg == AFS_UIOUSER) {
- dp = followlink ? namei(aname) : lnamei(aname);
- } else {
- dp = lookup_dentry(aname, NULL, followlink ? 1 : 0);
- }
-
- if (dp && !IS_ERR(dp)) {
- if (dp->d_inode) {
- *dpp = dp;
- code = 0;
- } else
- dput(dp);
- }
-
- return code;
-}
-#endif
-
-/* Intialize cache device info and fragment size for disk cache partition. */
-int
-osi_InitCacheInfo(char *aname)
-{
- int code;
- struct dentry *dp;
- extern ino_t cacheInode;
- extern struct osi_dev cacheDev;
- extern afs_int32 afs_fsfragsize;
- extern struct super_block *afs_cacheSBp;
- code = osi_lookupname(aname, AFS_UIOSYS, 1, NULL, &dp);
- if (code)
- return ENOENT;
-
- cacheInode = dp->d_inode->i_ino;
- cacheDev.dev = dp->d_inode->i_sb->s_dev;
- afs_fsfragsize = dp->d_inode->i_sb->s_blocksize - 1;
- afs_cacheSBp = dp->d_inode->i_sb;
-
- dput(dp);
-
- return 0;
-}
-
-
-#define FOP_READ(F, B, C) (F)->f_op->read(F, B, (size_t)(C), &(F)->f_pos)
-#define FOP_WRITE(F, B, C) (F)->f_op->write(F, B, (size_t)(C), &(F)->f_pos)
-
-/* osi_rdwr
- * Seek, then read or write to an open inode. addrp points to data in
- * kernel space.
- */
-int
-osi_rdwr(int rw, struct osi_file *file, caddr_t addrp, size_t asize,
- size_t * resid)
-{
- int code = 0;
- KERNEL_SPACE_DECL;
- struct file *filp = &file->file;
- off_t offset = file->offset;
- unsigned long savelim;
-
- /* Seek to the desired position. Return -1 on error. */
- if (filp->f_op->llseek) {
- if (filp->f_op->llseek(filp, (loff_t) offset, 0) != offset)
- return -1;
- } else
- filp->f_pos = offset;
-
- savelim = current->rlim[RLIMIT_FSIZE].rlim_cur;
- current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
-
- /* Read/Write the data. */
- TO_USER_SPACE();
- if (rw == UIO_READ)
- code = FOP_READ(filp, addrp, asize);
- else if (rw == UIO_WRITE)
- code = FOP_WRITE(filp, addrp, asize);
- else /* all is well? */
- code = asize;
- TO_KERNEL_SPACE();
-
- current->rlim[RLIMIT_FSIZE].rlim_cur = savelim;
-
- if (code >= 0) {
- *resid = asize - code;
- return 0;
- } else
- return -1;
-}
-
-/* This variant is called from AFS read/write routines and takes a uio
- * struct and, if successful, returns 0.
- */
-int
-osi_file_uio_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
-{
- struct file *filp = &osifile->file;
- struct inode *ip = FILE_INODE(&osifile->file);
- KERNEL_SPACE_DECL;
- int code = 0;
- struct iovec *iov;
- int count;
- unsigned long savelim;
-
- savelim = current->rlim[RLIMIT_FSIZE].rlim_cur;
- current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
-
- if (uiop->uio_seg == AFS_UIOSYS)
- TO_USER_SPACE();
-
- filp->f_pos = uiop->uio_offset;
- while (code == 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
- iov = uiop->uio_iov;
- count = iov->iov_len;
- if (count == 0) {
- uiop->uio_iov++;
- uiop->uio_iovcnt--;
- continue;
- }
-
- if (rw == UIO_READ)
- code = FOP_READ(filp, iov->iov_base, count);
- else
- code = FOP_WRITE(filp, iov->iov_base, count);
-
- if (code < 0) {
- code = -code;
- break;
- } else if (code == 0) {
- /*
- * This is bad -- we can't read any more data from the
- * file, but we have no good way of signaling a partial
- * read either.
- */
- code = EIO;
- break;
- }
-
- iov->iov_base += code;
- iov->iov_len -= code;
- uiop->uio_resid -= code;
- uiop->uio_offset += code;
- code = 0;
- }
-
- if (uiop->uio_seg == AFS_UIOSYS)
- TO_KERNEL_SPACE();
-
- current->rlim[RLIMIT_FSIZE].rlim_cur = savelim;
-
- return code;
-}
-
-/* setup_uio
- * Setup a uio struct.
- */
-void
-setup_uio(uio_t * uiop, struct iovec *iovecp, char *buf, afs_offs_t pos,
- int count, uio_flag_t flag, uio_seg_t seg)
-{
- iovecp->iov_base = buf;
- iovecp->iov_len = count;
- uiop->uio_iov = iovecp;
- uiop->uio_iovcnt = 1;
- uiop->uio_offset = pos;
- uiop->uio_seg = seg;
- uiop->uio_resid = count;
- uiop->uio_flag = flag;
-}
-
-
-/* uiomove
- * UIO_READ : dp -> uio
- * UIO_WRITE : uio -> dp
- */
-int
-uiomove(char *dp, int length, uio_flag_t rw, uio_t * uiop)
-{
- int count, n;
- struct iovec *iov;
- int code;
-
- while (length > 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
- iov = uiop->uio_iov;
- count = iov->iov_len;
-
- if (!count) {
- uiop->uio_iov++;
- uiop->uio_iovcnt--;
- continue;
- }
-
- if (count > length)
- count = length;
-
- switch (uiop->uio_seg) {
- case AFS_UIOSYS:
- switch (rw) {
- case UIO_READ:
- memcpy(iov->iov_base, dp, count);
- break;
- case UIO_WRITE:
- memcpy(dp, iov->iov_base, count);
- break;
- default:
- printf("uiomove: Bad rw = %d\n", rw);
- return -EINVAL;
- }
- break;
- case AFS_UIOUSER:
- switch (rw) {
- case UIO_READ:
- AFS_COPYOUT(dp, iov->iov_base, count, code);
- break;
- case UIO_WRITE:
- AFS_COPYIN(iov->iov_base, dp, count, code);
- break;
- default:
- printf("uiomove: Bad rw = %d\n", rw);
- return -EINVAL;
- }
- break;
- default:
- printf("uiomove: Bad seg = %d\n", uiop->uio_seg);
- return -EINVAL;
- }
-
- dp += count;
- length -= count;
- iov->iov_base += count;
- iov->iov_len -= count;
- uiop->uio_offset += count;
- uiop->uio_resid -= count;
- }
- return 0;
-}
-
-void
-afs_osi_SetTime(osi_timeval_t * tvp)
-{
-#if defined(AFS_LINUX24_ENV)
-
-#if defined(AFS_LINUX26_ENV)
- struct timespec tv;
- tv.tv_sec = tvp->tv_sec;
- tv.tv_nsec = tvp->tv_usec * NSEC_PER_USEC;
-#else
- struct timeval tv;
- tv.tv_sec = tvp->tv_sec;
- tv.tv_usec = tvp->tv_usec;
-#endif
-
- AFS_STATCNT(osi_SetTime);
-
- do_settimeofday(&tv);
-#else
- extern int (*sys_settimeofdayp) (struct timeval * tv,
- struct timezone * tz);
-
- KERNEL_SPACE_DECL;
-
- AFS_STATCNT(osi_SetTime);
-
- TO_USER_SPACE();
- (void)(*sys_settimeofdayp) (tvp, NULL);
- TO_KERNEL_SPACE();
-#endif
-}
-
-/* Free all the pages on any of the vnodes in the vlru. Must be done before
- * freeing all memory.
- */
-void
-osi_linux_free_inode_pages(void)
-{
- int i;
- struct vcache *tvc;
- struct inode *ip;
- extern struct vcache *afs_vhashT[VCSIZE];
-
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- ip = AFSTOI(tvc);
-#if defined(AFS_LINUX24_ENV)
- if (ip->i_data.nrpages) {
-#else
- if (ip->i_nrpages) {
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- truncate_inode_pages(&ip->i_data, 0);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- truncate_inode_pages(ip, 0);
-#else
- invalidate_inode_pages(ip);
-#endif
-#if defined(AFS_LINUX24_ENV)
- if (ip->i_data.nrpages) {
-#else
- if (ip->i_nrpages) {
-#endif
- printf("Failed to invalidate all pages on inode 0x%x\n",
- ip);
- }
- }
- }
- }
-}
-
-void
-osi_clear_inode(struct inode *ip)
-{
- cred_t *credp = crref();
- struct vcache *vcp = ITOAFS(ip);
-
-#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&ip->i_count) > 1)
-#else
- if (ip->i_count > 1)
-#endif
- printf("afs_put_inode: ino %d (0x%x) has count %d\n", ip->i_ino, ip,
- ip->i_count);
-
- afs_InactiveVCache(vcp, credp);
- ObtainWriteLock(&vcp->lock, 504);
- ip->i_nlink = 0; /* iput checks this after calling this routine. */
- ip->i_state = I_CLEAR;
- ReleaseWriteLock(&vcp->lock);
- crfree(credp);
-}
-
-#if !defined(AFS_LINUX26_ENV)
-/* iput an inode. Since we still have a separate inode pool, we don't want
- * to call iput on AFS inodes, since they would then end up on Linux's
- * inode_unsed list.
- */
-void
-osi_iput(struct inode *ip)
-{
- extern struct vfs *afs_globalVFS;
-
- AFS_GLOCK();
-
- if (afs_globalVFS && ip->i_sb != afs_globalVFS)
- osi_Panic("IPUT Not an afs inode\n");
-
-#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&ip->i_count) == 0)
-#else
- if (ip->i_count == 0)
-#endif
- osi_Panic("IPUT Bad refCount %d on inode 0x%x\n",
-#if defined(AFS_LINUX24_ENV)
- atomic_read(&ip->i_count),
-#else
- ip->i_count,
-#endif
- ip);
-
-#if defined(AFS_LINUX24_ENV)
- if (atomic_dec_and_test(&ip->i_count))
-#else
- if (!--ip->i_count)
-#endif
- {
- osi_clear_inode(ip);
- ip->i_state = 0;
- }
- AFS_GUNLOCK();
-}
-#endif
-
-/* check_bad_parent() : Checks if this dentry's vcache is a root vcache
- * that has its mvid (parent dir's fid) pointer set to the wrong directory
- * due to being mounted in multiple points at once. If so, check_bad_parent()
- * calls afs_lookup() to correct the vcache's mvid, as well as the volume's
- * dotdotfid and mtpoint fid members.
- * Parameters:
- * dp - dentry to be checked.
- * Return Values:
- * None.
- * Sideeffects:
- * This dentry's vcache's mvid will be set to the correct parent directory's
- * fid.
- * This root vnode's volume will have its dotdotfid and mtpoint fids set
- * to the correct parent and mountpoint fids.
- */
-
-void
-check_bad_parent(struct dentry *dp)
-{
- cred_t *credp;
- struct vcache *vcp = ITOAFS(dp->d_inode), *avc = NULL;
- struct vcache *pvc = ITOAFS(dp->d_parent->d_inode);
-
- if (vcp->mvid->Fid.Volume != pvc->fid.Fid.Volume) { /* bad parent */
- credp = crref();
-
-
- /* force a lookup, so vcp->mvid is fixed up */
- afs_lookup(pvc, dp->d_name.name, &avc, credp);
- if (!avc || vcp != avc) { /* bad, very bad.. */
- afs_Trace4(afs_iclSetp, CM_TRACE_TMP_1S3L, ICL_TYPE_STRING,
- "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
- ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
- ICL_TYPE_POINTER, dp);
- }
- if (avc)
- AFS_RELE(avc);
- crfree(credp);
- }
- /* if bad parent */
- return;
-}
-
-struct task_struct *rxk_ListenerTask;
-
-void
-osi_linux_mask(void)
-{
- SIG_LOCK(current);
- sigfillset(¤t->blocked);
- RECALC_SIGPENDING(current);
- SIG_UNLOCK(current);
-}
-
-void
-osi_linux_rxkreg(void)
-{
- rxk_ListenerTask = current;
-}
+++ /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
- */
-
-/*
- * Linux module support routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_module.c,v 1.48 2004/05/11 20:36:13 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "h/unistd.h" /* For syscall numbers. */
-#include "h/mm.h"
-
-#ifdef AFS_AMD64_LINUX20_ENV
-#include "../asm/ia32_unistd.h"
-#endif
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#include <linux/init.h>
-#include <linux/sched.h>
-#endif
-#if !defined(EXPORTED_SYS_CALL_TABLE) && defined(HAVE_KERNEL_LINUX_SYSCALL_H)
-#include <linux/syscall.h>
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-#include <linux/vermagic.h>
-#include <linux/compiler.h>
-
-MODULE_INFO(vermagic, VERMAGIC_STRING);
-
-#endif
-
-#ifdef AFS_SPARC64_LINUX24_ENV
-#define __NR_setgroups32 82 /* This number is not exported for some bizarre reason. */
-#endif
-
-#if !defined(AFS_LINUX24_ENV)
-asmlinkage int (*sys_settimeofdayp) (struct timeval * tv,
- struct timezone * tz);
-#endif
-asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
-#ifdef EXPORTED_SYS_CALL_TABLE
-#ifdef AFS_SPARC64_LINUX20_ENV
-extern unsigned int sys_call_table[]; /* changed to uint because SPARC64 has syscaltable of 32bit items */
-#else
-extern void *sys_call_table[]; /* safer for other linuces */
-#endif
-#else /* EXPORTED_SYS_CALL_TABLE */
-#ifdef AFS_SPARC64_LINUX20_ENV
-static unsigned int *sys_call_table; /* changed to uint because SPARC64 has syscaltable of 32bit items */
-#else
-static void **sys_call_table; /* safer for other linuces */
-#endif
-#endif
-extern struct file_system_type afs_fs_type;
-
-static long get_page_offset(void);
-
-#if defined(AFS_LINUX24_ENV)
-DECLARE_MUTEX(afs_global_lock);
-#else
-struct semaphore afs_global_lock = MUTEX;
-#endif
-int afs_global_owner = 0;
-#if !defined(AFS_LINUX24_ENV)
-unsigned long afs_linux_page_offset = 0; /* contains the PAGE_OFFSET value */
-#endif
-
-/* Since sys_ni_syscall is not exported, I need to cache it in order to restore
- * it.
- */
-#ifdef AFS_SPARC64_LINUX20_ENV
-static unsigned int afs_ni_syscall = 0;
-#else
-static void *afs_ni_syscall = 0;
-#endif
-
-#ifdef AFS_AMD64_LINUX20_ENV
-#ifdef EXPORTED_IA32_SYS_CALL_TABLE
-extern void *ia32_sys_call_table[];
-#else
-static void **ia32_sys_call_table;
-#endif
-
-static void *ia32_ni_syscall = 0;
-asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
-#if defined(__NR_ia32_setgroups32)
-asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
-#endif /* __NR_ia32_setgroups32 */
-#endif /* AFS_AMD64_LINUX20_ENV */
-
-#ifdef AFS_PPC64_LINUX20_ENV
-asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
-#endif /* AFS_AMD64_LINUX20_ENV */
-
-#ifdef AFS_SPARC64_LINUX20_ENV
-static unsigned int afs_ni_syscall32 = 0;
-asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
- __kernel_gid_t32 * grouplist);
-#if defined(__NR_setgroups32)
-asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
- __kernel_gid_t32 * grouplist);
-#endif /* __NR_setgroups32 */
-#ifdef EXPORTED_SYS_CALL_TABLE
-extern unsigned int sys_call_table32[];
-#else /* EXPORTED_SYS_CALL_TABLE */
-static unsigned int *sys_call_table32;
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
-asmlinkage int
-afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4,
- long parm5)
-{
- __asm__ __volatile__("srl %o4, 0, %o4\n\t" "mov %o7, %i7\n\t"
- "call afs_syscall\n\t" "srl %o5, 0, %o5\n\t"
- "ret\n\t" "nop");
-}
-#endif /* AFS_SPARC64_LINUX20_ENV */
-
-static int afs_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-
-static struct file_operations afs_syscall_fops = {
- .ioctl = afs_ioctl,
-};
-
-static struct proc_dir_entry *openafs_procfs;
-
-static int
-afsproc_init()
-{
- struct proc_dir_entry *entry1;
-
- openafs_procfs = proc_mkdir(PROC_FSDIRNAME, proc_root_fs);
- entry1 = create_proc_entry(PROC_SYSCALL_NAME, 0, openafs_procfs);
-
- entry1->proc_fops = &afs_syscall_fops;
-
- entry1->owner = THIS_MODULE;
-
- return 0;
-}
-
-static void
-afsproc_exit()
-{
- remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
- remove_proc_entry(PROC_FSDIRNAME, proc_root_fs);
-}
-
-static int
-afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
-
- struct afsprocdata sysargs;
-
- if (cmd != VIOC_SYSCALL) return -EINVAL;
-
- if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
- return -EFAULT;
-
- return afs_syscall(sysargs.syscall, sysargs.param1,
- sysargs.param2, sysargs.param3, sysargs.param4);
-}
-
-#ifdef AFS_IA64_LINUX20_ENV
-
-asmlinkage long
-afs_syscall_stub(int r0, int r1, long r2, long r3, long r4, long gp)
-{
- __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t" /* save rp */
- "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t" /* save gp */
- ";;\n" ".L1: mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_syscall-.L1,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t" /* restore gp */
- "br.ret.sptk.many b0\n" ".fptr_afs_syscall:\n\t"
- "data8 @fptr(afs_syscall)");
-}
-
-asmlinkage long
-afs_xsetgroups_stub(int r0, int r1, long r2, long r3, long r4, long gp)
-{
- __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t" /* save rp */
- "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t" /* save gp */
- ";;\n" ".L2: mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_xsetgroups - .L2,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t" /* restore gp */
- "br.ret.sptk.many b0\n" ".fptr_afs_xsetgroups:\n\t"
- "data8 @fptr(afs_xsetgroups)");
-}
-
-struct fptr {
- void *ip;
- unsigned long gp;
-};
-
-#endif /* AFS_IA64_LINUX20_ENV */
-
-#ifdef AFS_LINUX24_ENV
-asmlinkage int (*sys_setgroups32p) (int gidsetsize,
- __kernel_gid32_t * grouplist);
-#endif /* AFS_LINUX24_ENV */
-
-#ifdef AFS_SPARC64_LINUX20_ENV
-#define POINTER2SYSCALL (unsigned int)(unsigned long)
-#define SYSCALL2POINTER (void *)(long)
-#else
-#define POINTER2SYSCALL (void *)
-#define SYSCALL2POINTER (void *)
-#endif
-
-#ifdef AFS_PPC64_LINUX20_ENV
-extern void *set_afs_syscall(void*);
-extern void *set_afs_xsetgroups_syscall(void*);
-extern void *set_afs_xsetgroups_syscall32(void*);
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-int __init
-afs_init(void)
-#else
-int
-init_module(void)
-#endif
-{
-#if defined(AFS_IA64_LINUX20_ENV)
- unsigned long kernel_gp = 0;
- static struct fptr sys_setgroups;
-#endif /* defined(AFS_IA64_LINUX20_ENV) */
- extern int afs_syscall();
- extern long afs_xsetgroups();
-#if defined(__NR_setgroups32)
- extern int afs_xsetgroups32();
-#endif /* __NR_setgroups32 */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined (AFS_AMD64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
- extern int afs32_xsetgroups();
-#if (defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV))
- extern int afs32_xsetgroups32();
-#endif /* defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV) */
-#if (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV))
- extern int afs32_xsetgroups32();
-#endif /* (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV) */
-#endif /* AFS_SPARC64_LINUX20_ENV || AFS_AMD64_LINUX20_ENV || AFS_PPC64_LINUX20_ENV */
-
-#if !defined(EXPORTED_SYS_CALL_TABLE) || (defined(AFS_AMD64_LINUX20_ENV) && !defined(EXPORTED_IA32_SYS_CALL_TABLE))
- unsigned long *ptr;
- unsigned long offset=0;
- unsigned long datalen=0;
- int ret;
- unsigned long token=0;
- char *mod_name;
- unsigned long mod_start=0;
- unsigned long mod_end=0;
- char *sec_name;
- unsigned long sec_start=0;
- unsigned long sec_end=0;
- char *sym_name;
- unsigned long sym_start=0;
- unsigned long sym_end=0;
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
- RWLOCK_INIT(&afs_xosi, "afs_xosi");
-
-#if !defined(AFS_LINUX24_ENV)
- /* obtain PAGE_OFFSET value */
- afs_linux_page_offset = get_page_offset();
-
-#ifndef AFS_S390_LINUX22_ENV
- if (afs_linux_page_offset == 0) {
- /* couldn't obtain page offset so can't continue */
- printf("afs: Unable to obtain PAGE_OFFSET. Exiting..");
- return -EIO;
- }
-#endif /* AFS_S390_LINUX22_ENV */
-#endif /* !defined(AFS_LINUX24_ENV) */
-
-#ifndef EXPORTED_SYS_CALL_TABLE
- sys_call_table = 0;
-
-#ifdef EXPORTED_KALLSYMS_SYMBOL
- ret = 1;
- token = 0;
- while (ret) {
- sym_start = 0;
- ret =
- kallsyms_symbol_to_address("sys_call_table", &token, &mod_name,
- &mod_start, &mod_end, &sec_name,
- &sec_start, &sec_end, &sym_name,
- &sym_start, &sym_end);
- if (ret && !strcmp(mod_name, "kernel"))
- break;
- }
- if (ret && sym_start) {
- sys_call_table = sym_start;
- }
-#elif defined(EXPORTED_KALLSYMS_ADDRESS)
- ret =
- kallsyms_address_to_symbol((unsigned long)&init_mm, &mod_name,
- &mod_start, &mod_end, &sec_name,
- &sec_start, &sec_end, &sym_name,
- &sym_start, &sym_end);
- ptr = (unsigned long *)sec_start;
- datalen = (sec_end - sec_start) / sizeof(unsigned long);
-#elif defined(AFS_IA64_LINUX20_ENV)
- ptr = (unsigned long *)(&sys_close - 0x180000);
- datalen = 0x180000 / sizeof(ptr);
-#elif defined(AFS_AMD64_LINUX20_ENV)
- ptr = (unsigned long *)&init_mm;
- datalen = 0x360000 / sizeof(ptr);
-#else
- ptr = (unsigned long *)&init_mm;
- datalen = 16384;
-#endif
- for (offset = 0; offset < datalen; ptr++, offset++) {
-#if defined(AFS_IA64_LINUX20_ENV)
- unsigned long close_ip =
- (unsigned long)((struct fptr *)&sys_close)->ip;
- unsigned long chdir_ip =
- (unsigned long)((struct fptr *)&sys_chdir)->ip;
- unsigned long write_ip =
- (unsigned long)((struct fptr *)&sys_write)->ip;
- if (ptr[0] == close_ip && ptr[__NR_chdir - __NR_close] == chdir_ip
- && ptr[__NR_write - __NR_close] == write_ip) {
- sys_call_table = (void *)&(ptr[-1 * (__NR_close - 1024)]);
- break;
- }
-#elif defined(EXPORTED_SYS_WAIT4) && defined(EXPORTED_SYS_CLOSE)
- if (ptr[0] == (unsigned long)&sys_close
- && ptr[__NR_wait4 - __NR_close] == (unsigned long)&sys_wait4) {
- sys_call_table = ptr - __NR_close;
- break;
- }
-#elif defined(EXPORTED_SYS_CHDIR) && defined(EXPORTED_SYS_CLOSE)
- if (ptr[0] == (unsigned long)&sys_close
- && ptr[__NR_chdir - __NR_close] == (unsigned long)&sys_chdir) {
- sys_call_table = ptr - __NR_close;
- break;
- }
-#elif defined(EXPORTED_SYS_OPEN)
- if (ptr[0] == (unsigned long)&sys_exit
- && ptr[__NR_open - __NR_exit] == (unsigned long)&sys_open) {
- sys_call_table = ptr - __NR_exit;
- break;
- }
-#else /* EXPORTED_SYS_OPEN */
- break;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
- }
-#ifdef EXPORTED_KALLSYMS_ADDRESS
- ret =
- kallsyms_address_to_symbol((unsigned long)sys_call_table, &mod_name,
- &mod_start, &mod_end, &sec_name,
- &sec_start, &sec_end, &sym_name,
- &sym_start, &sym_end);
- if (ret && strcmp(sym_name, "sys_call_table"))
- sys_call_table = 0;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
- if (!sys_call_table) {
- printf("Failed to find address of sys_call_table\n");
- sys_settimeofdayp = 0;
- } else {
- printf("Found sys_call_table at %x\n", sys_call_table);
-#ifdef AFS_SPARC64_LINUX20_ENV
- error cant support this yet.;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
-#ifdef AFS_AMD64_LINUX20_ENV
-#ifndef EXPORTED_IA32_SYS_CALL_TABLE
- ia32_sys_call_table = 0;
-#ifdef EXPORTED_KALLSYMS_SYMBOL
- ret = 1;
- token = 0;
- while (ret) {
- sym_start = 0;
- ret = kallsyms_symbol_to_address("ia32_sys_call_table", &token,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (ret && !strcmp(mod_name, "kernel"))
- break;
- }
- if (ret && sym_start) {
- ia32_sys_call_table = sym_start;
- }
-#else /* EXPORTED_KALLSYMS_SYMBOL */
-#ifdef EXPORTED_KALLSYMS_ADDRESS
- ret = kallsyms_address_to_symbol((unsigned long)
- &interruptible_sleep_on,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- ptr = (unsigned long *)sec_start;
- datalen = (sec_end - sec_start) / sizeof(unsigned long);
-#else /* EXPORTED_KALLSYMS_ADDRESS */
-#if defined(AFS_AMD64_LINUX20_ENV)
- ptr = (unsigned long *)&interruptible_sleep_on;
- datalen = 0x180000 / sizeof(ptr);
-#else /* AFS_AMD64_LINUX20_ENV */
- ptr = (unsigned long *)&interruptible_sleep_on;
- datalen = 16384;
-#endif /* AFS_AMD64_LINUX20_ENV */
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
- for (offset = 0; offset < datalen; ptr++, offset++) {
- if (ptr[0] == (unsigned long)&sys_exit
- && ptr[__NR_ia32_open - __NR_ia32_exit] ==
- (unsigned long)&sys_open) {
- ia32_sys_call_table = ptr - __NR_ia32_exit;
- break;
- }
- }
-#ifdef EXPORTED_KALLSYMS_ADDRESS
- ret = kallsyms_address_to_symbol((unsigned long)ia32_sys_call_table,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (ret && strcmp(sym_name, "ia32_sys_call_table"))
- ia32_sys_call_table = 0;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
-#endif /* EXPORTED_KALLSYMS_SYMBOL */
- if (!ia32_sys_call_table) {
- printf("Warning: Failed to find address of ia32_sys_call_table\n");
- } else {
- printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table);
- }
-#else
- printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table);
-#endif /* IA32_SYS_CALL_TABLE */
-#endif
-
- /* Initialize pointers to kernel syscalls. */
-#if !defined(AFS_LINUX24_ENV)
- sys_settimeofdayp = SYSCALL2POINTER sys_call_table[__NR_settimeofday];
-#endif /* AFS_IA64_LINUX20_ENV */
-
- /* setup AFS entry point. */
- if (
-#if defined(AFS_IA64_LINUX20_ENV)
- SYSCALL2POINTER sys_call_table[__NR_afs_syscall - 1024]
-#else
- SYSCALL2POINTER sys_call_table[__NR_afs_syscall]
-#endif
- == afs_syscall) {
- printf("AFS syscall entry point already in use!\n");
- return -EBUSY;
- }
-#if defined(AFS_IA64_LINUX20_ENV)
- afs_ni_syscall = sys_call_table[__NR_afs_syscall - 1024];
- sys_call_table[__NR_afs_syscall - 1024] =
- POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
-#else /* AFS_IA64_LINUX20_ENV */
- afs_ni_syscall = sys_call_table[__NR_afs_syscall];
- sys_call_table[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall;
-#ifdef AFS_SPARC64_LINUX20_ENV
- afs_ni_syscall32 = sys_call_table32[__NR_afs_syscall];
- sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
-#endif
-#endif /* AFS_IA64_LINUX20_ENV */
-#ifdef AFS_AMD64_LINUX20_ENV
- if (ia32_sys_call_table) {
- ia32_ni_syscall = ia32_sys_call_table[__NR_ia32_afs_syscall];
- ia32_sys_call_table[__NR_ia32_afs_syscall] =
- POINTER2SYSCALL afs_syscall;
- }
-#endif /* AFS_S390_LINUX22_ENV */
-#ifndef EXPORTED_SYS_CALL_TABLE
- }
-#endif /* EXPORTED_SYS_CALL_TABLE */
- osi_Init();
- register_filesystem(&afs_fs_type);
-
- /* Intercept setgroups calls */
- if (sys_call_table) {
-#if defined(AFS_IA64_LINUX20_ENV)
- sys_setgroupsp = (void *)&sys_setgroups;
-
- ((struct fptr *)sys_setgroupsp)->ip =
- SYSCALL2POINTER sys_call_table[__NR_setgroups - 1024];
- ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
-
- sys_call_table[__NR_setgroups - 1024] =
- POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
-#else /* AFS_IA64_LINUX20_ENV */
- sys_setgroupsp = SYSCALL2POINTER sys_call_table[__NR_setgroups];
- sys_call_table[__NR_setgroups] = POINTER2SYSCALL afs_xsetgroups;
-#ifdef AFS_SPARC64_LINUX20_ENV
- sys32_setgroupsp = SYSCALL2POINTER sys_call_table32[__NR_setgroups];
- sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#if defined(__NR_setgroups32)
- sys_setgroups32p = SYSCALL2POINTER sys_call_table[__NR_setgroups32];
- sys_call_table[__NR_setgroups32] = POINTER2SYSCALL afs_xsetgroups32;
-#ifdef AFS_SPARC64_LINUX20_ENV
- sys32_setgroups32p =
- SYSCALL2POINTER sys_call_table32[__NR_setgroups32];
- sys_call_table32[__NR_setgroups32] =
- POINTER2SYSCALL afs32_xsetgroups32;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#endif /* __NR_setgroups32 */
-#ifdef AFS_AMD64_LINUX20_ENV
- if (ia32_sys_call_table) {
- sys32_setgroupsp =
- SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups];
- ia32_sys_call_table[__NR_ia32_setgroups] =
- POINTER2SYSCALL afs32_xsetgroups;
-#if defined(__NR_ia32_setgroups32)
- sys32_setgroups32p =
- SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups32];
- ia32_sys_call_table[__NR_ia32_setgroups32] =
- POINTER2SYSCALL afs32_xsetgroups32;
-#endif /* __NR_ia32_setgroups32 */
- }
-#endif /* AFS_AMD64_LINUX20_ENV */
-#endif /* AFS_IA64_LINUX20_ENV */
-
-#ifdef AFS_PPC64_LINUX20_ENV
- afs_ni_syscall = set_afs_syscall(afs_syscall);
- sys_setgroupsp = set_afs_xsetgroups_syscall(afs_xsetgroups);
- sys32_setgroupsp = set_afs_xsetgroups_syscall32(afs32_xsetgroups);
-#endif
- }
-
- osi_sysctl_init();
- afsproc_init();
-
- return 0;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-void __exit
-afs_cleanup(void)
-#else
-void
-cleanup_module(void)
-#endif
-{
- struct task_struct *t;
-
- osi_sysctl_clean();
- if (sys_call_table) {
-#if defined(AFS_IA64_LINUX20_ENV)
- sys_call_table[__NR_setgroups - 1024] =
- POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
- sys_call_table[__NR_afs_syscall - 1024] = afs_ni_syscall;
-#else /* AFS_IA64_LINUX20_ENV */
- sys_call_table[__NR_setgroups] = POINTER2SYSCALL sys_setgroupsp;
- sys_call_table[__NR_afs_syscall] = afs_ni_syscall;
-# ifdef AFS_SPARC64_LINUX20_ENV
- sys_call_table32[__NR_setgroups] = POINTER2SYSCALL sys32_setgroupsp;
- sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
-# endif
-# if defined(__NR_setgroups32)
- sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
-# ifdef AFS_SPARC64_LINUX20_ENV
- sys_call_table32[__NR_setgroups32] =
- POINTER2SYSCALL sys32_setgroups32p;
-# endif
-# endif
-#endif /* AFS_IA64_LINUX20_ENV */
-#ifdef AFS_AMD64_LINUX20_ENV
- if (ia32_sys_call_table) {
- ia32_sys_call_table[__NR_ia32_setgroups] =
- POINTER2SYSCALL sys32_setgroupsp;
- ia32_sys_call_table[__NR_ia32_afs_syscall] =
- POINTER2SYSCALL ia32_ni_syscall;
-# if defined(__NR_setgroups32)
- ia32_sys_call_table[__NR_ia32_setgroups32] =
- POINTER2SYSCALL sys32_setgroups32p;
-#endif
- }
-#endif
- }
-#ifdef AFS_PPC64_LINUX20_ENV
- set_afs_syscall(afs_ni_syscall);
- set_afs_xsetgroups_syscall(sys_setgroupsp);
- set_afs_xsetgroups_syscall32(sys32_setgroupsp);
-#endif
- unregister_filesystem(&afs_fs_type);
-
- osi_linux_free_inode_pages(); /* Invalidate all pages using AFS inodes. */
- osi_linux_free_afs_memory();
-
- afsproc_exit();
- return;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-module_init(afs_init);
-module_exit(afs_cleanup);
-#endif
-
-
-#if !defined(AFS_LINUX24_ENV)
-static long
-get_page_offset(void)
-{
-#if defined(AFS_PPC_LINUX22_ENV) || defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_S390_LINUX22_ENV) || defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PARISC_LINUX24_ENV) || defined(AFS_AMD64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
- return PAGE_OFFSET;
-#else
- struct task_struct *p, *q;
-
- /* search backward thru the circular list */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- read_lock(&tasklist_lock);
-#endif
- /* search backward thru the circular list */
-#ifdef DEFINED_PREV_TASK
- for (q = current; p = q; q = prev_task(p)) {
-#else
- for (p = current; p; p = p->prev_task) {
-#endif
- if (p->pid == 1) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- read_unlock(&tasklist_lock);
-#endif
- return p->addr_limit.seg;
- }
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- read_unlock(&tasklist_lock);
-#endif
- return 0;
-#endif
-}
-#endif /* !AFS_LINUX24_ENV */
+++ /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
- */
-
-/*
- * Exported linux support routines.
- */
-#ifndef _OSI_PROTO_H_
-#define _OSI_PROTO_H_
-
-/* osi_alloc.c */
-extern void *osi_linux_alloc(unsigned int size, int drop_glock);
-extern void osi_linux_free(void *addr);
-extern void osi_linux_free_afs_memory(void);
-/* Debugging aid */
-extern void osi_linux_verify_alloced_memory(void);
-
-/* osi_cred.c */
-extern cred_t *crget(void);
-extern void crfree(cred_t * cr);
-extern cred_t *crdup(cred_t * cr);
-extern cred_t *crref(void);
-extern void crset(cred_t * cr);
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-
-/* osi_misc.c */
-extern int osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- vnode_t ** dirvpp, struct dentry **dpp);
-extern int osi_InitCacheInfo(char *aname);
-extern int osi_rdwr(int rw, struct osi_file *file, caddr_t addrp,
- size_t asize, size_t * resid);
-extern void inline setup_uio(uio_t * uiop, struct iovec *iovecp, char *buf,
- afs_offs_t pos, int count, uio_flag_t flag,
- uio_seg_t seg);
-extern int osi_file_uio_rdwr(struct osi_file *osifile, uio_t * uiop, int rw);
-extern void afs_osi_SetTime(osi_timeval_t * tvp);
-extern void osi_linux_free_inode_pages(void);
-extern void check_bad_parent(struct dentry *dp);
-
-/* osi_vm.c */
-extern int osi_VM_FlushVCache(struct vcache *avc, int *slept);
-extern void osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred,
- int sync);
-extern void osi_VM_FSyncInval(struct vcache *avc);
-extern void osi_VM_StoreAllSegments(struct vcache *avc);
-extern void osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp);
-extern void osi_VM_Truncate(struct vcache *avc, int alen,
- struct AFS_UCRED *acred);
-
-/* osi_vfsops.c */
-extern void set_inode_cache(struct inode *ip, struct vattr *vp);
-
-
-#endif /* _OSI_PROTO_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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_sleep.c,v 1.21 2003/07/15 23:14:24 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-static char waitV, dummyV;
-
-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)
-{
- afs_int32 endTime;
- struct timer_list *timer = NULL;
- int code;
-
- AFS_STATCNT(osi_Wait);
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) current;
-
- do {
- AFS_ASSERT_GLOCK();
- code = osi_TimedSleep(&waitV, ams, 1);
- if (code)
- break;
- 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 */
-#if defined(AFS_LINUX24_ENV)
- wait_queue_head_t cond;
-#else
- struct wait_queue *cond;
-#endif
-} 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)
- return NULL;
-
- newp->event = event;
- newp->refcount = 1;
- return newp;
-}
-
-/* afs_addevent -- allocates a new event for the address. It isn't returned;
- * instead, afs_getevent should be called again. Thus, the real effect of
- * this routine is to add another event to the hash bucket for this
- * address.
- *
- * Locks:
- * Called with GLOCK held. However the function might drop
- * GLOCK when it calls osi_AllocSmallSpace for allocating
- * a new event (In Linux, the allocator drops GLOCK to avoid
- * a deadlock).
- */
-
-static void
-afs_addevent(char *event)
-{
- int hashcode;
- afs_event_t *newp;
-
- AFS_ASSERT_GLOCK();
- hashcode = afs_evhash(event);
- newp = osi_linux_alloc(sizeof(afs_event_t), 0);
- afs_evhashcnt++;
- newp->next = afs_evhasht[hashcode];
- afs_evhasht[hashcode] = newp;
-#if defined(AFS_LINUX24_ENV)
- init_waitqueue_head(&newp->cond);
-#else
- init_waitqueue(&newp->cond);
-#endif
- newp->seq = 0;
- newp->event = &dummyV; /* Dummy address for new events */
- newp->refcount = 0;
-}
-
-#ifndef set_current_state
-#define set_current_state(x) current->state = (x);
-#endif
-
-/* Release the specified event */
-#define relevent(evp) ((evp)->refcount--)
-
-/* afs_osi_SleepSig
- *
- * Waits for an event to be notified, returning early if a signal
- * is received. Returns EINTR if signaled, and 0 otherwise.
- */
-int
-afs_osi_SleepSig(void *event)
-{
- struct afs_event *evp;
- int seq, retval;
-#ifdef DECLARE_WAITQUEUE
- DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue wait = { current, NULL };
-#endif
-
- evp = afs_getevent(event);
- if (!evp) {
- afs_addevent(event);
- evp = afs_getevent(event);
- }
-
- seq = evp->seq;
- retval = 0;
-
- add_wait_queue(&evp->cond, &wait);
- while (seq == evp->seq) {
- set_current_state(TASK_INTERRUPTIBLE);
- AFS_ASSERT_GLOCK();
- AFS_GUNLOCK();
- schedule();
- AFS_GLOCK();
- if (signal_pending(current)) {
- retval = EINTR;
- break;
- }
- }
- remove_wait_queue(&evp->cond, &wait);
- set_current_state(TASK_RUNNING);
-
- relevent(evp);
- return retval;
-}
-
-/* afs_osi_Sleep -- waits for an event to be notified, ignoring signals.
- * - NOTE: that on Linux, there are circumstances in which TASK_INTERRUPTIBLE
- * can wake up, even if all signals are blocked
- * - TODO: handle signals correctly by passing an indication back to the
- * caller that the wait has been interrupted and the stack should be cleaned
- * up preparatory to signal delivery
- */
-void
-afs_osi_Sleep(void *event)
-{
- sigset_t saved_set;
-
- SIG_LOCK(current);
- saved_set = current->blocked;
- sigfillset(¤t->blocked);
- RECALC_SIGPENDING(current);
- SIG_UNLOCK(current);
-
- afs_osi_SleepSig(event);
-
- SIG_LOCK(current);
- current->blocked = saved_set;
- RECALC_SIGPENDING(current);
- SIG_UNLOCK(current);
-}
-
-/* osi_TimedSleep
- *
- * Arguments:
- * event - event to sleep on
- * ams --- max sleep time in milliseconds
- * aintok - 1 if should sleep interruptibly
- *
- * Returns 0 if timeout, EINTR if signalled, and EGAIN if it might
- * have raced.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- long ticks = (ams * HZ / 1000) + 1;
- struct afs_event *evp;
-#ifdef DECLARE_WAITQUEUE
- DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue wait = { current, NULL };
-#endif
-
- evp = afs_getevent(event);
- if (!evp) {
- afs_addevent(event);
- evp = afs_getevent(event);
- }
-
- add_wait_queue(&evp->cond, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- /* always sleep TASK_INTERRUPTIBLE to keep load average
- * from artifically increasing. */
- AFS_GUNLOCK();
-
- if (aintok) {
- if (schedule_timeout(ticks))
- code = EINTR;
- } else
- schedule_timeout(ticks);
-
- AFS_GLOCK();
- remove_wait_queue(&evp->cond, &wait);
- set_current_state(TASK_RUNNING);
-
- relevent(evp);
-
- return code;
-}
-
-
-int
-afs_osi_Wakeup(void *event)
-{
- int ret = 2;
- struct afs_event *evp;
-
- evp = afs_getevent(event);
- if (!evp) /* No sleepers */
- return 1;
-
- if (evp->refcount > 1) {
- evp->seq++;
- wake_up(&evp->cond);
- ret = 0;
- }
- relevent(evp);
- return ret;
-}
+++ /dev/null
-/*
- * osi_sysctl.c: Linux sysctl interface to OpenAFS
- *
- * $Id: osi_sysctl.c,v 1.7 2003/08/08 19:55:05 shadow Exp $
- *
- * Written Jan 30, 2002 by Kris Van Hees (Sine Nomine Associates)
- */
-
-#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 */
-
-#include <linux/sysctl.h>
-#include <linux/config.h>
-
-/* From afs_analyze.c */
-extern afs_int32 hm_retry_RO;
-extern afs_int32 hm_retry_RW;
-extern afs_int32 hm_retry_int;
-
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *afs_sysctl = NULL;
-
-static ctl_table afs_sysctl_table[] = {
- {1, "hm_retry_RO",
- &hm_retry_RO, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {2, "hm_retry_RW",
- &hm_retry_RW, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {3, "hm_retry_int",
- &hm_retry_int, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {4, "GCPAGs",
- &afs_gcpags, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {5, "rx_deadtime",
- &afs_rx_deadtime, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {6, "bkVolPref",
- &afs_bkvolpref, sizeof(afs_int32), 0644, NULL,
- &proc_dointvec}
- ,
- {0}
-};
-
-static ctl_table fs_sysctl_table[] = {
- {1, "afs", NULL, 0, 0555, afs_sysctl_table},
- {0}
-};
-
-int
-osi_sysctl_init()
-{
- afs_sysctl = register_sysctl_table(fs_sysctl_table, 0);
- if (!afs_sysctl)
- return -1;
-
- return 0;
-}
-
-void
-osi_sysctl_clean()
-{
- if (afs_sysctl) {
- unregister_sysctl_table(afs_sysctl);
- afs_sysctl = NULL;
- }
-}
-
-#endif /* CONFIG_SYSCTL */
+++ /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
- */
-
-/*
- * Linux interpretations of vnode and vfs structs.
- *
- * The Linux "inode" has been abstracted to the fs independent part to avoid
- * wasting 100+bytes per vnode.
- */
-
-#ifndef OSI_VFS_H_
-#define OSI_VFS_H_
-
-#if !defined(AFS_LINUX26_ENV)
-/* The vnode should match the current implementation of the fs independent
- * part of the Linux inode.
- */
-/* The first cut is to continue to use a separate vnode pool. */
-/* LINUX VNODE INCLUDED BELOW -- DO NOT MODIFY */
-
-typedef struct vnode vnode_t;
-#else
-typedef struct inode vnode_t;
-#define vnode inode
-#endif
-
-/* Map vnode fields to inode fields. */
-#define i_number i_ino
-#define v_count i_count
-#define v_op i_op
-#if defined(AFS_LINUX24_ENV)
-#define v_fop i_fop
-#endif
-#define v_type i_mode
-#define v_vfsp i_sb
-#define vfs_vnodecovered s_covered
-
-/* v_type bits map to mode bits: */
-#define VNON 0
-#define VREG S_IFREG
-#define VDIR S_IFDIR
-#define VBLK S_IFBLK
-#define VCHR S_IFCHR
-#define VLNK S_IFLNK
-#define VSOCK S_IFSOCK
-#define VFIFO S_IFIFO
-
-/* vcexcl - used only by afs_create */
-enum vcexcl { EXCL, NONEXCL } ;
-
-/* afs_open and afs_close needs to distinguish these cases */
-#define FWRITE O_WRONLY|O_RDWR|O_APPEND
-#define FTRUNC O_TRUNC
-
-
-#define IO_APPEND O_APPEND
-#define FSYNC O_SYNC
-
-#define VTOI(V) ((struct inode*)V)
-#define VFS_STATFS(V, S) ((V)->s_op->statfs)((V), (S), sizeof(*(S)))
-
-
-
-/* Various mode bits */
-#define VWRITE S_IWUSR
-#define VREAD S_IRUSR
-#define VEXEC S_IXUSR
-#define VSUID S_ISUID
-#define VSGID S_ISGID
-
-
-#define vfs super_block
-
-typedef struct vattr {
- int va_type; /* One of v_types above. */
- afs_size_t va_size;
- unsigned long va_blocks;
- unsigned long va_blocksize;
- int va_mask; /* AT_xxx operation to perform. */
- umode_t va_mode; /* mode bits. */
- uid_t va_uid;
- gid_t va_gid;
- int va_fsid; /* Not used? */
- dev_t va_rdev;
- ino_t va_nodeid; /* Inode number */
- nlink_t va_nlink; /* link count for file. */
- struct timeval va_atime;
- struct timeval va_mtime;
- struct timeval va_ctime;
-} vattr_t;
-
-#define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
-
-
-/* va_masks - these should match their respective ATTR_xxx #defines in fs.h.
- * afs_notify_change has to use the attr bits in both the Linux and AFS
- * meanings. The glue layer code uses the ATTR_xxx style names.
- */
-#define AT_SIZE ATTR_SIZE
-#define AT_MODE ATTR_MODE
-#undef AT_UID
-#define AT_UID ATTR_UID
-#undef AT_GID
-#define AT_GID ATTR_GID
-#define AT_MTIME ATTR_MTIME
-
-
-#define vnodeops inode_operations
-
-#endif /* OSI_VFS_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
- */
-
-/*
- * VFS operations for Linux
- *
- * super_block operations should return negated errno to Linux.
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_vfsops.c,v 1.27 2004/04/21 02:20:23 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#if !defined(AFS_LINUX26_ENV)
-#include "h/locks.h"
-#endif
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-
-#define __NO_VERSION__ /* don't define kernel_version in module.h */
-#include <linux/module.h>
-
-
-struct vcache *afs_globalVp = 0;
-struct vfs *afs_globalVFS = 0;
-#if defined(AFS_LINUX24_ENV)
-struct nameidata afs_cacheNd;
-#endif
-int afs_was_mounted = 0; /* Used to force reload if mount/unmount/mount */
-
-extern struct super_operations afs_sops;
-extern afs_rwlock_t afs_xvcache;
-extern struct afs_q VLRU;
-
-extern struct dentry_operations afs_dentry_operations;
-
-/* Forward declarations */
-static void iattr2vattr(struct vattr *vattrp, struct iattr *iattrp);
-static void update_inode_cache(struct inode *ip, struct vattr *vp);
-static int afs_root(struct super_block *afsp);
-struct super_block *afs_read_super(struct super_block *sb, void *data, int silent);
-int afs_fill_super(struct super_block *sb, void *data, int silent);
-static struct super_block *afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data);
-void put_inode_on_dummy_list(struct inode *ip);
-
-/* afs_file_system
- * VFS entry for Linux - installed in init_module
- * Linux mounts file systems by:
- * 1) register_filesystem(&afs_file_system) - done in init_module
- * 2) Mount call comes to us via do_mount -> read_super -> afs_read_super.
- * We are expected to setup the super_block. See afs_read_super.
- */
-#if defined(AFS_LINUX26_ENV)
-struct backing_dev_info afs_backing_dev_info = {
- .ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
- .state = 0,
-};
-
-struct file_system_type afs_fs_type = {
- .owner = THIS_MODULE,
- .name = "afs",
- .get_sb = afs_get_sb,
- .kill_sb = kill_anon_super,
- .fs_flags = FS_BINARY_MOUNTDATA,
-};
-#elif defined(AFS_LINUX24_ENV)
-DECLARE_FSTYPE(afs_fs_type, "afs", afs_read_super, 0);
-#else
-struct file_system_type afs_fs_type = {
- "afs", /* name - used by mount operation. */
- 0, /* requires_dev - no for network filesystems. mount() will
- * pass us an "unnamed" device. */
- afs_read_super, /* wrapper to afs_mount */
- NULL /* pointer to next file_system_type once registered. */
-};
-#endif
-
-/* afs_read_super
- * read the "super block" for AFS - roughly eguivalent to struct vfs.
- * dev, covered, s_rd_only, s_dirt, and s_type will be set by read_super.
- */
-#if defined(AFS_LINUX26_ENV)
-static struct super_block *
-afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
-{
- return get_sb_nodev(fs_type, flags, data, afs_fill_super);
-}
-
-int
-afs_fill_super(struct super_block *sb, void *data, int silent)
-#else
-struct super_block *
-afs_read_super(struct super_block *sb, void *data, int silent)
-#endif
-{
- int code = 0;
-
- AFS_GLOCK();
- if (afs_was_mounted) {
- printf
- ("You must reload the AFS kernel extensions before remounting AFS.\n");
- AFS_GUNLOCK();
-#if defined(AFS_LINUX26_ENV)
- return -EINVAL;
-#else
- return NULL;
-#endif
- }
- afs_was_mounted = 1;
-
- /* Set basics of super_block */
-#if !defined(AFS_LINUX24_ENV)
- lock_super(sb);
-#endif
-#if defined(AFS_LINUX26_ENV)
- __module_get(THIS_MODULE);
-#else
- MOD_INC_USE_COUNT;
-#endif
-
- afs_globalVFS = sb;
- sb->s_blocksize = 1024;
- sb->s_blocksize_bits = 10;
- sb->s_magic = AFS_VFSMAGIC;
- sb->s_op = &afs_sops; /* Super block (vfs) ops */
-#if defined(MAX_NON_LFS)
- sb->s_maxbytes = MAX_NON_LFS;
-#endif
- code = afs_root(sb);
- if (code)
-#if defined(AFS_LINUX26_ENV)
- module_put(THIS_MODULE);
-#else
- MOD_DEC_USE_COUNT;
-#endif
-
-#if !defined(AFS_LINUX24_ENV)
- unlock_super(sb);
-#endif
-
- AFS_GUNLOCK();
-#if defined(AFS_LINUX26_ENV)
- return code ? -EINVAL : 0;
-#else
- return code ? NULL : sb;
-#endif
-}
-
-
-/* afs_root - stat the root of the file system. AFS global held on entry. */
-static int
-afs_root(struct super_block *afsp)
-{
- register afs_int32 code = 0;
- struct vrequest treq;
- register struct vcache *tvp = 0;
-
- AFS_STATCNT(afs_root);
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- cred_t *credp = crref();
-
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
- tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
- if (tvp) {
- extern struct inode_operations afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
- extern struct file_operations afs_dir_fops;
-#endif
-
- /* "/afs" is a directory, reset inode ops accordingly. */
- AFSTOV(tvp)->v_op = &afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
- AFSTOV(tvp)->v_fop = &afs_dir_fops;
-#endif
-
- /* setup super_block and mount point inode. */
- afs_globalVp = tvp;
-#if defined(AFS_LINUX24_ENV)
- afsp->s_root = d_alloc_root(AFSTOI(tvp));
-#else
- afsp->s_root = d_alloc_root(AFSTOI(tvp), NULL);
-#endif
- afsp->s_root->d_op = &afs_dentry_operations;
- } else
- code = ENOENT;
- }
- crfree(credp);
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, afs_globalVp,
- ICL_TYPE_INT32, code);
- return code;
-}
-
-/* super_operations */
-
-/* afs_notify_change
- * Linux version of setattr call. What to change is in the iattr struct.
- * We need to set bits in both the Linux inode as well as the vcache.
- */
-int
-afs_notify_change(struct dentry *dp, struct iattr *iattrp)
-{
- struct vattr vattr;
- int code;
- cred_t *credp = crref();
- struct inode *ip = dp->d_inode;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- VATTR_NULL(&vattr);
- iattr2vattr(&vattr, iattrp); /* Convert for AFS vnodeops call. */
- update_inode_cache(ip, &vattr);
- code = afs_setattr(ITOAFS(ip), &vattr, credp);
- afs_CopyOutAttrs(ITOAFS(ip), &vattr);
- /* Note that the inode may still not have all the correct info. But at
- * least we've got the newest version of what was supposed to be set.
- */
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-
-/* This list is simply used to initialize the i_list member of the
- * linux inode. This stops linux inode syncing code from choking on our
- * inodes.
- */
-static LIST_HEAD(dummy_inode_list);
-
-
-/* This is included for documentation only. */
-/* afs_write_inode
- * Used to flush in core inode to disk. We don't need to do this. Top level
- * write_inode() routine will clear i_dirt. If this routine is in the table,
- * it's expected to do the cleaning and clear i_dirt.
- *
- * 9/24/99: This is what we thought until we discovered msync() does end up calling
- * this function to sync a single inode to disk. msync() only flushes selective
- * pages to disk. So it needs an inode syncing function to update metadata when it
- * has synced some pages of a file to disk.
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static void
-afs_write_inode(struct inode *ip, int unused)
-#else
-static void
-afs_write_inode(struct inode *ip)
-#endif
-{
- list_del(&ip->i_list);
- /* and put it back on our dummy list. */
- put_inode_on_dummy_list(ip);
-
- /* for now we don't actually update the metadata during msync. This
- * is just to keep linux happy. */
-}
-
-
-static void
-afs_destroy_inode(struct inode *ip)
-{
- ip->i_state = 0;
-}
-
-
-/* afs_put_inode
- * called from iput when count goes to zero. Linux version of inactive.
- * For Linux 2.2, this funcionality has moved to the delete inode super op.
- * If we use the common inode pool, we'll need to set i_nlink to 0 here.
- * That will trigger the call to delete routine.
- */
-
-static void
-afs_delete_inode(struct inode *ip)
-{
- struct vcache *vp = ITOAFS(ip);
-
-#ifdef AFS_LINUX26_ENV
- put_inode_on_dummy_list(ip);
-#endif
-
- AFS_GLOCK();
- osi_clear_inode(ip);
- AFS_GUNLOCK();
-}
-
-
-/* afs_put_super
- * Called from unmount to release super_block. */
-static void
-afs_put_super(struct super_block *sbp)
-{
- extern int afs_afs_cold_shutdown;
- int code = 0;
- int fv_slept;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
-
-#if !defined(AFS_LINUX26_ENV)
- if (!suser()) {
- AFS_GUNLOCK();
- return;
- }
-#endif
-
- afs_globalVFS = 0;
- afs_globalVp = 0;
- afs_shutdown();
-#if defined(AFS_LINUX24_ENV)
- path_release(&afs_cacheNd);
-#endif
-
- osi_linux_verify_alloced_memory();
- done:
- AFS_GUNLOCK();
-
- if (!code) {
- sbp->s_dev = 0;
-#if defined(AFS_LINUX26_ENV)
- module_put(THIS_MODULE);
-#else
- MOD_DEC_USE_COUNT;
-#endif
- }
-}
-
-
-/* afs_statfs
- * statp is in user space, so we need to cobble together a statfs, then
- * copy it.
- */
-#if defined(AFS_LINUX26_ENV)
-int
-afs_statfs(struct super_block *sbp, struct kstatfs *statp)
-#elif defined(AFS_LINUX24_ENV)
-int
-afs_statfs(struct super_block *sbp, struct statfs *statp)
-#else
-int
-afs_statfs(struct super_block *sbp, struct statfs *__statp, int size)
-#endif
-{
-#if !defined(AFS_LINUX24_ENV)
- struct statfs stat;
-
- if (size < sizeof(struct statfs))
- return;
-
- memset(&stat, 0, size);
- statp = &stat;
-#endif
-
- AFS_STATCNT(afs_statfs);
-
- statp->f_type = 0; /* Can we get a real type sometime? */
- statp->f_bsize = sbp->s_blocksize;
- statp->f_blocks = statp->f_bfree = statp->f_bavail = statp->f_files =
- statp->f_ffree = 9000000;
- statp->f_fsid.val[0] = AFS_VFSMAGIC;
- statp->f_fsid.val[1] = AFS_VFSFSID;
- statp->f_namelen = 256;
-
-#if !defined(AFS_LINUX24_ENV)
- memcpy_tofs(__statp, &stat, size);
-#endif
- return 0;
-}
-
-void
-afs_umount_begin(struct super_block *sbp)
-{
- afs_shuttingdown = 1;
-}
-
-struct super_operations afs_sops = {
-#if defined(AFS_LINUX26_ENV)
- .drop_inode = generic_delete_inode,
- .destroy_inode = afs_destroy_inode,
-#endif
- .delete_inode = afs_delete_inode,
- .write_inode = afs_write_inode,
- .put_super = afs_put_super,
- .statfs = afs_statfs,
- .umount_begin = afs_umount_begin
-#if !defined(AFS_LINUX24_ENV)
- .notify_change = afs_notify_change,
-#endif
-};
-
-/************** Support routines ************************/
-
-/* vattr_setattr
- * Set iattr data into vattr. Assume vattr cleared before call.
- */
-static void
-iattr2vattr(struct vattr *vattrp, struct iattr *iattrp)
-{
- vattrp->va_mask = iattrp->ia_valid;
- if (iattrp->ia_valid & ATTR_MODE)
- vattrp->va_mode = iattrp->ia_mode;
- if (iattrp->ia_valid & ATTR_UID)
- vattrp->va_uid = iattrp->ia_uid;
- if (iattrp->ia_valid & ATTR_GID)
- vattrp->va_gid = iattrp->ia_gid;
- if (iattrp->ia_valid & ATTR_SIZE)
- vattrp->va_size = iattrp->ia_size;
- if (iattrp->ia_valid & ATTR_ATIME) {
-#if defined(AFS_LINUX26_ENV)
- vattrp->va_atime.tv_sec = iattrp->ia_atime.tv_sec;
-#else
- vattrp->va_atime.tv_sec = iattrp->ia_atime;
-#endif
- vattrp->va_atime.tv_usec = 0;
- }
- if (iattrp->ia_valid & ATTR_MTIME) {
-#if defined(AFS_LINUX26_ENV)
- vattrp->va_mtime.tv_sec = iattrp->ia_mtime.tv_sec;
-#else
- vattrp->va_mtime.tv_sec = iattrp->ia_mtime;
-#endif
- vattrp->va_mtime.tv_usec = 0;
- }
- if (iattrp->ia_valid & ATTR_CTIME) {
-#if defined(AFS_LINUX26_ENV)
- vattrp->va_ctime.tv_sec = iattrp->ia_ctime.tv_sec;
-#else
- vattrp->va_ctime.tv_sec = iattrp->ia_ctime;
-#endif
- vattrp->va_ctime.tv_usec = 0;
- }
-}
-
-/* update_inode_cache
- * Update inode with info from vattr struct. Use va_mask to determine what
- * to update.
- */
-static void
-update_inode_cache(struct inode *ip, struct vattr *vp)
-{
- if (vp->va_mask & ATTR_MODE)
- ip->i_mode = vp->va_mode;
- if (vp->va_mask & ATTR_UID)
- ip->i_uid = vp->va_uid;
- if (vp->va_mask & ATTR_GID)
- ip->i_gid = vp->va_gid;
- if (vp->va_mask & ATTR_SIZE)
- ip->i_size = vp->va_size;
- if (vp->va_mask & ATTR_ATIME)
-#if defined(AFS_LINUX26_ENV)
- ip->i_atime.tv_sec = vp->va_atime.tv_sec;
-#else
- ip->i_atime = vp->va_atime.tv_sec;
-#endif
- if (vp->va_mask & ATTR_MTIME)
-#if defined(AFS_LINUX26_ENV)
- ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
-#else
- ip->i_mtime = vp->va_mtime.tv_sec;
-#endif
- if (vp->va_mask & ATTR_CTIME)
-#if defined(AFS_LINUX26_ENV)
- ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
-#else
- ip->i_ctime = vp->va_ctime.tv_sec;
-#endif
-}
-
-/* vattr2inode
- * Rewrite the inode cache from the attr. Assumes all vattr fields are valid.
- */
-void
-vattr2inode(struct inode *ip, struct vattr *vp)
-{
- ip->i_ino = vp->va_nodeid;
- ip->i_nlink = vp->va_nlink;
- ip->i_blocks = vp->va_blocks;
- ip->i_blksize = vp->va_blocksize;
- ip->i_rdev = vp->va_rdev;
- ip->i_mode = vp->va_mode;
- ip->i_uid = vp->va_uid;
- ip->i_gid = vp->va_gid;
- ip->i_size = vp->va_size;
-#if defined(AFS_LINUX26_ENV)
- ip->i_atime.tv_sec = vp->va_atime.tv_sec;
- ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
- ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
-#else
- ip->i_atime = vp->va_atime.tv_sec;
- ip->i_mtime = vp->va_mtime.tv_sec;
- ip->i_ctime = vp->va_ctime.tv_sec;
-#endif
-}
-
-/* Put this afs inode on our own dummy list. Linux expects to see inodes
- * nicely strung up in lists. Linux inode syncing code chokes on our inodes if
- * they're not on any lists.
- */
-void
-put_inode_on_dummy_list(struct inode *ip)
-{
- /* Initialize list. See explanation above. */
- list_add(&ip->i_list, &dummy_inode_list);
-}
-
-/* And yet another routine to update the inode cache - called from ProcessFS */
-void
-vcache2inode(struct vcache *avc)
-{
- struct vattr vattr;
-
- VATTR_NULL(&vattr);
- afs_CopyOutAttrs(avc, &vattr); /* calls vattr2inode */
-}
-
-/* Yet another one for fakestat'ed mountpoints */
-void
-vcache2fakeinode(struct vcache *rootvp, struct vcache *mpvp)
-{
- struct vattr vattr;
-
- VATTR_NULL(&vattr);
- afs_CopyOutAttrs(rootvp, &vattr);
- vattr2inode(AFSTOI(mpvp), &vattr);
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_vm.c,v 1.16 2004/04/12 16:04:32 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-/* Linux VM operations
- *
- * The general model for Linux is to treat vm as a cache that's:
- * 1) explicitly updated by AFS when AFS writes the data to the cache file.
- * 2) reads go through the cache. A cache miss is satisfied by the filesystem.
- *
- * This means flushing VM is not required on this OS.
- */
-
-/* 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.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- struct inode *ip = AFSTOI(avc);
-
- if (VREFCOUNT(avc) != 0)
- return EBUSY;
-
- if (avc->opens != 0)
- return EBUSY;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- truncate_inode_pages(&ip->i_data, 0);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- truncate_inode_pages(ip, 0);
-#else
- invalidate_inode_pages(ip);
-#endif
- return 0;
-}
-
-/* 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, struct AFS_UCRED *acred, int sync)
-{
- struct inode *ip = AFSTOI(avc);
-
-#if defined(AFS_LINUX26_ENV)
- invalidate_inode_pages(ip->i_mapping);
-#else
- invalidate_inode_pages(ip);
-#endif
-}
-
-/* Flush and invalidate pages, for fsync() with INVAL flag
- *
- * Locking: only the global lock is held.
- */
-void
-osi_VM_FSyncInval(struct vcache *avc)
-{
-
-}
-
-/* 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)
-{
- struct inode *ip = AFSTOI(avc);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
- /* filemap_fdatasync() only exported in 2.4.5 and above */
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
-#if defined(AFS_LINUX26_ENV)
- filemap_fdatawrite(ip->i_mapping);
-#else
- filemap_fdatasync(ip->i_mapping);
-#endif
- filemap_fdatawait(ip->i_mapping);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 121);
-#endif
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- struct inode *ip = AFSTOI(avc);
-
- truncate_inode_pages(&ip->i_data, 0);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- struct inode *ip = AFSTOI(avc);
-
- truncate_inode_pages(ip, 0);
-#else
- invalidate_inode_pages(AFSTOI(avc));
-#endif
-}
-
-/* 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, struct AFS_UCRED *acred)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- struct inode *ip = AFSTOI(avc);
-
- truncate_inode_pages(&ip->i_data, alen);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- struct inode *ip = AFSTOI(avc);
-
- truncate_inode_pages(ip, alen);
-#else
- invalidate_inode_pages(AFSTOI(avc));
-#endif
-}
+++ /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
- */
-
-/*
- * Linux specific vnodeops. Also includes the glue routines required to call
- * AFS vnodeops.
- *
- * So far the only truly scary part is that Linux relies on the inode cache
- * to be up to date. Don't you dare break a callback and expect an fstat
- * to give you meaningful information. This appears to be fixed in the 2.1
- * development kernels. As it is we can fix this now by intercepting the
- * stat calls.
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.74 2004/04/21 02:20:23 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#include "afs/afs_osidnlc.h"
-#include "h/mm.h"
-#include "h/pagemap.h"
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-
-#ifdef pgoff2loff
-#define pageoff(pp) pgoff2loff((pp)->index)
-#else
-#define pageoff(pp) pp->offset
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-#define UnlockPage(pp) unlock_page(pp)
-#endif
-
-extern struct vcache *afs_globalVp;
-extern afs_rwlock_t afs_xvcache;
-
-#if defined(AFS_LINUX24_ENV)
-extern struct inode_operations afs_file_iops;
-extern struct address_space_operations afs_file_aops;
-struct address_space_operations afs_symlink_aops;
-#endif
-extern struct inode_operations afs_dir_iops;
-extern struct inode_operations afs_symlink_iops;
-
-
-static ssize_t
-afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
-{
- ssize_t code;
- struct vcache *vcp = ITOAFS(fp->f_dentry->d_inode);
- cred_t *credp = crref();
- struct vrequest treq;
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
- 99999);
-
- /* get a validated vcache entry */
- code = afs_InitReq(&treq, credp);
- if (!code)
- code = afs_VerifyVCache(vcp, &treq);
-
- if (code)
- code = -code;
- else {
-#ifdef AFS_64BIT_CLIENT
- if (*offp + count > afs_vmMappingEnd) {
- uio_t tuio;
- struct iovec iov;
- afs_size_t oldOffset = *offp;
- afs_int32 xfered = 0;
-
- if (*offp < afs_vmMappingEnd) {
- /* special case of a buffer crossing the VM mapping end */
- afs_int32 tcount = afs_vmMappingEnd - *offp;
- count -= tcount;
- osi_FlushPages(vcp, credp); /* ensure stale pages are gone */
- AFS_GUNLOCK();
- code = generic_file_read(fp, buf, tcount, offp);
- AFS_GLOCK();
- if (code != tcount) {
- goto done;
- }
- xfered = tcount;
- }
- setup_uio(&tuio, &iov, buf + xfered, (afs_offs_t) * offp, count,
- UIO_READ, AFS_UIOSYS);
- code = afs_read(vcp, &tuio, credp, 0, 0, 0);
- xfered += count - tuio.uio_resid;
- if (code != 0) {
- afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER,
- vcp, ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, -1,
- ICL_TYPE_INT32, code);
- code = xfered;
- *offp += count - tuio.uio_resid;
- } else {
- code = xfered;
- *offp += count;
- }
- done:
- ;
- } else {
-#endif /* AFS_64BIT_CLIENT */
- osi_FlushPages(vcp, credp); /* ensure stale pages are gone */
- AFS_GUNLOCK();
- code = generic_file_read(fp, buf, count, offp);
- AFS_GLOCK();
-#ifdef AFS_64BIT_CLIENT
- }
-#endif /* AFS_64BIT_CLIENT */
- }
-
- afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
- code);
-
- AFS_GUNLOCK();
- crfree(credp);
- return code;
-}
-
-
-/* Now we have integrated VM for writes as well as reads. generic_file_write
- * also takes care of re-positioning the pointer if file is open in append
- * mode. Call fake open/close to ensure we do writes of core dumps.
- */
-static ssize_t
-afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
-{
- ssize_t code = 0;
- int code2;
- struct vcache *vcp = ITOAFS(fp->f_dentry->d_inode);
- struct vrequest treq;
- cred_t *credp = crref();
- afs_offs_t toffs;
-
- AFS_GLOCK();
-
- afs_Trace4(afs_iclSetp, CM_TRACE_WRITEOP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
- (fp->f_flags & O_APPEND) ? 99998 : 99999);
-
-
- /* get a validated vcache entry */
- code = (ssize_t) afs_InitReq(&treq, credp);
- if (!code)
- code = (ssize_t) afs_VerifyVCache(vcp, &treq);
-
- ObtainWriteLock(&vcp->lock, 529);
- afs_FakeOpen(vcp);
- ReleaseWriteLock(&vcp->lock);
- if (code)
- code = -code;
- else {
-#ifdef AFS_64BIT_CLIENT
- toffs = *offp;
- if (fp->f_flags & O_APPEND)
- toffs += vcp->m.Length;
- if (toffs + count > afs_vmMappingEnd) {
- uio_t tuio;
- struct iovec iov;
- afs_size_t oldOffset = *offp;
- afs_int32 xfered = 0;
-
- if (toffs < afs_vmMappingEnd) {
- /* special case of a buffer crossing the VM mapping end */
- afs_int32 tcount = afs_vmMappingEnd - *offp;
- count -= tcount;
- AFS_GUNLOCK();
- code = generic_file_write(fp, buf, tcount, offp);
- AFS_GLOCK();
- if (code != tcount) {
- goto done;
- }
- xfered = tcount;
- toffs += tcount;
- }
- setup_uio(&tuio, &iov, buf + xfered, (afs_offs_t) toffs, count,
- UIO_WRITE, AFS_UIOSYS);
- code = afs_write(vcp, &tuio, fp->f_flags, credp, 0);
- xfered += count - tuio.uio_resid;
- if (code != 0) {
- code = xfered;
- *offp += count - tuio.uio_resid;
- } else {
- /* 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 (AFS_CHUNKBASE(tuio.afsio_offset) !=
- AFS_CHUNKBASE(oldOffset)) {
- ObtainWriteLock(&vcp->lock, 402);
- code = afs_DoPartialWrite(vcp, &treq);
- vcp->states |= CDirty;
- ReleaseWriteLock(&vcp->lock);
- }
- code = xfered;
- *offp += count;
- toffs += count;
- ObtainWriteLock(&vcp->lock, 400);
- vcp->m.Date = osi_Time(); /* Set file date (for ranlib) */
- /* extend file */
- if (!(fp->f_flags & O_APPEND) && toffs > vcp->m.Length) {
- vcp->m.Length = toffs;
- }
- ReleaseWriteLock(&vcp->lock);
- }
- done:
- ;
- } else {
-#endif /* AFS_64BIT_CLIENT */
- AFS_GUNLOCK();
- code = generic_file_write(fp, buf, count, offp);
- AFS_GLOCK();
-#ifdef AFS_64BIT_CLIENT
- }
-#endif /* AFS_64BIT_CLIENT */
- }
-
- ObtainWriteLock(&vcp->lock, 530);
- vcp->m.Date = osi_Time(); /* set modification time */
- afs_FakeClose(vcp, credp);
- if (code >= 0)
- code2 = afs_DoPartialWrite(vcp, &treq);
- if (code2 && code >= 0)
- code = (ssize_t) - code2;
- ReleaseWriteLock(&vcp->lock);
-
- afs_Trace4(afs_iclSetp, CM_TRACE_WRITEOP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
- code);
-
- AFS_GUNLOCK();
- crfree(credp);
- return code;
-}
-
-/* This is a complete rewrite of afs_readdir, since we can make use of
- * filldir instead of afs_readdir_move. Note that changes to vcache/dcache
- * handling and use of bulkstats will need to be reflected here as well.
- */
-static int
-afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
-{
- extern struct DirEntry *afs_dir_GetBlob();
- struct vcache *avc = ITOAFS(FILE_INODE(fp));
- struct vrequest treq;
- register struct dcache *tdc;
- int code;
- int offset;
- int dirpos;
- struct DirEntry *de;
- ino_t ino;
- int len;
- afs_size_t origOffset, tlen;
- cred_t *credp = crref();
- struct afs_fakestat_state fakestat;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- AFS_STATCNT(afs_readdir);
-
- code = afs_InitReq(&treq, credp);
- crfree(credp);
- if (code)
- goto out1;
-
- afs_InitFakeStat(&fakestat);
- code = afs_EvalFakeStat(&avc, &fakestat, &treq);
- if (code)
- goto out;
-
- /* update the cache entry */
- tagain:
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto out;
-
- /* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
- len = tlen;
- if (!tdc) {
- code = -ENOENT;
- goto out;
- }
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((avc->states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- /* Fill in until we get an error or we're done. This implementation
- * takes an offset in units of blobs, rather than bytes.
- */
- code = 0;
- offset = (int) fp->f_pos;
- while (1) {
- dirpos = BlobScan(&tdc->f.inode, offset);
- if (!dirpos)
- break;
-
- de = afs_dir_GetBlob(&tdc->f.inode, dirpos);
- if (!de)
- break;
-
- ino = (avc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- ino &= 0x7fffffff; /* Assumes 32 bit ino_t ..... */
- if (de->name)
- len = strlen(de->name);
- else {
- printf("afs_linux_readdir: afs_dir_GetBlob failed, null name (inode %x, dirpos %d)\n",
- &tdc->f.inode, dirpos);
- DRelease((struct buffer *) de, 0);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
- code = -ENOENT;
- goto out;
- }
-
- /* filldir returns -EINVAL when the buffer is full. */
-#if defined(AFS_LINUX26_ENV) || ((defined(AFS_LINUX24_ENV) || defined(pgoff2loff)) && defined(DECLARE_FSTYPE))
- {
- unsigned int type = DT_UNKNOWN;
- struct VenusFid afid;
- struct vcache *tvc;
- int vtype;
- afid.Cell = avc->fid.Cell;
- afid.Fid.Volume = avc->fid.Fid.Volume;
- afid.Fid.Vnode = ntohl(de->fid.vnode);
- afid.Fid.Unique = ntohl(de->fid.vunique);
- if ((avc->states & CForeign) == 0 && (ntohl(de->fid.vnode) & 1)) {
- type = DT_DIR;
- } else if ((tvc = afs_FindVCache(&afid, 0, 0))) {
- if (tvc->mvstat) {
- type = DT_DIR;
- } else if (((tvc->states) & (CStatd | CTruth))) {
- /* CTruth will be set if the object has
- *ever* been statd */
- vtype = vType(tvc);
- if (vtype == VDIR)
- type = DT_DIR;
- else if (vtype == VREG)
- type = DT_REG;
- /* Don't do this until we're sure it can't be a mtpt */
- /* else if (vtype == VLNK)
- * type=DT_LNK; */
- /* what other types does AFS support? */
- }
- /* clean up from afs_FindVCache */
- afs_PutVCache(tvc);
- }
- code = (*filldir) (dirbuf, de->name, len, offset, ino, type);
- }
-#else
- code = (*filldir) (dirbuf, de->name, len, offset, ino);
-#endif
- DRelease((struct buffer *)de, 0);
- if (code)
- break;
- offset = dirpos + 1 + ((len + 16) >> 5);
- }
- /* If filldir didn't fill in the last one this is still pointing to that
- * last attempt.
- */
- fp->f_pos = (loff_t) offset;
-
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
- code = 0;
-
-out:
- afs_PutFakeStat(&fakestat);
-out1:
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- return code;
-}
-
-
-/* in afs_pioctl.c */
-extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
- unsigned long arg);
-
-
-/* We need to detect unmap's after close. To do that, we need our own
- * vm_operations_struct's. And we need to set them up for both the
- * private and shared mappings. The fun part is that these are all static
- * so we'll have to initialize on the fly!
- */
-static struct vm_operations_struct afs_private_mmap_ops;
-static int afs_private_mmap_ops_inited = 0;
-static struct vm_operations_struct afs_shared_mmap_ops;
-static int afs_shared_mmap_ops_inited = 0;
-
-void
-afs_linux_vma_close(struct vm_area_struct *vmap)
-{
- struct vcache *vcp;
- cred_t *credp;
- int need_unlock = 0;
-
- if (!vmap->vm_file)
- return;
-
- vcp = ITOAFS(FILE_INODE(vmap->vm_file));
- if (!vcp)
- return;
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_VM_CLOSE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_INT32, vcp->mapcnt, ICL_TYPE_INT32, vcp->opens,
- ICL_TYPE_INT32, vcp->execsOrWriters);
- if ((&vcp->lock)->excl_locked == 0 || (&vcp->lock)->pid_writer == MyPidxx) {
- ObtainWriteLock(&vcp->lock, 532);
- need_unlock = 1;
- } else
- printk("AFS_VMA_CLOSE(%d): Skipping Already locked vcp=%p vmap=%p\n",
- MyPidxx, &vcp, &vmap);
- if (vcp->mapcnt) {
- vcp->mapcnt--;
- if (need_unlock)
- ReleaseWriteLock(&vcp->lock);
- if (!vcp->mapcnt) {
- if (need_unlock && vcp->execsOrWriters < 2) {
- credp = crref();
- (void)afs_close(vcp, vmap->vm_file->f_flags, credp);
- /* only decrement the execsOrWriters flag if this is not a
- * writable file. */
- if (!(vmap->vm_file->f_flags & (FWRITE | FTRUNC)))
- vcp->execsOrWriters--;
- vcp->states &= ~CMAPPED;
- crfree(credp);
- } else if ((vmap->vm_file->f_flags & (FWRITE | FTRUNC)))
- vcp->execsOrWriters--;
- /* If we did not have the lock */
- if (!need_unlock) {
- vcp->mapcnt++;
- if (!vcp->execsOrWriters)
- vcp->execsOrWriters = 1;
- }
- }
- } else {
- if (need_unlock)
- ReleaseWriteLock(&vcp->lock);
- }
-
- unlock_exit:
- AFS_GUNLOCK();
-}
-
-static int
-afs_linux_mmap(struct file *fp, struct vm_area_struct *vmap)
-{
- struct vcache *vcp = ITOAFS(FILE_INODE(fp));
- cred_t *credp = crref();
- struct vrequest treq;
- int code;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX24_ENV)
- afs_Trace3(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, vmap->vm_start, ICL_TYPE_INT32,
- vmap->vm_end - vmap->vm_start);
-#else
- afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, vmap->vm_start, ICL_TYPE_INT32,
- vmap->vm_end - vmap->vm_start, ICL_TYPE_INT32,
- vmap->vm_offset);
-#endif
-
- /* get a validated vcache entry */
- code = afs_InitReq(&treq, credp);
- if (!code)
- code = afs_VerifyVCache(vcp, &treq);
-
-
- if (code)
- code = -code;
- else {
- osi_FlushPages(vcp, credp); /* ensure stale pages are gone */
-
- AFS_GUNLOCK();
- code = generic_file_mmap(fp, vmap);
- AFS_GLOCK();
- }
-
- if (code == 0) {
- ObtainWriteLock(&vcp->lock, 531);
- /* Set out vma ops so we catch the close. The following test should be
- * the same as used in generic_file_mmap.
- */
- if ((vmap->vm_flags & VM_SHARED) && (vmap->vm_flags & VM_MAYWRITE)) {
- if (!afs_shared_mmap_ops_inited) {
- afs_shared_mmap_ops_inited = 1;
- afs_shared_mmap_ops = *vmap->vm_ops;
- afs_shared_mmap_ops.close = afs_linux_vma_close;
- }
- vmap->vm_ops = &afs_shared_mmap_ops;
- } else {
- if (!afs_private_mmap_ops_inited) {
- afs_private_mmap_ops_inited = 1;
- afs_private_mmap_ops = *vmap->vm_ops;
- afs_private_mmap_ops.close = afs_linux_vma_close;
- }
- vmap->vm_ops = &afs_private_mmap_ops;
- }
-
-
- /* Add an open reference on the first mapping. */
- if (vcp->mapcnt == 0) {
- vcp->execsOrWriters++;
- vcp->opens++;
- vcp->states |= CMAPPED;
- }
- ReleaseWriteLock(&vcp->lock);
- vcp->mapcnt++;
- }
-
- AFS_GUNLOCK();
- crfree(credp);
- return code;
-}
-
-int
-afs_linux_open(struct inode *ip, struct file *fp)
-{
- int code;
- cred_t *credp = crref();
-
- AFS_GLOCK();
-#ifdef AFS_LINUX24_ENV
- lock_kernel();
-#endif
- code = afs_open((struct vcache **)&ip, fp->f_flags, credp);
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
-
- crfree(credp);
- return -code;
-}
-
-/* afs_Close is called from release, since release is used to handle all
- * file closings. In addition afs_linux_flush is called from sys_close to
- * handle flushing the data back to the server. The kicker is that we could
- * ignore flush completely if only sys_close took it's return value from
- * fput. See afs_linux_flush for notes on interactions between release and
- * flush.
- */
-static int
-afs_linux_release(struct inode *ip, struct file *fp)
-{
- int code = 0;
- cred_t *credp = crref();
- struct vcache *vcp = ITOAFS(ip);
-
- AFS_GLOCK();
-#ifdef AFS_LINUX24_ENV
- lock_kernel();
-#endif
- if (vcp->flushcnt) {
- vcp->flushcnt--; /* protected by AFS global lock. */
- } else {
- code = afs_close(vcp, fp->f_flags, credp);
- }
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
-
- crfree(credp);
- return -code;
-}
-
-#if defined(AFS_LINUX24_ENV)
-static int
-afs_linux_fsync(struct file *fp, struct dentry *dp, int datasync)
-#else
-static int
-afs_linux_fsync(struct file *fp, struct dentry *dp)
-#endif
-{
- int code;
- struct inode *ip = FILE_INODE(fp);
- cred_t *credp = crref();
-
- AFS_GLOCK();
-#ifdef AFS_LINUX24_ENV
- lock_kernel();
-#endif
- code = afs_fsync(ITOAFS(ip), credp);
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-
-}
-
-
-static int
-afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
-{
- int code = 0;
- struct vcache *vcp = ITOAFS(FILE_INODE(fp));
- cred_t *credp = crref();
-#ifdef AFS_LINUX24_ENV
- struct flock64 flock;
-#else
- struct flock flock;
-#endif
-
- /* Convert to a lock format afs_lockctl understands. */
- memset((char *)&flock, 0, sizeof(flock));
- flock.l_type = flp->fl_type;
- flock.l_pid = flp->fl_pid;
- flock.l_whence = 0;
- flock.l_start = flp->fl_start;
- flock.l_len = flp->fl_end - flp->fl_start;
-
- /* Safe because there are no large files, yet */
-#if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
- if (cmd == F_GETLK64)
- cmd = F_GETLK;
- else if (cmd == F_SETLK64)
- cmd = F_SETLK;
- else if (cmd == F_SETLKW64)
- cmd = F_SETLKW;
-#endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
-
- AFS_GLOCK();
- code = afs_lockctl(vcp, &flock, cmd, credp);
- AFS_GUNLOCK();
-
- /* Convert flock back to Linux's file_lock */
- flp->fl_type = flock.l_type;
- flp->fl_pid = flock.l_pid;
- flp->fl_start = flock.l_start;
- flp->fl_end = flock.l_start + flock.l_len;
-
- crfree(credp);
- return -code;
-
-}
-
-/* afs_linux_flush
- * flush is called from sys_close. We could ignore it, but sys_close return
- * code comes from flush, not release. We need to use release to keep
- * the vcache open count correct. Note that flush is called before release
- * (via fput) in sys_close. vcp->flushcnt is a bit of ugliness to avoid
- * races and also avoid calling afs_close twice when closing the file.
- * If we merely checked for opens > 0 in afs_linux_release, then if an
- * new open occurred when storing back the file, afs_linux_release would
- * incorrectly close the file and decrement the opens count. Calling afs_close
- * on the just flushed file is wasteful, since the background daemon will
- * execute the code that finally decides there is nothing to do.
- */
-int
-afs_linux_flush(struct file *fp)
-{
- struct vcache *vcp = ITOAFS(FILE_INODE(fp));
- int code = 0;
- cred_t *credp;
-
- /* Only do this on the last close of the file pointer. */
-#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&fp->f_count) > 1)
-#else
- if (fp->f_count > 1)
-#endif
- return 0;
-
- credp = crref();
-
- AFS_GLOCK();
- code = afs_close(vcp, fp->f_flags, credp);
- vcp->flushcnt++; /* protected by AFS global lock. */
- AFS_GUNLOCK();
-
- crfree(credp);
- return -code;
-}
-
-#if !defined(AFS_LINUX24_ENV)
-/* Not allowed to directly read a directory. */
-ssize_t
-afs_linux_dir_read(struct file * fp, char *buf, size_t count, loff_t * ppos)
-{
- return -EISDIR;
-}
-#endif
-
-
-
-struct file_operations afs_dir_fops = {
-#if !defined(AFS_LINUX24_ENV)
- .read = afs_linux_dir_read,
- .lock = afs_linux_lock,
- .fsync = afs_linux_fsync,
-#else
- .read = generic_read_dir,
-#endif
- .readdir = afs_linux_readdir,
- .ioctl = afs_xioctl,
- .open = afs_linux_open,
- .release = afs_linux_release,
-};
-
-struct file_operations afs_file_fops = {
- .read = afs_linux_read,
- .write = afs_linux_write,
- .ioctl = afs_xioctl,
- .mmap = afs_linux_mmap,
- .open = afs_linux_open,
- .flush = afs_linux_flush,
- .release = afs_linux_release,
- .fsync = afs_linux_fsync,
- .lock = afs_linux_lock,
-};
-
-
-/**********************************************************************
- * AFS Linux dentry operations
- **********************************************************************/
-
-/* afs_linux_revalidate
- * Ensure vcache is stat'd before use. Return 0 if entry is valid.
- */
-static int
-afs_linux_revalidate(struct dentry *dp)
-{
- int code;
- cred_t *credp;
- struct vrequest treq;
- struct vcache *vcp = ITOAFS(dp->d_inode);
- struct vcache *rootvp = NULL;
-
- AFS_GLOCK();
-
- if (afs_fakestat_enable && vcp->mvstat == 1 && vcp->mvid
- && (vcp->states & CMValid) && (vcp->states & CStatd)) {
- ObtainSharedLock(&afs_xvcache, 680);
- rootvp = afs_FindVCache(vcp->mvid, 0, 0);
- ReleaseSharedLock(&afs_xvcache);
- }
-#ifdef AFS_LINUX24_ENV
- lock_kernel();
-#endif
-
- /* Make this a fast path (no crref), since it's called so often. */
- if (vcp->states & CStatd) {
- if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
- check_bad_parent(dp); /* check and correct mvid */
- if (rootvp)
- vcache2fakeinode(rootvp, vcp);
- else
- vcache2inode(vcp);
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- if (rootvp)
- afs_PutVCache(rootvp);
- AFS_GUNLOCK();
- return 0;
- }
-
- credp = crref();
- code = afs_InitReq(&treq, credp);
- if (!code)
- code = afs_VerifyVCache(vcp, &treq);
-
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
-
- return -code;
-}
-
-#if defined(AFS_LINUX26_ENV)
-static int
-afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
- int err = afs_linux_revalidate(dentry);
- if (!err)
- generic_fillattr(dentry->d_inode, stat);
- return err;
-}
-#endif
-
-/* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
- * In kernels 2.2.10 and above, we are passed an additional flags var which
- * may have either the LOOKUP_FOLLOW OR LOOKUP_DIRECTORY set in which case
- * we are advised to follow the entry if it is a link or to make sure that
- * it is a directory. But since the kernel itself checks these possibilities
- * later on, we shouldn't have to do it until later. Perhaps in the future..
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
-static int
-afs_linux_dentry_revalidate(struct dentry *dp, int flags)
-#else
-static int
-afs_linux_dentry_revalidate(struct dentry *dp)
-#endif
-{
- char *name;
- cred_t *credp = crref();
- struct vrequest treq;
- struct vcache *lookupvcp = NULL;
- int code, bad_dentry = 1;
- struct sysname_info sysState;
- struct vcache *vcp = ITOAFS(dp->d_inode);
- struct vcache *parentvcp = ITOAFS(dp->d_parent->d_inode);
-
- AFS_GLOCK();
- lock_kernel();
-
- sysState.allocked = 0;
-
- /* If it's a negative dentry, then there's nothing to do. */
- if (!vcp || !parentvcp)
- goto done;
-
- /* If it is the AFS root, then there's no chance it needs
- * revalidating */
- if (vcp == afs_globalVp) {
- bad_dentry = 0;
- goto done;
- }
-
- if ((code = afs_InitReq(&treq, credp)))
- goto done;
-
- Check_AtSys(parentvcp, dp->d_name.name, &sysState, &treq);
- name = sysState.name;
-
- /* First try looking up the DNLC */
- if ((lookupvcp = osi_dnlc_lookup(parentvcp, name, WRITE_LOCK))) {
- /* Verify that the dentry does not point to an old inode */
- if (vcp != lookupvcp)
- goto done;
- /* Check and correct mvid */
- if (*name != '/' && vcp->mvstat == 2)
- check_bad_parent(dp);
- vcache2inode(vcp);
- bad_dentry = 0;
- goto done;
- }
-
- /* A DNLC lookup failure cannot be trusted. Try a real lookup.
- Make sure to try the real name and not the @sys expansion;
- afs_lookup will expand @sys itself. */
-
- code = afs_lookup(parentvcp, dp->d_name.name, &lookupvcp, credp);
-
- /* Verify that the dentry does not point to an old inode */
- if (vcp != lookupvcp)
- goto done;
-
- bad_dentry = 0;
-
- done:
- /* Clean up */
- if (lookupvcp)
- afs_PutVCache(lookupvcp);
- if (sysState.allocked)
- osi_FreeLargeSpace(name);
-
- AFS_GUNLOCK();
- crfree(credp);
-
- if (bad_dentry) {
- shrink_dcache_parent(dp);
- d_drop(dp);
- }
- unlock_kernel();
-
- return !bad_dentry;
-}
-
-#if !defined(AFS_LINUX26_ENV)
-/* afs_dentry_iput */
-static void
-afs_dentry_iput(struct dentry *dp, struct inode *ip)
-{
- if (ICL_SETACTIVE(afs_iclSetp)) {
- AFS_GLOCK();
- afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYIPUT, ICL_TYPE_POINTER, ip,
- ICL_TYPE_STRING, dp->d_parent->d_name.name,
- ICL_TYPE_STRING, dp->d_name.name);
- AFS_GUNLOCK();
- }
-
- osi_iput(ip);
-}
-#endif
-
-static int
-afs_dentry_delete(struct dentry *dp)
-{
- if (ICL_SETACTIVE(afs_iclSetp)) {
- AFS_GLOCK();
- afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYDELETE, ICL_TYPE_POINTER,
- dp->d_inode, ICL_TYPE_STRING, dp->d_parent->d_name.name,
- ICL_TYPE_STRING, dp->d_name.name);
- AFS_GUNLOCK();
- }
-
- if (dp->d_inode && (ITOAFS(dp->d_inode)->states & CUnlinked))
- return 1; /* bad inode? */
-
- return 0;
-}
-
-struct dentry_operations afs_dentry_operations = {
- .d_revalidate = afs_linux_dentry_revalidate,
- .d_delete = afs_dentry_delete,
-#if !defined(AFS_LINUX26_ENV)
- .d_iput = afs_dentry_iput,
-#endif
-};
-
-/**********************************************************************
- * AFS Linux inode operations
- **********************************************************************/
-
-/* afs_linux_create
- *
- * Merely need to set enough of vattr to get us through the create. Note
- * that the higher level code (open_namei) will take care of any tuncation
- * explicitly. Exclusive open is also taken care of in open_namei.
- *
- * name is in kernel space at this point.
- */
-int
-afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
-{
- int code;
- cred_t *credp = crref();
- struct vattr vattr;
- enum vcexcl excl;
- const char *name = dp->d_name.name;
- struct inode *ip;
-
- VATTR_NULL(&vattr);
- vattr.va_mode = mode;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- code =
- afs_create(ITOAFS(dip), name, &vattr, NONEXCL, mode,
- (struct vcache **)&ip, credp);
-
- if (!code) {
- vattr2inode(ip, &vattr);
- /* Reset ops if symlink or directory. */
-#if defined(AFS_LINUX24_ENV)
- if (S_ISREG(ip->i_mode)) {
- ip->i_op = &afs_file_iops;
- ip->i_fop = &afs_file_fops;
- ip->i_data.a_ops = &afs_file_aops;
- } else if (S_ISDIR(ip->i_mode)) {
- ip->i_op = &afs_dir_iops;
- ip->i_fop = &afs_dir_fops;
- } else if (S_ISLNK(ip->i_mode)) {
- ip->i_op = &afs_symlink_iops;
- ip->i_data.a_ops = &afs_symlink_aops;
- ip->i_mapping = &ip->i_data;
- } else
- printk("afs_linux_create: FIXME\n");
-#else
- if (S_ISDIR(ip->i_mode))
- ip->i_op = &afs_dir_iops;
- else if (S_ISLNK(ip->i_mode))
- ip->i_op = &afs_symlink_iops;
-#endif
-
- dp->d_op = &afs_dentry_operations;
- dp->d_time = jiffies;
- d_instantiate(dp, ip);
- }
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-/* afs_linux_lookup */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
-struct dentry *
-afs_linux_lookup(struct inode *dip, struct dentry *dp)
-#else
-int
-afs_linux_lookup(struct inode *dip, struct dentry *dp)
-#endif
-{
- int code = 0;
- cred_t *credp = crref();
- struct vcache *vcp = NULL;
- const char *comp = dp->d_name.name;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- code = afs_lookup(ITOAFS(dip), comp, &vcp, credp);
-
- if (vcp) {
- struct inode *ip = AFSTOI(vcp);
- /* Reset ops if symlink or directory. */
-#if defined(AFS_LINUX24_ENV)
- if (S_ISREG(ip->i_mode)) {
- ip->i_op = &afs_file_iops;
- ip->i_fop = &afs_file_fops;
- ip->i_data.a_ops = &afs_file_aops;
- } else if (S_ISDIR(ip->i_mode)) {
- ip->i_op = &afs_dir_iops;
- ip->i_fop = &afs_dir_fops;
- } else if (S_ISLNK(ip->i_mode)) {
- ip->i_op = &afs_symlink_iops;
- ip->i_data.a_ops = &afs_symlink_aops;
- ip->i_mapping = &ip->i_data;
- } else
- printk
- ("afs_linux_lookup: ip->i_mode 0x%x dp->d_name.name %s code %d\n",
- ip->i_mode, dp->d_name.name, code);
-#else
- if (S_ISDIR(ip->i_mode))
- ip->i_op = &afs_dir_iops;
- else if (S_ISLNK(ip->i_mode))
- ip->i_op = &afs_symlink_iops;
-#endif
- }
- dp->d_time = jiffies;
- dp->d_op = &afs_dentry_operations;
- d_add(dp, AFSTOI(vcp));
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
-
- /* It's ok for the file to not be found. That's noted by the caller by
- * seeing that the dp->d_inode field is NULL.
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
- if (code == ENOENT)
- return ERR_PTR(0);
- else
- return ERR_PTR(-code);
-#else
- if (code == ENOENT)
- code = 0;
- return -code;
-#endif
-}
-
-int
-afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
-{
- int code;
- cred_t *credp = crref();
- const char *name = newdp->d_name.name;
- struct inode *oldip = olddp->d_inode;
-
- /* If afs_link returned the vnode, we could instantiate the
- * dentry. Since it's not, we drop this one and do a new lookup.
- */
- d_drop(newdp);
-
- AFS_GLOCK();
- code = afs_link(ITOAFS(oldip), ITOAFS(dip), name, credp);
-
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-int
-afs_linux_unlink(struct inode *dip, struct dentry *dp)
-{
- int code;
- cred_t *credp = crref();
- const char *name = dp->d_name.name;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- code = afs_remove(ITOAFS(dip), name, credp);
- if (!code)
- d_drop(dp);
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-
-int
-afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
-{
- int code;
- cred_t *credp = crref();
- struct vattr vattr;
- const char *name = dp->d_name.name;
-
- /* If afs_symlink returned the vnode, we could instantiate the
- * dentry. Since it's not, we drop this one and do a new lookup.
- */
- d_drop(dp);
-
- AFS_GLOCK();
- VATTR_NULL(&vattr);
- code = afs_symlink(ITOAFS(dip), name, &vattr, target, credp);
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-int
-afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
-{
- int code;
- cred_t *credp = crref();
- struct vcache *tvcp = NULL;
- struct vattr vattr;
- const char *name = dp->d_name.name;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- VATTR_NULL(&vattr);
- vattr.va_mask = ATTR_MODE;
- vattr.va_mode = mode;
- code = afs_mkdir(ITOAFS(dip), name, &vattr, &tvcp, credp);
-
- if (tvcp) {
- tvcp->v.v_op = &afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
- tvcp->v.v_fop = &afs_dir_fops;
-#endif
- dp->d_op = &afs_dentry_operations;
- dp->d_time = jiffies;
- d_instantiate(dp, AFSTOI(tvcp));
- }
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-int
-afs_linux_rmdir(struct inode *dip, struct dentry *dp)
-{
- int code;
- cred_t *credp = crref();
- const char *name = dp->d_name.name;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- code = afs_rmdir(ITOAFS(dip), name, credp);
-
- /* Linux likes to see ENOTEMPTY returned from an rmdir() syscall
- * that failed because a directory is not empty. So, we map
- * EEXIST to ENOTEMPTY on linux.
- */
- if (code == EEXIST) {
- code = ENOTEMPTY;
- }
-
- if (!code) {
- d_drop(dp);
- }
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-
-
-int
-afs_linux_rename(struct inode *oldip, struct dentry *olddp,
- struct inode *newip, struct dentry *newdp)
-{
- int code;
- cred_t *credp = crref();
- const char *oldname = olddp->d_name.name;
- const char *newname = newdp->d_name.name;
-
- AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
- lock_kernel();
-#endif
- /* Remove old and new entries from name hash. New one will change below.
- * While it's optimal to catch failures and re-insert newdp into hash,
- * it's also error prone and in that case we're already dealing with error
- * cases. Let another lookup put things right, if need be.
- */
-#if defined(AFS_LINUX26_ENV)
- if (!d_unhashed(olddp))
- d_drop(olddp);
- if (!d_unhashed(newdp))
- d_drop(newdp);
-#else
- if (!list_empty(&olddp->d_hash))
- d_drop(olddp);
- if (!list_empty(&newdp->d_hash))
- d_drop(newdp);
-#endif
- code = afs_rename(ITOAFS(oldip), oldname, ITOAFS(newip), newname, credp);
-
- if (!code) {
- /* update time so it doesn't expire immediately */
- newdp->d_time = jiffies;
- d_move(olddp, newdp);
- }
-
-#if defined(AFS_LINUX26_ENV)
- unlock_kernel();
-#endif
- AFS_GUNLOCK();
-
- crfree(credp);
- return -code;
-}
-
-
-/* afs_linux_ireadlink
- * Internal readlink which can return link contents to user or kernel space.
- * Note that the buffer is NOT supposed to be null-terminated.
- */
-static int
-afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
-{
- int code;
- cred_t *credp = crref();
- uio_t tuio;
- struct iovec iov;
-
- setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
- code = afs_readlink(ITOAFS(ip), &tuio, credp);
- crfree(credp);
-
- if (!code)
- return maxlen - tuio.uio_resid;
- else
- return -code;
-}
-
-#if !defined(AFS_LINUX24_ENV)
-/* afs_linux_readlink
- * Fill target (which is in user space) with contents of symlink.
- */
-int
-afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
-{
- int code;
- struct inode *ip = dp->d_inode;
-
- AFS_GLOCK();
- code = afs_linux_ireadlink(ip, target, maxlen, AFS_UIOUSER);
- AFS_GUNLOCK();
- return code;
-}
-
-
-/* afs_linux_follow_link
- * a file system dependent link following routine.
- */
-struct dentry *
-afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
- unsigned int follow)
-{
- int code = 0;
- char *name;
- struct dentry *res;
-
-
- AFS_GLOCK();
- name = osi_Alloc(PATH_MAX + 1);
- if (!name) {
- AFS_GUNLOCK();
- dput(basep);
- return ERR_PTR(-EIO);
- }
-
- code = afs_linux_ireadlink(dp->d_inode, name, PATH_MAX, AFS_UIOSYS);
- AFS_GUNLOCK();
-
- if (code < 0) {
- dput(basep);
- res = ERR_PTR(code);
- } else {
- name[code] = '\0';
- res = lookup_dentry(name, basep, follow);
- }
-
- AFS_GLOCK();
- osi_Free(name, PATH_MAX + 1);
- AFS_GUNLOCK();
- return res;
-}
-#endif
-
-/* afs_linux_readpage
- * all reads come through here. A strategy-like read call.
- */
-int
-afs_linux_readpage(struct file *fp, struct page *pp)
-{
- int code;
- cred_t *credp = crref();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- char *address;
- afs_offs_t offset = pp->index << PAGE_CACHE_SHIFT;
-#else
- ulong address = afs_linux_page_address(pp);
- afs_offs_t offset = pageoff(pp);
-#endif
- uio_t tuio;
- struct iovec iovec;
- struct inode *ip = FILE_INODE(fp);
- int cnt = atomic_read(&pp->count);
- struct vcache *avc = ITOAFS(ip);
-
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip, ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32, 99999); /* not a possible code value */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- address = kmap(pp);
- ClearPageError(pp);
-
- lock_kernel();
-#else
- atomic_add(1, &pp->count);
- set_bit(PG_locked, &pp->flags); /* other bits? See mm.h */
- clear_bit(PG_error, &pp->flags);
-#endif
-
- setup_uio(&tuio, &iovec, (char *)address, offset, PAGESIZE, UIO_READ,
- AFS_UIOSYS);
- code = afs_rdwr(avc, &tuio, UIO_READ, 0, credp);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- unlock_kernel();
-#endif
-
- if (!code) {
- if (tuio.uio_resid) /* zero remainder of page */
- memset((void *)(address + (PAGESIZE - tuio.uio_resid)), 0,
- tuio.uio_resid);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- flush_dcache_page(pp);
- SetPageUptodate(pp);
-#else
- set_bit(PG_uptodate, &pp->flags);
-#endif
- }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- kunmap(pp);
- UnlockPage(pp);
-#else
- clear_bit(PG_locked, &pp->flags);
- wake_up(&pp->wait);
- free_page(address);
-#endif
-
- if (!code && AFS_CHUNKOFFSET(offset) == 0) {
- struct dcache *tdc;
- struct vrequest treq;
-
- code = afs_InitReq(&treq, credp);
- if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
- tdc = afs_FindDCache(avc, offset);
- if (tdc) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, credp, &treq);
- afs_PutDCache(tdc);
- }
- ReleaseWriteLock(&avc->lock);
- }
- }
-
- crfree(credp);
- afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
- code);
- AFS_GUNLOCK();
- return -code;
-}
-
-#if defined(AFS_LINUX24_ENV)
-int
-afs_linux_writepage(struct page *pp)
-{
- struct address_space *mapping = pp->mapping;
- struct inode *inode;
- unsigned long end_index;
- unsigned offset = PAGE_CACHE_SIZE;
- long status;
-
- inode = (struct inode *)mapping->host;
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-
- /* easy case */
- if (pp->index < end_index)
- goto do_it;
- /* things got complicated... */
- offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
- /* OK, are we completely out? */
- if (pp->index >= end_index + 1 || !offset)
- return -EIO;
- do_it:
- AFS_GLOCK();
- status = afs_linux_writepage_sync(inode, pp, 0, offset);
- AFS_GUNLOCK();
- SetPageUptodate(pp);
- UnlockPage(pp);
- if (status == offset)
- return 0;
- else
- return status;
-}
-#endif
-
-/* afs_linux_permission
- * Check access rights - returns error if can't check or permission denied.
- */
-int
-afs_linux_permission(struct inode *ip, int mode)
-{
- int code;
- cred_t *credp = crref();
- int tmp = 0;
-
- AFS_GLOCK();
- if (mode & MAY_EXEC)
- tmp |= VEXEC;
- if (mode & MAY_READ)
- tmp |= VREAD;
- if (mode & MAY_WRITE)
- tmp |= VWRITE;
- code = afs_access(ITOAFS(ip), tmp, credp);
-
- AFS_GUNLOCK();
- crfree(credp);
- return -code;
-}
-
-
-#if defined(AFS_LINUX24_ENV)
-int
-afs_linux_writepage_sync(struct inode *ip, struct page *pp,
- unsigned long offset, unsigned int count)
-{
- struct vcache *vcp = ITOAFS(ip);
- char *buffer;
- afs_offs_t base;
- int code = 0;
- cred_t *credp;
- uio_t tuio;
- struct iovec iovec;
- int f_flags = 0;
-
- buffer = kmap(pp) + offset;
- base = (pp->index << PAGE_CACHE_SHIFT) + offset;
-
- credp = crref();
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, atomic_read(&pp->count),
- ICL_TYPE_INT32, 99999);
-
- setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
-
- code = afs_write(vcp, &tuio, f_flags, credp, 0);
-
- vcache2inode(vcp);
-
- if (!code
- && afs_stats_cmperf.cacheCurrDirtyChunks >
- afs_stats_cmperf.cacheMaxDirtyChunks) {
- struct vrequest treq;
-
- ObtainWriteLock(&vcp->lock, 533);
- if (!afs_InitReq(&treq, credp))
- code = afs_DoPartialWrite(vcp, &treq);
- ReleaseWriteLock(&vcp->lock);
- }
- code = code ? -code : count - tuio.uio_resid;
-
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, atomic_read(&pp->count),
- ICL_TYPE_INT32, code);
-
- crfree(credp);
- kunmap(pp);
-
- return code;
-}
-
-static int
-afs_linux_updatepage(struct file *file, struct page *page,
- unsigned long offset, unsigned int count)
-{
- struct dentry *dentry = file->f_dentry;
-
- return afs_linux_writepage_sync(dentry->d_inode, page, offset, count);
-}
-#else
-/* afs_linux_updatepage
- * What one would have thought was writepage - write dirty page to file.
- * Called from generic_file_write. buffer is still in user space. pagep
- * has been filled in with old data if we're updating less than a page.
- */
-int
-afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
- unsigned int count, int sync)
-{
- struct vcache *vcp = ITOAFS(FILE_INODE(fp));
- u8 *page_addr = (u8 *) afs_linux_page_address(pp);
- int code = 0;
- cred_t *credp;
- uio_t tuio;
- struct iovec iovec;
-
- set_bit(PG_locked, &pp->flags);
-
- credp = crref();
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, atomic_read(&pp->count),
- ICL_TYPE_INT32, 99999);
- setup_uio(&tuio, &iovec, page_addr + offset,
- (afs_offs_t) (pageoff(pp) + offset), count, UIO_WRITE,
- AFS_UIOSYS);
-
- code = afs_write(vcp, &tuio, fp->f_flags, credp, 0);
-
- vcache2inode(vcp);
-
- code = code ? -code : count - tuio.uio_resid;
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, atomic_read(&pp->count),
- ICL_TYPE_INT32, code);
-
- AFS_GUNLOCK();
- crfree(credp);
-
- clear_bit(PG_locked, &pp->flags);
- return code;
-}
-#endif
-
-#if defined(AFS_LINUX24_ENV)
-static int
-afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
- unsigned to)
-{
- int code;
-
- AFS_GLOCK();
- lock_kernel();
- code = afs_linux_updatepage(file, page, offset, to - offset);
- unlock_kernel();
- AFS_GUNLOCK();
- kunmap(page);
-
- return code;
-}
-
-static int
-afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
- unsigned to)
-{
- kmap(page);
- return 0;
-}
-
-extern int afs_notify_change(struct dentry *dp, struct iattr *iattrp);
-#endif
-
-struct inode_operations afs_file_iops = {
-#if defined(AFS_LINUX26_ENV)
- .permission = afs_linux_permission,
- .getattr = afs_linux_getattr,
- .setattr = afs_notify_change,
-#elif defined(AFS_LINUX24_ENV)
- .permission = afs_linux_permission,
- .revalidate = afs_linux_revalidate,
- .setattr = afs_notify_change,
-#else
- .default_file_ops = &afs_file_fops,
- .readpage = afs_linux_readpage,
- .revalidate = afs_linux_revalidate,
- .updatepage = afs_linux_updatepage,
-#endif
-};
-
-#if defined(AFS_LINUX24_ENV)
-struct address_space_operations afs_file_aops = {
- .readpage = afs_linux_readpage,
- .writepage = afs_linux_writepage,
- .commit_write = afs_linux_commit_write,
- .prepare_write = afs_linux_prepare_write,
-};
-#endif
-
-
-/* Separate ops vector for directories. Linux 2.2 tests type of inode
- * by what sort of operation is allowed.....
- */
-
-struct inode_operations afs_dir_iops = {
-#if !defined(AFS_LINUX24_ENV)
- .default_file_ops = &afs_dir_fops,
-#else
- .setattr = afs_notify_change,
-#endif
- .create = afs_linux_create,
- .lookup = afs_linux_lookup,
- .link = afs_linux_link,
- .unlink = afs_linux_unlink,
- .symlink = afs_linux_symlink,
- .mkdir = afs_linux_mkdir,
- .rmdir = afs_linux_rmdir,
- .rename = afs_linux_rename,
-#if defined(AFS_LINUX26_ENV)
- .getattr = afs_linux_getattr,
-#else
- .revalidate = afs_linux_revalidate,
-#endif
- .permission = afs_linux_permission,
-};
-
-/* We really need a separate symlink set of ops, since do_follow_link()
- * determines if it _is_ a link by checking if the follow_link op is set.
- */
-#if defined(AFS_LINUX24_ENV)
-static int
-afs_symlink_filler(struct file *file, struct page *page)
-{
- struct inode *ip = (struct inode *)page->mapping->host;
- char *p = (char *)kmap(page);
- int code;
-
- AFS_GLOCK();
- lock_kernel();
- code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
-
- if (code < 0)
- goto fail;
- p[code] = '\0'; /* null terminate? */
- unlock_kernel();
- AFS_GUNLOCK();
-
- SetPageUptodate(page);
- kunmap(page);
- UnlockPage(page);
- return 0;
-
- fail:
- unlock_kernel();
- AFS_GUNLOCK();
-
- SetPageError(page);
- kunmap(page);
- UnlockPage(page);
- return code;
-}
-
-struct address_space_operations afs_symlink_aops = {
- .readpage = afs_symlink_filler
-};
-#endif
-
-struct inode_operations afs_symlink_iops = {
-#if defined(AFS_LINUX24_ENV)
- .readlink = page_readlink,
- .follow_link = page_follow_link,
- .setattr = afs_notify_change,
-#else
- .readlink = afs_linux_readlink,
- .follow_link = afs_linux_follow_link,
- .permission = afs_linux_permission,
- .revalidate = afs_linux_revalidate,
-#endif
-};
+++ /dev/null
-# $Id: Makefile.am,v 1.1 2001/06/05 20:17:49 shadow Exp $
-
-include $(top_srcdir)/Makefile.am.common
-
-SUBDIRS= "foo"
+++ /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
-#
-# Portions Copyright (c) 2003 Apple Computer, Inc.
-
-srcdir=@srcdir@
-include @TOP_OBJDIR@/src/config/Makefile.config
-
-all: depinstall
-
-depinstall: ${TOP_INCDIR}/afs/afs.h ${TOP_INCDIR}/afs/osi_inode.h ${TOP_INCDIR}/afs/afs_stats.h \
- ${TOP_INCDIR}/afs/exporter.h ${TOP_INCDIR}/afs/nfsclient.h afszcm.cat AFS_component_version_number.c ${TOP_INCDIR}/afs/unified_afs.h ${TOP_INCDIR}/afs/sysctl.h
- case ${SYS_NAME} in \
- pmax_ul43 | pmax_ul43a) \
- ${INSTALL} longc_procs.h ${TOP_INCDIR}/afs ;; \
- esac
-
-afs_trace.h afs_trace.msf: afs_trace.et
- ${COMPILE_ET} -v 2 -p ${srcdir} afs_trace.et
-
-unified_afs.c unified_afs.h: unified_afs.et
- $(RM) -f unified_afs.c unified_afs.h
- ${COMPILE_ET} -p ${srcdir} unified_afs -h unified_afs
-
-afszcm.cat: afs_trace.msf
- -$(RM) -f afszcm.cat
- case ${SYS_NAME} in \
- sgi_* ) \
- gencat -m afszcm.cat afs_trace.msf ;; \
- sun*_4* ) \
- /usr/etc/gencat afszcm.cat afs_trace.msf ;; \
- *_linux* | *_umlinux* ) \
- gencat --new afszcm.cat afs_trace.msf ;; \
- *_darwin_* | i386_fbsd*) \
- echo No gencat for ${SYS_NAME} ;; \
- * ) \
- gencat afszcm.cat afs_trace.msf ;; \
- esac
-
-install: ${DESTDIR}${includedir}/afs/afs.h ${DESTDIR}${includedir}/afs/osi_inode.h ${DESTDIR}${includedir}/afs/afs_stats.h ${DESTDIR}${includedir}/afs/exporter.h ${DESTDIR}${includedir}/afs/nfsclient.h ${DESTDIR}${includedir}/afs/unified_afs.h ${DESTDIR}${includedir}/afs/sysctl.h
- case ${SYS_NAME} in \
- pmax_ul43 | pmax_ul43a) \
- ${INSTALL} longc_procs.h ${DESTDIR}${includedir}/afs ;; \
- esac
- case ${SYS_NAME} in \
- *linux* ) \
- ${INSTALL} ${MKAFS_OSTYPE}/osi_vfs.h ${DESTDIR}${includedir}/afs || true ;;\
- * ) \
- echo No vfs headers to install for ${SYS_NAME};; \
- esac
-
-clean:
- -$(RM) -f *.o core AFS_component_version_number.c afs_trace.h afs_trace.msf afszcm.cat
-
-include ../config/Makefile.version
-${DEST}/include/afs/afs.h: afs.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/afs.h: afs.h
- ${INSTALL} $? $@
-
-${TOP_INCDIR}/afs/afs.h: afs.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/unified_afs.h: unified_afs.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/unified_afs.h: unified_afs.h
- ${INSTALL} $? $@
-
-${TOP_INCDIR}/afs/unified_afs.h: unified_afs.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/osi_inode.h: ${MKAFS_OSTYPE}/osi_inode.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/osi_inode.h: ${MKAFS_OSTYPE}/osi_inode.h
- ${INSTALL} $? $@
-
-${TOP_INCDIR}/afs/osi_inode.h: ${MKAFS_OSTYPE}/osi_inode.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/afs_stats.h: afs_stats.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/afs_stats.h: afs_stats.h
- ${INSTALL} $? $@
-
-${TOP_INCDIR}/afs/afs_stats.h: afs_stats.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/sysctl.h: sysctl.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/sysctl.h: sysctl.h
- ${INSTALL} $? $@
-
-${TOP_INCDIR}/afs/sysctl.h: sysctl.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/exporter.h: exporter.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/exporter.h: exporter.h
- ${INSTALL} $? $@
-
-
-${TOP_INCDIR}/afs/exporter.h: exporter.h
- ${INSTALL} $? $@
-
-
-${DEST}/include/afs/nfsclient.h: nfsclient.h
- ${INSTALL} $? $@
-
-${DESTDIR}${includedir}/afs/nfsclient.h: nfsclient.h
- ${INSTALL} $? $@
-
-
-${TOP_INCDIR}/afs/nfsclient.h: nfsclient.h
- ${INSTALL} $? $@
-
-
-dest: ${DEST}/include/afs/afs.h ${DEST}/include/afs/osi_inode.h ${DEST}/include/afs/afs_stats.h ${DEST}/include/afs/exporter.h ${DEST}/include/afs/nfsclient.h ${DEST}/include/afs/unified_afs.h ${DEST}/include/afs/sysctl.h
- case ${SYS_NAME} in \
- pmax_ul43 | pmax_ul43a) \
- ${INSTALL} longc_procs.h ${DEST}/include/afs ;; \
- esac
- case ${SYS_NAME} in \
- next_mach30 | vax_ul43 | *_darwin* | i386_fbsd* ) \
- echo skipping afszcm.cat install for ${SYS_NAME} ;; \
- * ) \
- ${INSTALL} afszcm.cat ${DEST}/root.client/usr/vice/etc/C ;; \
- esac
- case ${SYS_NAME} in \
- *linux* ) \
- ${INSTALL} ${MKAFS_OSTYPE}/osi_vfs.h ${DEST}/include/afs || true;;\
- * ) \
- echo No vfs headers to install for ${SYS_NAME};; \
- esac
-
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_file.c,v 1.12 2003/07/15 23:14:26 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/osi_inode.h"
-
-
-int afs_osicred_initialized = 0;
-struct AFS_UCRED afs_osi_cred;
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-extern struct vfs *afs_cacheVfsp;
-
-
-#ifdef AFS_HAVE_VXFS
-
-/* Support for UFS and VXFS caches. The assumption here is that the size of
- * a cache file also does not exceed 32 bits.
- */
-
-/* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
-int afs_CacheFSType = -1;
-
-/* pointer to VXFS routine to access vnodes by inode number */
-int (*vxfs_vx_vp_byino) ();
-
-/* Initialize the cache operations. Called while initializing cache files. */
-void
-afs_InitDualFSCacheOps(struct vnode *vp)
-{
- int code;
- static int inited = 0;
- struct vfs *vfsp;
-#ifdef AFS_SUN56_ENV
- struct statvfs64 vfst;
-#else /* AFS_SUN56_ENV */
- struct statvfs vfst;
-#endif /* AFS_SUN56_ENV */
-
- if (inited)
- return;
- inited = 1;
-
- if (vp == NULL)
- return;
-
- vfsp = vp->v_vfsp;
- if (vfsp == NULL)
- osi_Panic("afs_InitDualFSCacheOps: vp->v_vfsp is NULL");
- code = VFS_STATVFS(vfsp, &vfst);
- if (code)
- osi_Panic("afs_InitDualFSCacheOps: statvfs failed");
-
- if (strcmp(vfst.f_basetype, "vxfs") == 0) {
- vxfs_vx_vp_byino = (int (*)())modlookup("vxfs", "vx_vp_byino");
- if (vxfs_vx_vp_byino == NULL)
- osi_Panic
- ("afs_InitDualFSCacheOps: modlookup(vx_vp_byino) failed");
-
- afs_CacheFSType = AFS_SUN_VXFS_CACHE;
- return;
- }
-
- afs_CacheFSType = AFS_SUN_UFS_CACHE;
- return;
-}
-
-ino_t
-VnodeToIno(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
- code = VOP_GETATTR(vp, &vattr, 0, &afs_osi_cred);
- if (code) {
- osi_Panic("VnodeToIno");
- }
- return vattr.va_nodeid;
-}
-
-dev_t
-VnodeToDev(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- vattr.va_mask = AT_FSID | AT_NODEID; /* quick return using this mask. */
- AFS_GUNLOCK();
- code = VOP_GETATTR(vp, &vattr, 0, &afs_osi_cred);
- AFS_GLOCK();
- if (code) {
- osi_Panic("VnodeToDev");
- }
- return (dev_t) vattr.va_fsid;
-}
-
-afs_int32
-VnodeToSize(vnode_t * vp)
-{
- int code;
- struct vattr vattr;
-
- /*
- * We lock xosi in osi_Stat, so we probably should
- * lock it here too - RWH.
- */
- MObtainWriteLock(&afs_xosi, 578);
- vattr.va_mask = AT_SIZE;
- AFS_GUNLOCK();
- code = VOP_GETATTR(vp, &vattr, 0, &afs_osi_cred);
- AFS_GLOCK();
- if (code) {
- osi_Panic("VnodeToSize");
- }
- MReleaseWriteLock(&afs_xosi);
- return (afs_int32) (vattr.va_size);
-}
-
-void *
-osi_VxfsOpen(afs_int32 ainode)
-{
- struct vnode *vp;
- register struct osi_file *afile = NULL;
- afs_int32 code = 0;
- int dummy;
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- code = (*vxfs_vx_vp_byino) (afs_cacheVfsp, &vp, (unsigned int)ainode);
- AFS_GLOCK();
- if (code) {
- osi_FreeSmallSpace(afile);
- osi_Panic("VxfsOpen: vx_vp_byino failed");
- }
- afile->vnode = vp;
- afile->size = VnodeToSize(afile->vnode);
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- return (void *)afile;
-}
-#endif /* AFS_HAVE_VXFS */
-
-#if defined(AFS_SUN57_64BIT_ENV)
-void *
-osi_UfsOpen(ino_t ainode)
-#else
-void *
-osi_UfsOpen(afs_int32 ainode)
-#endif
-{
- struct inode *ip;
- register struct osi_file *afile = NULL;
- afs_int32 code = 0;
- int dummy;
- afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
- AFS_GUNLOCK();
- code =
- igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t) ainode, &ip,
- CRED(), &dummy);
- AFS_GLOCK();
- if (code) {
- osi_FreeSmallSpace(afile);
- osi_Panic("UfsOpen: igetinode failed");
- }
- afile->vnode = ITOV(ip);
- afile->size = VTOI(afile->vnode)->i_size;
- afile->offset = 0;
- afile->proc = (int (*)())0;
- afile->inum = ainode; /* for hint validity checking */
- return (void *)afile;
-}
-
-/**
- * In Solaris 7 we use 64 bit inode numbers
- */
-#if defined(AFS_SUN57_64BIT_ENV)
-void *
-osi_UFSOpen(ino_t ainode)
-#else
-void *
-osi_UFSOpen(afs_int32 ainode)
-#endif
-{
- extern int cacheDiskType;
- AFS_STATCNT(osi_UFSOpen);
- if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
- osi_Panic("UFSOpen called for non-UFS cache\n");
- }
- if (!afs_osicred_initialized) {
- /* valid for alpha_osf, SunOS, Ultrix */
- memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
-#ifdef AFS_HAVE_VXFS
- if (afs_CacheFSType == AFS_SUN_VXFS_CACHE)
- return osi_VxfsOpen(ainode);
-#endif
- return osi_UfsOpen(ainode);
-}
-
-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);
- MObtainWriteLock(&afs_xosi, 320);
- /* Ufs doesn't seem to care about the flags so we pass 0 for now */
- tvattr.va_mask = AT_ALL;
- AFS_GUNLOCK();
- code = VOP_GETATTR(afile->vnode, &tvattr, 0, &afs_osi_cred);
- AFS_GLOCK();
- if (code == 0) {
- astat->size = tvattr.va_size;
- astat->blksize = tvattr.va_blksize;
- astat->mtime = tvattr.va_mtime.tv_sec;
- astat->atime = tvattr.va_atime.tv_sec;
- }
- MReleaseWriteLock(&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)
-{
- struct AFS_UCRED *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;
- MObtainWriteLock(&afs_xosi, 321);
- tvattr.va_mask = AT_SIZE;
- tvattr.va_size = asize;
- /*
- * The only time a flag is used (ATTR_UTIME) is when we're changing the time
- */
- AFS_GUNLOCK();
- code = VOP_SETATTR(afile->vnode, &tvattr, 0, &afs_osi_cred);
- AFS_GLOCK();
- MReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-void
-osi_DisableAtimes(struct vnode *avp)
-{
- if (afs_CacheFSType == AFS_SUN_UFS_CACHE) {
- struct inode *ip = VTOI(avp);
- rw_enter(&ip->i_contents, RW_READER);
- mutex_enter(&ip->i_tlock);
- ip->i_flag &= ~IACC;
- mutex_exit(&ip->i_tlock);
- rw_exit(&ip->i_contents);
- }
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct AFS_UCRED *oldCred;
-#if defined(AFS_SUN57_ENV)
- ssize_t resid;
-#else
- int resid;
-#endif
- 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, 0, 0, &afs_osi_cred, &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)
-{
- struct AFS_UCRED *oldCred;
-#if defined(AFS_SUN57_ENV)
- ssize_t resid;
-#else
- int resid;
-#endif
- 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;
- AFS_GUNLOCK();
- code =
- gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
- afile->offset, AFS_UIOSYS, 0, RLIM64_INFINITY, &afs_osi_cred,
- &resid);
- AFS_GLOCK();
- 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)
-{
- extern int afs_cold_shutdown;
-
- 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
- */
-
-/*
- * Implements:
- * setgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_groups.c,v 1.7 2003/07/15 23:14:26 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-
-static int
- afs_getgroups(struct cred *cred, gid_t * gidset);
-
-static int
- afs_setgroups(struct cred **cred, int ngroups, gid_t * gidset,
- int change_parent);
-
-
-#if defined(AFS_SUN55_ENV)
-int
-afs_xsetgroups(uap, rvp)
- u_int uap; /* this is gidsetsize */
- gid_t *rvp; /* this is gidset */
-#else
-struct setgroupsa {
- u_int gidsetsize;
- gid_t *gidset;
-};
-
-afs_xsetgroups(uap, rvp)
- struct setgroupsa *uap;
- rval_t *rvp;
-#endif
-{
- int code = 0;
- struct vrequest treq;
- struct proc *proc = ttoproc(curthread);
-
- AFS_STATCNT(afs_xsetgroups);
- AFS_GLOCK();
- code = afs_InitReq(&treq, proc->p_cred);
- AFS_GUNLOCK();
- if (code)
- return code;
- code = setgroups(uap, rvp);
-
- /* Note that if there is a pag already in the new groups we don't
- * overwrite it with the old pag.
- */
- if (PagInCred(proc->p_cred) == NOPAG) {
- if (((treq.uid >> 24) & 0xff) == 'A') {
- AFS_GLOCK();
- /* we've already done a setpag, so now we redo it */
- AddPag(treq.uid, &proc->p_cred);
- AFS_GUNLOCK();
- }
- }
- return code;
-}
-
-int
-setpag(cred, pagvalue, newpag, change_parent)
- struct cred **cred;
- afs_uint32 pagvalue;
- afs_uint32 *newpag;
- afs_uint32 change_parent;
-{
- gid_t *gidset;
- int ngroups, code;
- int j;
-
- AFS_STATCNT(setpag);
-
- gidset = (gid_t *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-
- mutex_enter(&curproc->p_crlock);
- ngroups = afs_getgroups(*cred, gidset);
-
- if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
- /* We will have to shift grouplist to make room for pag */
- if ((sizeof gidset[0]) * (ngroups + 2) > AFS_SMALLOCSIZ) {
- osi_FreeSmallSpace((char *)gidset);
- 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]);
- /* afs_setgroups will release curproc->p_crlock */
- if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
- osi_FreeSmallSpace((char *)gidset);
- return (code);
- }
- osi_FreeSmallSpace((char *)gidset);
- return code;
-}
-
-
-static int
-afs_getgroups(struct cred *cred, gid_t * gidset)
-{
- int ngrps, savengrps;
- gid_t *gp;
-
- AFS_STATCNT(afs_getgroups);
-
- gidset[0] = gidset[1] = 0;
- savengrps = ngrps = cred->cr_ngroups;
- gp = cred->cr_groups;
- while (ngrps--)
- *gidset++ = *gp++;
- return savengrps;
-}
-
-
-
-static int
-afs_setgroups(struct cred **cred, int ngroups, gid_t * gidset,
- int change_parent)
-{
- int ngrps;
- int i;
- gid_t *gp;
-
- AFS_STATCNT(afs_setgroups);
-
- if (ngroups > ngroups_max) {
- mutex_exit(&curproc->p_crlock);
- return EINVAL;
- }
- if (!change_parent)
- *cred = (struct cred *)crcopy(*cred);
- (*cred)->cr_ngroups = ngroups;
- gp = (*cred)->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- mutex_exit(&curproc->p_crlock);
- if (!change_parent)
- crset(curproc, *cred); /* broadcast to all threads */
- 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
- */
-
-/*
- * SOLARIS inode operations
- *
- * Implements:
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_inode.c,v 1.14 2003/07/15 23:14:26 shadow Exp $");
-
-#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 */
-
-extern int (*ufs_iallocp) (), (*ufs_iupdatp) (), (*ufs_igetp) (),
- (*ufs_itimes_nolockp) ();
-
-#define AFS_ITIMES(ip) { \
- mutex_enter(&(ip)->i_tlock); \
- (*ufs_itimes_nolockp)(ip); \
- mutex_exit(&(ip)->i_tlock); \
-}
-
-#define AFS_ITIMES_NOLOCK(ip) \
- (*ufs_itimes_nolockp)(ip);
-
-getinode(vfsp, dev, inode, ipp, credp, perror)
- struct vfs *vfsp;
- struct AFS_UCRED *credp;
- struct inode **ipp;
- dev_t dev;
- ino_t inode;
- int *perror;
-{
- struct inode *ip;
- register afs_int32 code;
- struct vnode *vp;
- struct fs *fs;
- struct inode *pip;
- struct ufsvfs *ufsvfsp;
-
- AFS_STATCNT(getinode);
-
- *perror = 0;
-
- if (!vfsp
-#if !defined(AFS_SUN58_ENV)
- && !(vfsp = vfs_devsearch(dev))
-#else
- && !(vfsp = vfs_dev2vfsp(dev))
-#endif
- ) {
- return (ENODEV);
- }
- ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
-
-#ifdef HAVE_VFS_DQRWLOCK
- rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
-#endif
- code = (*ufs_igetp) (vfsp, inode, &ip, credp);
-#ifdef HAVE_VFS_DQRWLOCK
- rw_exit(&ufsvfsp->vfs_dqrwlock);
-#endif
-
- if (code) {
- *perror = BAD_IGET;
- return code;
- }
- *ipp = ip;
- return code;
-}
-
-/* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
-igetinode(vfsp, dev, inode, ipp, credp, perror)
- struct AFS_UCRED *credp;
- struct inode **ipp;
- struct vfs *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);
-
- code = getinode(vfsp, dev, inode, &ip, credp, perror);
- if (code)
- return code;
-
- rw_enter(&ip->i_contents, RW_READER);
-
- if (ip->i_mode == 0) {
- /* Not an allocated inode */
- rw_exit(&ip->i_contents);
- VN_RELE(ITOV(ip));
- return (ENOENT);
- }
-
- if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
- AFS_ITIMES(ip);
- rw_exit(&ip->i_contents);
- VN_RELE(ITOV(ip));
- return (ENOENT);
- }
-
- /* On VFS40 systems, iput does major synchronous write action, but only
- * when the reference count on the vnode goes to 0. Normally, Sun users
- * don't notice this because the DNLC keep references for them, but we
- * notice 'cause we don't. So, we make a fake dnlc entry which gets
- * cleaned up by iget when it needs the space. */
- if (dev != cacheDev.dev) {
- /*
- * Don't call dnlc for the cm inodes since it's a big performance
- * penalty there!
- */
- dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *)0);
- }
-
- *ipp = ip;
- rw_exit(&ip->i_contents);
- return (code);
-}
-
-int CrSync = 1;
-
-afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp,
- credp)
- rval_t *rvp;
- struct AFS_UCRED *credp;
- long near_inode, param1, param2, param3, param4;
- dev_t dev;
-{
- int dummy, err = 0;
- struct inode *ip, *newip;
- register int code;
- dev_t newdev;
- struct ufsvfs *ufsvfsp;
-
- AFS_STATCNT(afs_syscall_icreate);
-
- if (!afs_suser(credp))
- return (EPERM);
-
- /** Code to convert a 32 bit dev_t into a 64 bit dev_t
- * This conversion is needed only for the 64 bit OS.
- */
-
-#ifdef AFS_SUN57_64BIT_ENV
- newdev = expldev((dev32_t) dev);
-#else
- newdev = dev;
-#endif
-
- code = getinode(0, (dev_t) newdev, 2, &ip, credp, &dummy);
- if (code) {
- return (code);
- }
-
- ufsvfsp = ip->i_ufsvfs;
- rw_enter(&ip->i_rwlock, RW_WRITER);
-#ifdef HAVE_VFS_DQRWLOCK
- rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
-#endif
- rw_enter(&ip->i_contents, RW_WRITER);
- code = (*ufs_iallocp) (ip, near_inode, 0, &newip, credp);
- AFS_ITIMES_NOLOCK(ip);
- rw_exit(&ip->i_contents);
-#ifdef HAVE_VFS_DQRWLOCK
- rw_exit(&ufsvfsp->vfs_dqrwlock);
-#endif
- rw_exit(&ip->i_rwlock);
- VN_RELE(ITOV(ip));
-
- if (code) {
- return (code);
- }
- rw_enter(&newip->i_contents, RW_WRITER);
- newip->i_flag |= IACC | IUPD | ICHG;
-
-#if defined(AFS_SUN56_ENV)
- newip->i_vicemagic = VICEMAGIC;
-#else
- newip->i_uid = 0;
- newip->i_gid = -2;
-#endif
- newip->i_nlink = 1;
- newip->i_mode = IFREG;
- newip->i_vnode.v_type = VREG;
-
- newip->i_vicep1 = param1;
- if (param2 == 0x1fffffff /*INODESPECIAL*/) {
- newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
- newip->i_vicep3 = param3;
- } else {
- newip->i_vicep2 =
- (((param2 >> 16) & 0x1f) << 27) +
- (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
- newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
- }
-#ifdef AFS_SUN57_64BIT_ENV
- rvp->r_vals = newip->i_number;
-#else
- rvp->r_val1 = newip->i_number;
-#endif
-
- /*
- * We're being conservative and sync to the disk
- */
- if (CrSync)
- (*ufs_iupdatp) (newip, 1);
- AFS_ITIMES_NOLOCK(newip);
- rw_exit(&newip->i_contents);
- VN_RELE(ITOV(newip));
- return (code);
-}
-
-afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
- rval_t *rvp;
- struct AFS_UCRED *credp;
- int inode, usrmod;
- dev_t dev;
-{
- struct file *fp;
- struct inode *ip;
- struct vnode *vp = NULL;
- int dummy;
- int fd;
- register int code;
- dev_t newdev;
-
- AFS_STATCNT(afs_syscall_iopen);
-
- if (!afs_suser(credp))
- return (EPERM);
-
- /** Code to convert a 32 bit dev_t into a 64 bit dev_t
- * This conversion is needed only for the 64 bit OS.
- */
-
-#ifdef AFS_SUN57_64BIT_ENV
- newdev = expldev((dev32_t) dev);
-#else
- newdev = dev;
-#endif
-
- code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
- if (code) {
- return (code);
- }
- code = falloc((struct vnode *)NULL, FWRITE | FREAD, &fp, &fd);
- if (code) {
- rw_enter(&ip->i_contents, RW_READER);
- AFS_ITIMES(ip);
- rw_exit(&ip->i_contents);
- VN_RELE(ITOV(ip));
- return (code);
- }
-
- /* fp->f_count, f_audit_data are set by falloc */
- fp->f_vnode = ITOV(ip);
-
- fp->f_flag = (usrmod + 1) & (FMASK);
-
- /* fp->f_count, f_msgcount are set by falloc */
-
- /* fp->f_offset zeroed by falloc */
- /* f_cred set by falloc */
- /*
- * falloc returns the fp write locked
- */
- mutex_exit(&fp->f_tlock);
- /*
- * XXX We should set the fp to null since we don't need it in the icalls
- */
- setf(fd, fp);
-#ifdef AFS_SUN57_64BIT_ENV
- rvp->r_val2 = fd;
-#else
- rvp->r_val1 = fd;
-#endif
-
- return code;
-}
-
-int IncSync = 1;
-
-afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
- rval_t *rvp;
- struct AFS_UCRED *credp;
- int inode, inode_p1, amount;
- dev_t dev;
-{
- int dummy;
- struct inode *ip;
- register afs_int32 code;
- dev_t newdev;
-
- if (!afs_suser(credp))
- return (EPERM);
-
- /** Code to convert a 32 bit dev_t into a 64 bit dev_t
- * This conversion is needed only for the 64 bit OS.
- */
-
-#ifdef AFS_SUN57_64BIT_ENV
- newdev = expldev((dev32_t) dev);
-#else
- newdev = dev;
-#endif
-
- code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
- if (code) {
- return (code);
- }
- if (!IS_VICEMAGIC(ip)) {
- code = EPERM;
- rw_enter(&ip->i_contents, RW_READER);
- AFS_ITIMES(ip);
- rw_exit(&ip->i_contents);
- VN_RELE(ITOV(ip));
- } else {
- rw_enter(&ip->i_contents, RW_WRITER);
- ip->i_nlink += amount;
- if (ip->i_nlink == 0) {
- /* remove the "a" name added by igetinode so that the space is reclaimed. */
- dnlc_remove(ITOV(ip), "a");
- CLEAR_VICEMAGIC(ip);
- }
- ip->i_flag |= ICHG;
- /* We may want to force the inode to the disk in case of crashes, other references, etc. */
- if (IncSync)
- (*ufs_iupdatp) (ip, 1);
- AFS_ITIMES_NOLOCK(ip);
- rw_exit(&ip->i_contents);
- VN_RELE(ITOV(ip));
- }
- return (code);
-}
+++ /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
- */
-
-/*
- * Inode information required for SOLARIS servers and salvager.
- */
-#ifndef _OSI_INODE_H_
-#define _OSI_INODE_H_
-
-#define BAD_IGET -1000
-
-#define VICEMAGIC 0x84fa1cb6
-
-/* These exist because HP requires more work to extract uid. */
-#define DI_VICEP3(p) ( (p)->di_vicep3 )
-#define I_VICE3(p) ( (p)->i_vicep3 )
-
-#define di_vicep1 di_un . di_icom .ic_gen
-#define di_vicep2 di_un . di_icom .ic_flags
-#if defined(AFS_SUN56_ENV)
-#define di_vicep3 di_ic.ic_uid
-#define di_vicemagic di_ic.ic_gid
-#else
-#define di_vicep3 di_un . di_icom .ic_size.val[0]
-#endif
-
-#define i_vicep1 i_ic.ic_gen
-#define i_vicep2 i_ic.ic_flags
-#if defined(AFS_SUN56_ENV)
-#define i_vicep3 i_ic.ic_uid
-#define i_vicemagic i_ic.ic_gid
-#else
-#define i_vicep3 i_ic.ic_size.val[0]
-#endif
-
-#if defined(AFS_SUN56_ENV)
-#define IS_VICEMAGIC(ip) ((ip)->i_vicemagic == VICEMAGIC)
-#define IS_DVICEMAGIC(dp) ((dp)->di_vicemagic == VICEMAGIC)
-
-#define CLEAR_VICEMAGIC(ip) (ip)->i_vicemagic = (ip)->i_vicep3 = 0
-#define CLEAR_DVICEMAGIC(dp) (dp)->di_vicemagic = (dp)->di_vicep3 = 0
-#else
-#define IS_VICEMAGIC(ip) (((ip)->i_vicep2 || (ip)->i_vicep3) ? 1 : 0)
-#define IS_DVICEMAGIC(dp) (((dp)->di_vicep2 || (dp)->di_vicep3) ? 1 : 0)
-
-#define CLEAR_VICEMAGIC(ip) (ip)->i_vicep2 = (ip)->i_vicep3 = 0
-#define CLEAR_DVICEMAGIC(dp) (dp)->di_vicep2 = (dp)->di_vicep3 = 0
-#endif
-
-#define AFS_SUN_UFS_CACHE 0
-#ifdef AFS_HAVE_VXFS
-#define AFS_SUN_VXFS_CACHE 1
-#endif /* AFS_HAVE_VXFS */
-
-#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
- */
-
-/*
- * Solaris 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_
-
-#ifdef AFS_SUN57_64BIT_ENV
-#include <sys/model.h> /* for get_udatamodel() */
-#endif
-
-#define getpid() curproc->p_pid
-
-/**
- * The location of the NFSSRV module
- * Used in osi_vfsops.c when checking to see if the nfssrv module is
- * loaded
- */
-#define NFSSRV "/kernel/misc/nfssrv"
-#define NFSSRV_V9 "/kernel/misc/sparcv9/nfssrv"
-
-#define AFS_UCRED cred
-#define AFS_PROC struct proc
-
-/*
- * Time related macros
- */
-#define afs_hz hz
-#ifdef AFS_SUN59_ENV
-#define osi_Time() local_osi_Time()
-extern void gethrestime(timespec_t *);
-static int
-local_osi_Time()
-{
- timespec_t start;
- gethrestime(&start);
- return start.tv_sec;
-}
-#else
-#define osi_Time() (hrestime.tv_sec)
-#endif
-
-#undef afs_osi_Alloc_NoSleep
-extern void *afs_osi_Alloc_NoSleep(size_t size);
-
-#define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0)
-#define gop_rdwr(rw,gp,base,len,offset,segflg,ioflag,ulimit,cr,aresid) \
- vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(ioflag),(ulimit),(cr),(aresid))
-
-#define afs_suser suser
-
-
-#ifdef KERNEL
-/*
- * Global lock support.
- */
-#include <sys/mutex.h>
-extern kmutex_t afs_global_lock;
-extern kmutex_t afs_rxglobal_lock;
-
-#define AFS_GLOCK() mutex_enter(&afs_global_lock);
-#define AFS_GUNLOCK() mutex_exit(&afs_global_lock);
-#define ISAFS_GLOCK() mutex_owned(&afs_global_lock)
-
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-#endif
-
-
-/* Associate the Berkley signal equivalent lock types to System V's */
-#define LOCK_SH 1 /* F_RDLCK */
-#define LOCK_EX 2 /* F_WRLCK */
-#define LOCK_NB 4 /* XXX */
-#define LOCK_UN 8 /* F_UNLCK */
-
-#ifndef IO_APPEND
-#define IO_APPEND FAPPEND
-#endif
-
-#ifndef IO_SYNC
-#define IO_SYNC FSYNC
-#endif
-
-#if defined(AFS_SUN56_ENV)
-/*
-** Macro returns 1 if file is larger than 2GB; else returns 0
-*/
-#undef AfsLargeFileUio
-#define AfsLargeFileUio(uio) ( (uio)->_uio_offset._p._u ? 1 : 0 )
-#undef AfsLargeFileSize
-#define AfsLargeFileSize(pos, off) ( ((offset_t)(pos)+(offset_t)(off) > (offset_t)0x7fffffff)?1:0)
-#endif
-
-#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
- */
-
-#ifndef _OSI_PROTOTYPES_H_
-#define _OSI_PROTOTYPES_H_
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-
-/* osi_vnodeops.c */
-int afs_putapage(struct vnode *vp, struct page *pages,
-#if defined(AFS_SUN56_ENV)
- u_offset_t * offp,
-#else
- u_int * offp,
-#endif
-#if defined(AFS_SUN58_ENV)
- size_t * lenp,
-#else
- u_int * lenp,
-#endif
- int flags, struct AFS_UCRED *credp);
-
-
-
-#endif /* _OSI_PROTOTYPES_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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_sleep.c,v 1.9 2003/07/15 23:14:26 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-
-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) curthread;
- do {
- AFS_ASSERT_GLOCK();
- code = 0;
- code = 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 */
- kcondvar_t cond; /* Currently associated condition variable */
-} 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;
- cv_init(&newp->cond, "event cond var", CV_DEFAULT, NULL);
- 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();
- cv_wait(&evp->cond, &afs_global_lock);
- }
- relevent(evp);
-}
-
-int
-afs_osi_SleepSig(void *event)
-{
- struct afs_event *evp;
- int seq, code = 0;
-
- evp = afs_getevent(event);
- seq = evp->seq;
- while (seq == evp->seq) {
- AFS_ASSERT_GLOCK();
- if (cv_wait_sig(&evp->cond, &afs_global_lock) == 0) {
- code = EINTR;
- break;
- }
- }
- relevent(evp);
- return code;
-}
-
-/* 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.
- */
-static int
-osi_TimedSleep(char *event, afs_int32 ams, int aintok)
-{
- int code = 0;
- struct afs_event *evp;
- clock_t ticks;
-
- ticks = (ams * afs_hz) / 1000;
- ticks = ticks + lbolt;
-
- evp = afs_getevent(event);
-
- AFS_ASSERT_GLOCK();
- if (aintok) {
- if (cv_timedwait_sig(&evp->cond, &afs_global_lock, ticks) == 0)
- code = EINTR;
- } else {
- cv_timedwait(&evp->cond, &afs_global_lock, ticks);
- }
-
- 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++;
- cv_broadcast(&evp->cond);
- ret = 0;
- }
- relevent(evp);
- 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_vfsops.c for SOLARIS
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_vfsops.c,v 1.17 2003/07/15 23:14:26 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-#include "h/modctl.h"
-#include "h/syscall.h"
-#include <sys/kobj.h>
-
-
-
-struct vfs *afs_globalVFS = 0;
-struct vcache *afs_globalVp = 0;
-
-#if defined(AFS_SUN57_64BIT_ENV)
-extern struct sysent sysent32[];
-#endif
-
-int afsfstype = 0;
-
-int
-afs_mount(struct vfs *afsp, struct vnode *amvp, struct mounta *uap,
- struct AFS_UCRED *credp)
-{
-
- AFS_GLOCK();
-
- AFS_STATCNT(afs_mount);
-
- if (!suser(credp)) {
- AFS_GUNLOCK();
- return EPERM;
- }
- afsp->vfs_fstype = afsfstype;
-
- if (afs_globalVFS) { /* Don't allow remounts. */
- AFS_GUNLOCK();
- return EBUSY;
- }
-
- afs_globalVFS = afsp;
- afsp->vfs_bsize = 8192;
- afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
- afsp->vfs_fsid.val[1] = AFS_VFSFSID;
- afsp->vfs_dev = AFS_VFSMAGIC;
-
- AFS_GUNLOCK();
- return 0;
-}
-
-#if defined(AFS_SUN58_ENV)
-int
-afs_unmount(struct vfs *afsp, int flag, struct AFS_UCRED *credp)
-#else
-int
-afs_unmount(struct vfs *afsp, struct AFS_UCRED *credp)
-#endif
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
-
- if (!suser(credp)) {
- AFS_GUNLOCK();
- return EPERM;
- }
- afs_globalVFS = 0;
- afs_shutdown();
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_root(struct vfs *afsp, struct vnode **avpp)
-{
- register afs_int32 code = 0;
- struct vrequest treq;
- register struct vcache *tvp = 0;
- struct proc *proc = ttoproc(curthread);
- struct vnode *vp = afsp->vfs_vnodecovered;
- int locked = 0;
-
- /* Potential deadlock:
- * afs_root is called with the Vnode's v_lock locked. Set VVFSLOCK
- * and drop the v_lock if we need to make an RPC to complete this
- * request. There used to be a deadlock on the global lock until
- * we stopped calling iget while holding the global lock.
- */
-
- AFS_GLOCK();
-
- AFS_STATCNT(afs_root);
-
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- if (MUTEX_HELD(&vp->v_lock)) {
- vp->v_flag |= VVFSLOCK;
- locked = 1;
- mutex_exit(&vp->v_lock);
- }
-
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, proc->p_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) {
- VN_HOLD(AFSTOV(tvp));
- mutex_enter(&AFSTOV(tvp)->v_lock);
- AFSTOV(tvp)->v_flag |= VROOT;
- mutex_exit(&AFSTOV(tvp)->v_lock);
-
- afs_globalVFS = afsp;
- *avpp = AFSTOV(tvp);
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
- ICL_TYPE_INT32, code);
-
- AFS_GUNLOCK();
- if (locked) {
- mutex_enter(&vp->v_lock);
- vp->v_flag &= ~VVFSLOCK;
- if (vp->v_flag & VVFSWAIT) {
- vp->v_flag &= ~VVFSWAIT;
- cv_broadcast(&vp->v_cv);
- }
- }
-
- return code;
-}
-
-#ifdef AFS_SUN56_ENV
-int
-afs_statvfs(struct vfs *afsp, struct statvfs64 *abp)
-#else
-int
-afs_statvfs(struct vfs *afsp, struct statvfs *abp)
-#endif
-{
- AFS_GLOCK();
-
- AFS_STATCNT(afs_statfs);
-
- abp->f_frsize = 1024;
- abp->f_favail = 9000000;
- abp->f_bsize = afsp->vfs_bsize;
- abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
- abp->f_ffree = 9000000;
- abp->f_fsid = (AFS_VFSMAGIC << 16) || AFS_VFSFSID;
-
- AFS_GUNLOCK();
- return 0;
-}
-
-int
-afs_sync(struct vfs *afsp, short flags, struct AFS_UCRED *credp)
-{
- return 0;
-}
-
-int
-afs_vget(struct vfs *afsp, struct vnode **avcp, struct fid *fidp)
-{
- cred_t *credp = CRED();
- struct vrequest treq;
- int code;
-
- AFS_GLOCK();
-
- AFS_STATCNT(afs_vget);
-
- *avcp = NULL;
- if (!(code = afs_InitReq(&treq, credp))) {
- 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;
-}
-
-/* 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;
-afs_mountroot(struct vfs *afsp, whymountroot_t why)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_mountroot);
- afsmountroot++;
- AFS_GUNLOCK();
- return EINVAL;
-}
-
-/* afs_swapvp is called to setup swapping over the net for diskless clients.
- * Again not for us.
- */
-int afsswapvp = 0;
-afs_swapvp(struct vfs *afsp, struct vnode **avpp, char *nm)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_swapvp);
- afsswapvp++;
- AFS_GUNLOCK();
- return EINVAL;
-}
-
-
-struct vfsops Afs_vfsops = {
- afs_mount,
- afs_unmount,
- afs_root,
- afs_statvfs,
- afs_sync,
- afs_vget,
- afs_mountroot,
- afs_swapvp,
-#if defined(AFS_SUN58_ENV)
- fs_freevfs,
-#endif
-};
-
-
-/*
- * afsinit - intialize VFS
- */
-int (*ufs_iallocp) ();
-void (*ufs_iupdatp) ();
-int (*ufs_igetp) ();
-void (*ufs_itimes_nolockp) ();
-
-int (*afs_orig_ioctl) (), (*afs_orig_ioctl32) ();
-int (*afs_orig_setgroups) (), (*afs_orig_setgroups32) ();
-
-struct streamtab *udp_infop = 0;
-struct ill_s *ill_g_headp = 0;
-
-int afs_sinited = 0;
-
-#if !defined(AFS_NONFSTRANS)
-int (*nfs_rfsdisptab_v2) ();
-int (*nfs_rfsdisptab_v3) ();
-int (*nfs_acldisptab_v2) ();
-int (*nfs_acldisptab_v3) ();
-
-int (*nfs_checkauth) ();
-#endif
-
-extern Afs_syscall();
-
-afsinit(struct vfssw *vfsswp, int fstype)
-{
- extern int afs_xioctl();
- extern int afs_xsetgroups();
-
- AFS_STATCNT(afsinit);
-
- afs_orig_setgroups = sysent[SYS_setgroups].sy_callc;
- afs_orig_ioctl = sysent[SYS_ioctl].sy_call;
- sysent[SYS_setgroups].sy_callc = afs_xsetgroups;
- sysent[SYS_ioctl].sy_call = afs_xioctl;
-
-#if defined(AFS_SUN57_64BIT_ENV)
- afs_orig_setgroups32 = sysent32[SYS_setgroups].sy_callc;
- afs_orig_ioctl32 = sysent32[SYS_ioctl].sy_call;
- sysent32[SYS_setgroups].sy_callc = afs_xsetgroups;
- sysent32[SYS_ioctl].sy_call = afs_xioctl;
-#endif
-
- vfsswp->vsw_vfsops = &Afs_vfsops;
- afsfstype = fstype;
-
-
-#if !defined(AFS_NONFSTRANS)
- nfs_rfsdisptab_v2 = (int (*)())modlookup("nfssrv", "rfsdisptab_v2");
- if (!nfs_rfsdisptab_v2) {
- afs_warn("warning : rfsdisptab_v2 NOT FOUND\n");
- }
- if (nfs_rfsdisptab_v2) {
- nfs_acldisptab_v2 = (int (*)())modlookup("nfssrv", "acldisptab_v2");
- if (!nfs_acldisptab_v2) {
- afs_warn("warning : acldisptab_v2 NOT FOUND\n");
- } else {
- afs_xlatorinit_v2(nfs_rfsdisptab_v2, nfs_acldisptab_v2);
- }
- }
- nfs_rfsdisptab_v3 = (int (*)())modlookup("nfssrv", "rfsdisptab_v3");
- if (!nfs_rfsdisptab_v3) {
- afs_warn("warning : rfsdisptab_v3 NOT FOUND\n");
- }
- if (nfs_rfsdisptab_v3) {
- nfs_acldisptab_v3 = (int (*)())modlookup("nfssrv", "acldisptab_v3");
- if (!nfs_acldisptab_v3) {
- afs_warn("warning : acldisptab_v3 NOT FOUND\n");
- } else {
- afs_xlatorinit_v3(nfs_rfsdisptab_v3, nfs_acldisptab_v3);
- }
- }
-
- nfs_checkauth = (int (*)())modlookup("nfssrv", "checkauth");
- if (!nfs_checkauth)
- afs_warn("nfs_checkauth not initialised");
-#endif
- ufs_iallocp = (int (*)())modlookup("ufs", "ufs_ialloc");
- ufs_iupdatp = (void (*)())modlookup("ufs", "ufs_iupdat");
- ufs_igetp = (int (*)())modlookup("ufs", "ufs_iget");
- ufs_itimes_nolockp = (void (*)())modlookup("ufs", "ufs_itimes_nolock");
- udp_infop = (struct streamtab *)modlookup("udp", "udpinfo");
- ill_g_headp = (struct ill_s *)modlookup("ip", "ill_g_head");
-
- if (!ufs_iallocp || !ufs_iupdatp || !ufs_itimes_nolockp || !ufs_igetp
- || !udp_infop || !ill_g_headp)
- afs_warn("AFS to UFS mapping cannot be fully initialised\n");
-
- afs_sinited = 1;
- return 0;
-
-}
-
-static struct vfssw afs_vfw = {
- "afs",
- afsinit,
- &Afs_vfsops,
- 0
-};
-
-static struct sysent afssysent = {
- 6,
- 0,
- Afs_syscall
-};
-
-/* inter-module dependencies */
-char _depends_on[] = "drv/ip drv/udp strmod/rpcmod";
-
-/*
- * Info/Structs to link the afs module into the kernel
- */
-extern struct mod_ops mod_fsops;
-extern struct mod_ops mod_syscallops;
-
-static struct modlfs afsmodlfs = {
- &mod_fsops,
- "afs filesystem",
- &afs_vfw
-};
-
-static struct modlsys afsmodlsys = {
- &mod_syscallops,
- "afs syscall interface",
- &afssysent
-};
-
-/** The two structures afssysent32 and afsmodlsys32 are being added
- * for supporting 32 bit syscalls. In Solaris 7 there are two system
- * tables viz. sysent ans sysent32. 32 bit applications use sysent32.
- * Since most of our user space binaries are going to be 32 bit
- * we need to attach to sysent32 also. Note that the entry into AFS
- * land still happens through Afs_syscall irrespective of whether we
- * land here from sysent or sysent32
- */
-
-#if defined(AFS_SUN57_64BIT_ENV)
-extern struct mod_ops mod_syscallops32;
-
-static struct modlsys afsmodlsys32 = {
- &mod_syscallops32,
- "afs syscall interface(32 bit)",
- &afssysent
-};
-#endif
-
-
-static struct modlinkage afs_modlinkage = {
- MODREV_1,
- (void *)&afsmodlsys,
-#ifdef AFS_SUN57_64BIT_ENV
- (void *)&afsmodlsys32,
-#endif
- (void *)&afsmodlfs,
- NULL
-};
-
-/** This is the function that modload calls when loading the afs kernel
- * extensions. The solaris modload program searches for the _init
- * function in a module and calls it when modloading
- */
-
-_init()
-{
- char *sysn, *mod_getsysname();
- int code;
- extern char *sysbind;
- extern struct bind *sb_hashtab[];
- struct modctl *mp = 0;
-
- if (afs_sinited)
- return EBUSY;
-
- if ((!(mp = mod_find_by_filename("fs", "ufs"))
- && !(mp = mod_find_by_filename(NULL, "/kernel/fs/ufs"))
- && !(mp = mod_find_by_filename(NULL, "sys/ufs"))) || (mp
- && !mp->
- mod_installed))
- {
- printf
- ("ufs module must be loaded before loading afs; use modload /kernel/fs/ufs\n");
- return (ENOSYS);
- }
-#ifndef AFS_NONFSTRANS
-#if defined(AFS_SUN55_ENV)
- if ((!(mp = mod_find_by_filename("misc", "nfssrv"))
- && !(mp = mod_find_by_filename(NULL, NFSSRV))
- && !(mp = mod_find_by_filename(NULL, NFSSRV_V9))) || (mp
- && !mp->
- mod_installed))
- {
- printf
- ("misc/nfssrv module must be loaded before loading afs with nfs-xlator\n");
- return (ENOSYS);
- }
-#else /* !AFS_SUN55_ENV */
-#if defined(AFS_SUN52_ENV)
- if ((!(mp = mod_find_by_filename("fs", "nfs"))
- && !(mp = mod_find_by_filename(NULL, "/kernel/fs/nfs"))
- && !(mp = mod_find_by_filename(NULL, "sys/nfs"))) || (mp
- && !mp->
- mod_installed))
- {
- printf
- ("fs/nfs module must be loaded before loading afs with nfs-xlator\n");
- return (ENOSYS);
- }
-#endif /* AFS_SUN52_ENV */
-#endif /* AFS_SUN55_ENV */
-#endif /* !AFS_NONFSTRANS */
-#if !defined(AFS_SUN58_ENV)
- /*
- * Re-read the /etc/name_to_sysnum file to make sure afs isn't added after
- * reboot. Ideally we would like to call modctl_read_sysbinding_file() but
- * unfortunately in Solaris 2.2 it became a local function so we have to do
- * the read_binding_file() direct call with the appropriate text file and
- * system call hashtable. make_syscallname actually copies "afs" to the
- * proper slot entry and we also actually have to properly initialize the
- * global sysent[AFS_SYSCALL] entry!
- */
-#ifdef AFS_SUN53_ENV
-#ifndef SYSBINDFILE
-#define SYSBINDFILE "/etc/name_to_sysnum"
-#endif /* SYSBINDFILE */
- read_binding_file(SYSBINDFILE, sb_hashtab);
-#else /* !AFS_SUN53_ENV */
- read_binding_file(sysbind, sb_hashtab);
-#endif /* AFS_SUN53_ENV */
- make_syscallname("afs", AFS_SYSCALL);
-
- if (sysent[AFS_SYSCALL].sy_call == nosys) {
- if ((sysn = mod_getsysname(AFS_SYSCALL)) != NULL) {
- sysent[AFS_SYSCALL].sy_lock =
- (krwlock_t *) kobj_zalloc(sizeof(krwlock_t), KM_SLEEP);
- rw_init(sysent[AFS_SYSCALL].sy_lock, "afs_syscall",
-#ifdef AFS_SUN57_ENV
- RW_DEFAULT, NULL);
-#else /* !AFS_SUN57_ENV */
- RW_DEFAULT, DEFAULT_WT);
-#endif /* AFS_SUN57_ENV */
- }
- }
-#endif /* !AFS_SUN58_ENV */
-
- osi_Init(); /* initialize global lock, etc */
-
- code = mod_install(&afs_modlinkage);
- return code;
-}
-
-_info(modp)
- struct modinfo *modp;
-{
- int code;
-
- code = mod_info(&afs_modlinkage, modp);
- return code;
-}
-
-_fini()
-{
- int code;
-
- if (afs_globalVFS)
- return EBUSY;
-
- if (afs_sinited) {
- sysent[SYS_setgroups].sy_callc = afs_orig_setgroups;
- sysent[SYS_ioctl].sy_call = afs_orig_ioctl;
-#if defined(AFS_SUN57_64BIT_ENV)
- sysent32[SYS_setgroups].sy_callc = afs_orig_setgroups32;
- sysent32[SYS_ioctl].sy_call = afs_orig_ioctl32;
-#endif
- }
- code = mod_remove(&afs_modlinkage);
- return code;
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_vm.c,v 1.8 2003/07/15 23:14:26 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/nfsclient.h"
-
-#if defined(AFS_SUN5_ENV)
-/* This file contains Solaris VM-related code for the cache manager. */
-
-#include <sys/mman.h>
-#include <vm/hat.h>
-#include <vm/as.h>
-#include <vm/page.h>
-#include <vm/pvn.h>
-#include <vm/seg.h>
-#include <vm/seg_map.h>
-#include <vm/seg_vn.h>
-#include <vm/rm.h>
-#include <sys/modctl.h>
-#include <sys/syscall.h>
-#include <sys/debug.h>
-#include <sys/fs_subr.h>
-
-/* Try to invalidate pages, in order to recycle a dcache entry.
- *
- * This function only exists for Solaris. For other platforms, it's OK to
- * recycle a dcache entry without invalidating pages, because the strategy
- * function can call afs_GetDCache().
- *
- * Locking: only the global lock is held on entry.
- */
-int
-osi_VM_GetDownD(struct vcache *avc, struct dcache *adc)
-{
- int code;
-
- AFS_GUNLOCK();
- code =
- afs_putpage(AFSTOV(avc), (offset_t) AFS_CHUNKTOBASE(adc->f.chunk),
- AFS_CHUNKTOSIZE(adc->f.chunk), B_INVAL, CRED());
- AFS_GLOCK();
-
- return code;
-}
-
-/* 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.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- if (avc->vrefCount != 0)
- return EBUSY;
-
- if (avc->opens)
- return EBUSY;
-
- /* if a lock is held, give up */
- if (CheckLock(&avc->lock))
- return EBUSY;
- if (afs_CheckBozonLock(&avc->pvnLock))
- return EBUSY;
-
- AFS_GUNLOCK();
- pvn_vplist_dirty(AFSTOV(avc), 0, NULL, B_TRUNC | B_INVAL, CRED());
- AFS_GLOCK();
-
- /* Might as well make the obvious check */
- if (AFSTOV(avc)->v_pages)
- return EBUSY; /* should be all gone still */
-
- rw_destroy(&avc->rwlock);
- if (avc->credp) {
- crfree(avc->credp);
- avc->credp = NULL;
- }
-
-
- return 0;
-}
-
-/* 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)
-{
- AFS_GUNLOCK();
-#if defined(AFS_SUN56_ENV)
- (void)pvn_vplist_dirty(AFSTOV(avc), (u_offset_t) 0, afs_putapage, 0,
- CRED());
-#else
- (void)pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage, 0, CRED());
-#endif
- AFS_GLOCK();
-}
-
-/* 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.
- */
-void
-osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
-{
- AFS_GUNLOCK();
-#if defined(AFS_SUN56_ENV)
- (void)pvn_vplist_dirty(AFSTOV(avc), (u_offset_t) 0, afs_putapage,
- (sync ? B_INVAL : B_FREE), acred);
-#else
- (void)pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage,
- (sync ? B_INVAL : B_FREE), acred);
-#endif
- AFS_GLOCK();
-}
-
-/* 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, struct AFS_UCRED *credp)
-{
- extern int afs_pvn_vptrunc;
-
- afs_pvn_vptrunc++;
- (void)afs_putpage(AFSTOV(avc), (offset_t) 0, 0, B_TRUNC | B_INVAL, credp);
-}
-
-/* Zero no-longer-used part of last page, when truncating a file
- *
- * This function only exists for Solaris. Other platforms do not support it.
- *
- * Locking: the vcache entry lock is held. It is released and re-obtained.
- * The caller will raise activeV (to prevent pageins), but this function must
- * be called first, since it causes a pagein.
- */
-void
-osi_VM_PreTruncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
-{
- page_t *pp;
- int pageOffset = (alen & PAGEOFFSET);
-
- if (pageOffset == 0) {
- return;
- }
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- pp = page_lookup(AFSTOV(avc), alen - pageOffset, SE_EXCL);
- if (pp) {
- pagezero(pp, pageOffset, PAGESIZE - pageOffset);
- page_unlock(pp);
- }
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 563);
-}
-
-/* Purge pages beyond end-of-file, when truncating a file.
- *
- * Locking: no lock is held, not even the global lock.
- * Pageins are blocked (activeV is raised).
- */
-void
-osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
-{
- /*
- * It's OK to specify afs_putapage here, even though we aren't holding
- * the vcache entry lock, because it isn't going to get called.
- */
- pvn_vplist_dirty(AFSTOV(avc), alen, afs_putapage, B_TRUNC | B_INVAL,
- acred);
-}
-
-#endif /* SUN5 && !NCR */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/SOLARIS/osi_vnodeops.c,v 1.19 2003/07/15 23:14:26 shadow Exp $");
-
-#if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
-/*
- * SOLARIS/osi_vnodeops.c
- *
- * Implements:
- *
- * Functions: AFS_TRYUP, _init, _info, _fini, afs_addmap, afs_delmap,
- * afs_vmread, afs_vmwrite, afs_getpage, afs_GetOnePage, afs_putpage,
- * afs_putapage, afs_nfsrdwr, afs_map, afs_PageLeft, afs_pathconf/afs_cntl,
- * afs_ioctl, afs_rwlock, afs_rwunlock, afs_seek, afs_space, afs_dump,
- * afs_cmp, afs_realvp, afs_pageio, afs_dumpctl, afs_dispose, afs_setsecattr,
- * afs_getsecattr, gafs_open, gafs_close, gafs_getattr, gafs_setattr,
- * gafs_access, gafs_lookup, gafs_create, gafs_remove, gafs_link,
- * gafs_rename, gafs_mkdir, gafs_rmdir, gafs_readdir, gafs_symlink,
- * gafs_readlink, gafs_fsync, afs_inactive, gafs_inactive, gafs_fid
- *
- *
- * Variables: Afs_vnodeops
- *
- */
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/nfsclient.h"
-
-
-#include <sys/mman.h>
-#include <vm/hat.h>
-#include <vm/as.h>
-#include <vm/page.h>
-#include <vm/pvn.h>
-#include <vm/seg.h>
-#include <vm/seg_map.h>
-#include <vm/seg_vn.h>
-#include <vm/rm.h>
-#if defined(AFS_SUN5_ENV)
-#include <sys/modctl.h>
-#include <sys/syscall.h>
-#else
-#include <vm/swap.h>
-#endif
-#include <sys/debug.h>
-#if defined(AFS_SUN5_ENV)
-#include <sys/fs_subr.h>
-#endif
-
-#if defined(AFS_SUN5_ENV)
-/*
- * XXX Temporary fix for problems with Solaris rw_tryupgrade() lock.
- * It isn't very persistent in getting the upgrade when others are
- * waiting for it and returns 0. So the UpgradeSToW() macro that the
- * rw_tryupgrade used to map to wasn't good enough and we need to use
- * the following code instead. Obviously this isn't the proper place
- * for it but it's only called from here for now
- *
- */
-#ifndef AFS_SUN54_ENV
-AFS_TRYUP(lock)
- afs_rwlock_t *lock;
-{
- if (!rw_tryupgrade(lock)) {
- rw_exit(lock);
- rw_enter(lock, RW_WRITER);
- }
-}
-#endif
-#endif
-
-
-/* Translate a faultcode_t as returned by some of the vm routines
- * into a suitable errno value.
- */
-static int
-afs_fc2errno(faultcode_t fc)
-{
- switch (FC_CODE(fc)) {
- case 0:
- return 0;
-
- case FC_OBJERR:
- return FC_ERRNO(fc);
-
- default:
- return EIO;
- }
-}
-
-
-extern struct as kas; /* kernel addr space */
-extern unsigned char *afs_indexFlags;
-extern afs_lock_t afs_xdcache;
-
-/* Additional vnodeops for SunOS 4.0.x */
-int afs_nfsrdwr(), afs_getpage(), afs_putpage(), afs_map();
-int afs_dump(), afs_cmp(), afs_realvp(), afs_GetOnePage();
-
-int afs_pvn_vptrunc;
-
-#ifdef AFS_SUN5_ENV
-
-int
-afs_addmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
- register struct vnode *avp;
- offset_t offset;
- struct as *asp;
- caddr_t addr;
- int length, prot, maxprot, flags;
- struct AFS_UCRED *credp;
-{
- /* XXX What should we do here?? XXX */
- return (0);
-}
-
-int
-afs_delmap(avp, offset, asp, addr, length, prot, maxprot, flags, credp)
- register struct vnode *avp;
- offset_t offset;
- struct as *asp;
- caddr_t addr;
- int length, prot, maxprot, flags;
- struct AFS_UCRED *credp;
-{
- /* XXX What should we do here?? XXX */
- return (0);
-}
-
-int
-afs_vmread(avp, auio, ioflag, acred)
- register struct vnode *avp;
- struct uio *auio;
- int ioflag;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- if (!RW_READ_HELD(&(VTOAFS(avp))->rwlock))
- osi_Panic("afs_vmread: !rwlock");
- AFS_GLOCK();
- code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_READ, ioflag, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-
-int
-afs_vmwrite(avp, auio, ioflag, acred)
- register struct vnode *avp;
- struct uio *auio;
- int ioflag;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- if (!RW_WRITE_HELD(&(VTOAFS(avp))->rwlock))
- osi_Panic("afs_vmwrite: !rwlock");
- AFS_GLOCK();
- code = afs_nfsrdwr(VTOAFS(avp), auio, UIO_WRITE, ioflag, acred);
- AFS_GUNLOCK();
- return code;
-}
-
-#endif /* AFS_SUN5_ENV */
-
-int
-afs_getpage(vp, off, len, protp, pl, plsz, seg, addr, rw, acred)
- struct vnode *vp;
- u_int len;
- u_int *protp;
- struct page *pl[];
- u_int plsz;
- struct seg *seg;
-#ifdef AFS_SUN5_ENV
- offset_t off;
- caddr_t addr;
-#else
- u_int off;
- addr_t addr;
-#endif
- enum seg_rw rw;
- struct AFS_UCRED *acred;
-{
- register afs_int32 code = 0;
- AFS_STATCNT(afs_getpage);
-
-#ifdef AFS_SUN5_ENV
- if (vp->v_flag & VNOMAP) /* File doesn't allow mapping */
- return (ENOSYS);
-#endif
-
- AFS_GLOCK();
-
-#if defined(AFS_SUN56_ENV)
- if (len <= PAGESIZE)
- code =
- afs_GetOnePage(vp, off, len, protp, pl, plsz, seg, addr, rw,
- acred);
-#else
-#ifdef AFS_SUN5_ENV
- if (len <= PAGESIZE)
- code =
- afs_GetOnePage(vp, (u_int) off, len, protp, pl, plsz, seg, addr,
- rw, acred);
-#else
- if (len == PAGESIZE)
- code = afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred);
-#endif
-#endif
- else {
- struct vcache *vcp = VTOAFS(vp);
-#ifdef AFS_SUN5_ENV
- ObtainWriteLock(&vcp->vlock, 548);
- vcp->multiPage++;
- ReleaseWriteLock(&vcp->vlock);
-#endif
- afs_BozonLock(&vcp->pvnLock, vcp);
-#if defined(AFS_SUN56_ENV)
- code =
- pvn_getpages(afs_GetOnePage, vp, off, len, protp, pl, plsz, seg,
- addr, rw, acred);
-#else
- code =
- pvn_getpages(afs_GetOnePage, vp, (u_int) off, len, protp, pl,
- plsz, seg, addr, rw, acred);
-#endif
- afs_BozonUnlock(&vcp->pvnLock, vcp);
-#ifdef AFS_SUN5_ENV
- ObtainWriteLock(&vcp->vlock, 549);
- vcp->multiPage--;
- ReleaseWriteLock(&vcp->vlock);
-#endif
- }
- AFS_GUNLOCK();
- return code;
-}
-
-/* Return all the pages from [off..off+len) in file */
-#ifdef AFS_SUN5_ENV
-int
-afs_GetOnePage(vp, off, alen, protp, pl, plsz, seg, addr, rw, acred)
- u_int alen;
-#else
-int
-afs_GetOnePage(vp, off, protp, pl, plsz, seg, addr, rw, acred)
-#endif
- struct vnode *vp;
-#if defined(AFS_SUN56_ENV)
- u_offset_t off;
-#else
- u_int off;
-#endif
- u_int *protp;
- struct page *pl[];
- u_int plsz;
- struct seg *seg;
-#ifdef AFS_SUN5_ENV
- caddr_t addr;
-#else
- addr_t addr;
-#endif
- enum seg_rw rw;
- struct AFS_UCRED *acred;
-{
- register struct page *page;
- register afs_int32 code = 0;
- u_int len;
- struct buf *buf;
- afs_int32 tlen;
- register struct vcache *avc;
- register struct dcache *tdc;
- int i, s, pexists;
- int slot;
- afs_size_t offset, nlen;
- struct vrequest treq;
- afs_int32 mapForRead = 0, Code = 0;
-#if defined(AFS_SUN56_ENV)
- u_offset_t toffset;
-#else
- afs_int32 toffset;
-#endif
-
- if (!acred)
-#ifdef AFS_SUN5_ENV
- osi_Panic("GetOnePage: !acred");
-#else
- acred = u.u_cred; /* better than nothing */
-#endif
-
- avc = VTOAFS(vp); /* cast to afs vnode */
-
-#ifdef AFS_SUN5_ENV
- if (avc->credp /*&& AFS_NFSXLATORREQ(acred) */
- && AFS_NFSXLATORREQ(avc->credp)) {
- acred = avc->credp;
- }
-#endif
- if (code = afs_InitReq(&treq, acred))
- return code;
-
- if (!pl) {
- /* This is a read-ahead request, e.g. due to madvise. */
-#ifdef AFS_SUN5_ENV
- int plen = alen;
-#else
- int plen = PAGESIZE;
-#endif
- ObtainReadLock(&avc->lock);
-
- while (plen > 0 && !afs_BBusy()) {
- /* Obtain a dcache entry at off. 2 means don't fetch data. */
- tdc =
- afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen,
- 2);
- if (!tdc)
- break;
-
- /* Write-lock the dcache entry, if we don't succeed, just go on */
- if (0 != NBObtainWriteLock(&tdc->lock, 642)) {
- afs_PutDCache(tdc);
- goto next_prefetch;
- }
-
- /* If we aren't already fetching this dcache entry, queue it */
- if (!(tdc->mflags & DFFetchReq)) {
- struct brequest *bp;
-
- tdc->mflags |= DFFetchReq;
- bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) off, (afs_size_t) 1, tdc);
- if (!bp) {
- /* Unable to start background fetch; might as well stop */
- tdc->mflags &= ~DFFetchReq;
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- break;
- }
- ReleaseWriteLock(&tdc->lock);
- } else {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
-
- next_prefetch:
- /* Adjust our offset and remaining length values */
- off += nlen;
- plen -= nlen;
-
- /* If we aren't making progress for some reason, bail out */
- if (nlen <= 0)
- break;
- }
-
- ReleaseReadLock(&avc->lock);
- return 0;
- }
-
- len = PAGESIZE;
- pl[0] = NULL; /* Make sure it's empty */
-
- /* first, obtain the proper lock for the VM system */
-
- /* if this is a read request, map the page in read-only. This will
- * allow us to swap out the dcache entry if there are only read-only
- * pages created for the chunk, which helps a *lot* when dealing
- * with small caches. Otherwise, we have to invalidate the vm
- * pages for the range covered by a chunk when we swap out the
- * chunk.
- */
- if (rw == S_READ || rw == S_EXEC)
- mapForRead = 1;
-
- if (protp)
- *protp = PROT_ALL;
-#ifndef AFS_SUN5_ENV
- if (AFS_NFSXLATORREQ(acred)) {
- if (rw == S_READ) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- return EACCES;
- }
- }
- }
-#endif
-
- retry:
-#ifdef AFS_SUN5_ENV
- if (rw == S_WRITE || rw == S_CREATE)
- tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 5);
- else
- tdc = afs_GetDCache(avc, (afs_offs_t) off, &treq, &offset, &nlen, 1);
- if (!tdc)
- return EINVAL;
-#endif
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
-#ifdef AFS_SUN5_ENV
- afs_PutDCache(tdc);
-#endif
- return afs_CheckCode(code, &treq, 44); /* failed to get it */
- }
-
- afs_BozonLock(&avc->pvnLock, avc);
- ObtainReadLock(&avc->lock);
-
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, (afs_int32) vp,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off), ICL_TYPE_LONG, len,
- ICL_TYPE_LONG, (int)rw);
-
- tlen = len;
- slot = 0;
- toffset = off;
-#ifdef AFS_SUN5_ENV
- /* Check to see if we're in the middle of a VM purge, and if we are, release
- * the locks and try again when the VM purge is done. */
- ObtainWriteLock(&avc->vlock, 550);
- if (avc->activeV) {
- ReleaseReadLock(&avc->lock);
- ReleaseWriteLock(&avc->vlock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- afs_PutDCache(tdc);
- /* Check activeV again, it may have been turned off
- * while we were waiting for a lock in afs_PutDCache */
- ObtainWriteLock(&avc->vlock, 574);
- if (avc->activeV) {
- avc->vstates |= VRevokeWait;
- ReleaseWriteLock(&avc->vlock);
- afs_osi_Sleep(&avc->vstates);
- } else {
- ReleaseWriteLock(&avc->vlock);
- }
- goto retry;
- }
- ReleaseWriteLock(&avc->vlock);
-#endif
-
- /* We're about to do stuff with our dcache entry.. Lock it. */
- ObtainReadLock(&tdc->lock);
-
- /* Check to see whether the cache entry is still valid */
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- afs_PutDCache(tdc);
- goto retry;
- }
-
- AFS_GUNLOCK();
- while (1) { /* loop over all pages */
- /* now, try to find the page in memory (it may already be intransit or laying
- * around the free list */
- page =
- page_lookup(vp, toffset, (rw == S_CREATE ? SE_EXCL : SE_SHARED));
- if (page)
- goto nextpage;
-
- /* if we make it here, we can't find the page in memory. Do a real disk read
- * from the cache to get the data */
- Code |= 0x200; /* XXX */
-#ifdef AFS_SUN5_ENV
-#if defined(AFS_SUN54_ENV)
- /* use PG_EXCL because we know the page does not exist already. If it
- * actually does exist, we have somehow raced between lookup and create.
- * As of 4/98, that shouldn't be possible, but we'll be defensive here
- * in case someone tries to relax all the serialization of read and write
- * operations with harmless things like stat. */
-#if defined(AFS_SUN58_ENV)
- page =
- page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL, seg,
- addr);
-#else
- page =
- page_create_va(vp, toffset, PAGESIZE, PG_WAIT | PG_EXCL,
- seg->s_as, addr);
-#endif
-#else
- page = page_create(vp, toffset, PAGESIZE, PG_WAIT);
-#endif
- if (!page) {
- continue;
- }
- if (alen < PAGESIZE)
- pagezero(page, alen, PAGESIZE - alen);
-#else
- page = rm_allocpage(seg, addr, PAGESIZE, 1); /* can't fail */
- if (!page)
- osi_Panic("afs_getpage alloc page");
- /* we get a circularly-linked list of pages back, but we expect only
- * one, since that's what we asked for */
- if (page->p_next != page)
- osi_Panic("afs_getpage list");
- /* page enter returns a locked page; we'll drop the lock as a side-effect
- * of the pvn_done done by afs_ustrategy. If we decide not to call
- * strategy, we must be sure to call pvn_fail, at least, to release the
- * page locks and otherwise reset the pages. The page, while locked, is
- * not held, for what it is worth */
- page->p_intrans = 1; /* set appropriate flags */
- page->p_pagein = 1;
- /* next call shouldn't fail, since we have pvnLock set */
- if (page_enter(page, vp, toffset))
- osi_Panic("afs_getpage enter race");
-#endif /* AFS_SUN5_ENV */
-
-#ifdef AFS_SUN5_ENV
- if (rw == S_CREATE) {
- /* XXX Don't read from AFS in write only cases XXX */
- page_io_unlock(page);
- } else
-#else
- if (0) {
- /* XXX Don't read from AFS in write only cases XXX */
- page->p_intrans = page->p_pagein = 0;
- page_unlock(page); /* XXX */
- } else
-#endif
- {
-#ifndef AFS_SUN5_ENV
- PAGE_HOLD(page);
-#endif
- /* now it is time to start I/O operation */
- buf = pageio_setup(page, PAGESIZE, vp, B_READ); /* allocate a buf structure */
-#if defined(AFS_SUN5_ENV)
- buf->b_edev = 0;
-#endif
- buf->b_dev = 0;
- buf->b_blkno = btodb(toffset);
- bp_mapin(buf); /* map it in to our address space */
-
-#if defined(AFS_SUN5_ENV)
- AFS_GLOCK();
- /* afs_ustrategy will want to lock the dcache entry */
- ReleaseReadLock(&tdc->lock);
- code = afs_ustrategy(buf, acred); /* do the I/O */
- ObtainReadLock(&tdc->lock);
- AFS_GUNLOCK();
-#else
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_ustrategy(buf); /* do the I/O */
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
-#endif
-
-#ifdef AFS_SUN5_ENV
- /* Before freeing unmap the buffer */
- bp_mapout(buf);
- pageio_done(buf);
-#endif
- if (code) {
-#ifndef AFS_SUN5_ENV
- PAGE_RELE(page);
-#endif
- goto bad;
- }
-#ifdef AFS_SUN5_ENV
- page_io_unlock(page);
-#endif
- }
-
- /* come here when we have another page (already held) to enter */
- nextpage:
- /* put page in array and continue */
-#ifdef AFS_SUN5_ENV
- /* The p_selock must be downgraded to a shared lock after the page is read */
-#if defined(AFS_SUN56_ENV)
- if ((rw != S_CREATE) && !(PAGE_SHARED(page)))
-#else
- if ((rw != S_CREATE) && !(se_shared_assert(&page->p_selock)))
-#endif
- {
- page_downgrade(page);
- }
-#endif
- pl[slot++] = page;
-#ifdef AFS_SUN5_ENV
- code = page_iolock_assert(page);
-#endif
- code = 0;
- toffset += PAGESIZE;
- addr += PAGESIZE;
- tlen -= PAGESIZE;
- if (tlen <= 0)
- break; /* done all the pages */
- } /* while (1) ... */
-
- AFS_GLOCK();
- pl[slot] = NULL;
- ReleaseReadLock(&tdc->lock);
-
- /* Prefetch next chunk if we're at a chunk boundary */
- if (AFS_CHUNKOFFSET(off) == 0) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, acred, &treq);
- }
-
- ReleaseReadLock(&avc->lock);
-#ifdef AFS_SUN5_ENV
- ObtainWriteLock(&afs_xdcache, 246);
- if (!mapForRead) {
- /* track that we have dirty (or dirty-able) pages for this chunk. */
- afs_indexFlags[tdc->index] |= IFDirtyPages;
- }
- afs_indexFlags[tdc->index] |= IFAnyPages;
- ReleaseWriteLock(&afs_xdcache);
-#endif
- afs_BozonUnlock(&avc->pvnLock, avc);
-#ifdef AFS_SUN5_ENV
- afs_PutDCache(tdc);
-#endif
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
- ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
- return 0;
-
- bad:
- AFS_GLOCK();
- afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_LONG, code,
- ICL_TYPE_LONG, (int)page, ICL_TYPE_LONG, Code);
- /* release all pages, drop locks, return code */
-#ifdef AFS_SUN5_ENV
- if (page)
- pvn_read_done(page, B_ERROR);
-#else
- for (i = 0; i < slot; i++)
- PAGE_RELE(pl[i]);
-#endif
- ReleaseReadLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
-#ifdef AFS_SUN5_ENV
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
-#endif
- return code;
-}
-
-#ifdef AFS_SUN5_ENV
-int
-afs_putpage(vp, off, len, flags, cred)
- struct vnode *vp;
- offset_t off;
- u_int len;
- int flags;
- struct AFS_UCRED *cred;
-{
- struct vcache *avc;
- struct page *pages;
- afs_int32 code = 0;
-#if defined(AFS_SUN58_ENV)
- size_t tlen;
-#else
- afs_int32 tlen;
-#endif
- afs_offs_t endPos;
- afs_int32 NPages = 0;
-#if defined(AFS_SUN56_ENV)
- u_offset_t toff = off;
-#else
- int toff = (int)off;
-#endif
- int didWriteLock;
-
- AFS_STATCNT(afs_putpage);
- if (vp->v_flag & VNOMAP) /* file doesn't allow mapping */
- return (ENOSYS);
-
- /*
- * Putpage (ASYNC) is called every sec to flush out dirty vm pages
- */
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER,
- (afs_int32) vp, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(off),
- ICL_TYPE_INT32, (afs_int32) len, ICL_TYPE_LONG, (int)flags);
- avc = VTOAFS(vp);
- afs_BozonLock(&avc->pvnLock, avc);
- ObtainSharedLock(&avc->lock, 247);
- didWriteLock = 0;
-
- /* Get a list of modified (or whatever) pages */
- if (len) {
- endPos = (afs_offs_t) off + len; /* position we're supposed to write up to */
- while ((afs_offs_t) toff < endPos
- && (afs_offs_t) toff < avc->m.Length) {
- /* If not invalidating pages use page_lookup_nowait to avoid reclaiming
- * them from the free list
- */
- AFS_GUNLOCK();
- if (flags & (B_FREE | B_INVAL))
- pages = page_lookup(vp, toff, SE_EXCL);
- else
- pages = page_lookup_nowait(vp, toff, SE_SHARED);
- if (!pages || !pvn_getdirty(pages, flags))
- tlen = PAGESIZE;
- else {
- if (!didWriteLock) {
- AFS_GLOCK();
- didWriteLock = 1;
- UpgradeSToWLock(&avc->lock, 671);
- AFS_GUNLOCK();
- }
- NPages++;
- code = afs_putapage(vp, pages, &toff, &tlen, flags, cred);
- if (code) {
- AFS_GLOCK();
- break;
- }
- }
- toff += tlen;
- AFS_GLOCK();
- }
- } else {
- if (!didWriteLock) {
- UpgradeSToWLock(&avc->lock, 670);
- didWriteLock = 1;
- }
-
- AFS_GUNLOCK();
-#if defined(AFS_SUN56_ENV)
- code = pvn_vplist_dirty(vp, toff, afs_putapage, flags, cred);
-#else
- code = pvn_vplist_dirty(vp, (u_int) off, afs_putapage, flags, cred);
-#endif
- AFS_GLOCK();
- }
-
- if (code && !avc->vc_error) {
- if (!didWriteLock) {
- UpgradeSToWLock(&avc->lock, 669);
- didWriteLock = 1;
- }
- avc->vc_error = code;
- }
-
- if (didWriteLock)
- ReleaseWriteLock(&avc->lock);
- else
- ReleaseSharedLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_LONG, code,
- ICL_TYPE_LONG, NPages);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-int
-afs_putapage(struct vnode *vp, struct page *pages,
-#if defined(AFS_SUN56_ENV)
- u_offset_t * offp,
-#else
- u_int * offp,
-#endif
-#if defined(AFS_SUN58_ENV)
- size_t * lenp,
-#else
- u_int * lenp,
-#endif
- int flags, struct AFS_UCRED *credp)
-{
- struct buf *tbuf;
- struct vcache *avc = VTOAFS(vp);
- afs_int32 code = 0;
- u_int tlen = PAGESIZE;
- afs_offs_t off = (pages->p_offset / PAGESIZE) * PAGESIZE;
-
- /*
- * Now we've got the modified pages. All pages are locked and held
- * XXX Find a kluster that fits in one block (or page). We also
- * adjust the i/o if the file space is less than a while page. XXX
- */
- if (off + tlen > avc->m.Length) {
- tlen = avc->m.Length - off;
- }
- /* can't call mapout with 0 length buffers (rmfree panics) */
- if (((tlen >> 24) & 0xff) == 0xff) {
- tlen = 0;
- }
- if ((int)tlen > 0) {
- /*
- * Can't call mapout with 0 length buffers since we'll get rmfree panics
- */
- tbuf = pageio_setup(pages, tlen, vp, B_WRITE | flags);
- if (!tbuf)
- return (ENOMEM);
-
- tbuf->b_dev = 0;
- tbuf->b_blkno = btodb(pages->p_offset);
- bp_mapin(tbuf);
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUTONE, ICL_TYPE_LONG, avc,
- ICL_TYPE_LONG, pages, ICL_TYPE_LONG, tlen, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(off));
- code = afs_ustrategy(tbuf, credp); /* unlocks page */
- AFS_GUNLOCK();
- bp_mapout(tbuf);
- }
- pvn_write_done(pages, ((code) ? B_ERROR : 0) | B_WRITE | flags);
- if ((int)tlen > 0)
- pageio_done(tbuf);
- if (offp)
- *offp = off;
- if (lenp)
- *lenp = tlen;
- return code;
-}
-
-#else /* AFS_SUN5_ENV */
-
-int
-afs_putpage(vp, off, len, flags, cred)
- struct vnode *vp;
- u_int off;
- u_int len;
- int flags;
- struct AFS_UCRED *cred;
-{
- int wholeEnchilada; /* true if we must get all of the pages */
- struct vcache *avc;
- struct page *pages;
- struct page *tpage;
- struct buf *tbuf;
- afs_int32 tlen;
- afs_int32 code = 0, rcode;
- afs_int32 poffset;
- afs_int32 clusterStart, clusterEnd, endPos;
-
- /* In the wholeEnchilada case, we must ensure that we get all of the pages
- * from the system, since we're doing this to shutdown the use of a vnode */
-
- AFS_STATCNT(afs_putpage);
- wholeEnchilada = (off == 0 && len == 0
- && (flags & (B_INVAL | B_ASYNC)) == B_INVAL);
-
- avc = VTOAFS(vp);
- afs_BozonLock(&avc->pvnLock, avc);
- ObtainWriteLock(&avc->lock, 248);
-
- while (1) {
- /* in whole enchilada case, loop until call to pvn_getdirty can't find
- * any more modified pages */
-
- /* first we try to get a list of modified (or whatever) pages */
- if (len == 0) {
- pages = pvn_vplist_dirty(vp, off, flags);
- } else {
- endPos = off + len; /* position we're supposed to write up to */
- if (endPos > avc->m.Length)
- endPos = avc->m.Length; /* bound by this */
- clusterStart = off & ~(PAGESIZE - 1); /* round down to nearest page */
- clusterEnd = ((endPos - 1) | (PAGESIZE - 1)) + 1; /* round up to nearest page */
- pages =
- pvn_range_dirty(vp, off, endPos, clusterStart, clusterEnd,
- flags);
- }
-
- /* Now we've got the modified pages. All pages are locked and held */
- rcode = 0; /* return code */
- while (pages) { /* look over all pages in the returned set */
- tpage = pages; /* get first page in the list */
-
- /* write out the page */
- poffset = tpage->p_offset; /* where the page starts in the file */
- /* tlen will represent the end of the range to write, for a while */
- tlen = PAGESIZE + poffset; /* basic place to end tpage write */
- /* but we also don't want to write past end of off..off+len range */
- if (len != 0 && tlen > off + len)
- tlen = off + len;
- /* and we don't want to write past the end of the file */
- if (tlen > avc->m.Length)
- tlen = avc->m.Length;
- /* and we don't want to write at all if page starts after end */
- if (poffset >= tlen) {
- pvn_fail(pages, B_WRITE | flags);
- goto done;
- }
- /* finally change tlen from end position to length */
- tlen -= poffset; /* compute bytes to write from this page */
- page_sub(&pages, tpage); /* remove tpage from "pages" list */
- tbuf = pageio_setup(tpage, tlen, vp, B_WRITE | flags);
- if (!tbuf) {
- pvn_fail(tpage, B_WRITE | flags);
- pvn_fail(pages, B_WRITE | flags);
- goto done;
- }
- tbuf->b_dev = 0;
- tbuf->b_blkno = btodb(tpage->p_offset);
- bp_mapin(tbuf);
- ReleaseWriteLock(&avc->lock); /* can't hold during strategy call */
- code = afs_ustrategy(tbuf); /* unlocks page */
- ObtainWriteLock(&avc->lock, 249); /* re-obtain */
- if (code) {
- /* unlocking of tpage is done by afs_ustrategy */
- rcode = code;
- if (pages) /* may have already removed last page */
- pvn_fail(pages, B_WRITE | flags);
- goto done;
- }
- } /* for (tpage=pages....) */
-
- /* see if we've gotten all of the pages in the whole enchilada case */
- if (!wholeEnchilada || !vp->v_pages)
- break;
- } /* while(1) obtaining all pages */
-
- /*
- * If low on chunks, and if writing the last byte of a chunk, try to
- * free some. Note that afs_DoPartialWrite calls osi_SyncVM which now
- * calls afs_putpage, so this is recursion. It stops there because we
- * insist on len being non-zero.
- */
- if (afs_stats_cmperf.cacheCurrDirtyChunks >
- afs_stats_cmperf.cacheMaxDirtyChunks && len != 0
- && AFS_CHUNKOFFSET((off + len)) == 0) {
- struct vrequest treq;
- if (!afs_InitReq(&treq, cred ? cred : u.u_cred)) {
- rcode = afs_DoPartialWrite(avc, &treq); /* XXX */
- }
- }
-
- done:
-
- if (rcode && !avc->vc_error)
- avc->vc_error = rcode;
-
- /* when we're here, we just return code. */
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return rcode;
-}
-
-#endif /* AFS_SUN5_ENV */
-
-int
-afs_nfsrdwr(avc, auio, arw, ioflag, acred)
- register struct vcache *avc;
- struct uio *auio;
- enum uio_rw arw;
- int ioflag;
- struct AFS_UCRED *acred;
-{
- register afs_int32 code;
- afs_int32 code2;
- int counter;
- afs_int32 mode, sflags;
- register char *data;
- struct dcache *dcp, *dcp_newpage;
- afs_size_t fileBase, size;
- afs_size_t pageBase;
- register afs_int32 tsize;
- register afs_int32 pageOffset, extraResid = 0;
- register afs_size_t origLength; /* length when reading/writing started */
- register long appendLength; /* length when this call will finish */
- int created; /* created pages instead of faulting them */
- int lockCode;
- int didFakeOpen, eof;
- struct vrequest treq;
- caddr_t raddr;
- u_int rsize;
-
- AFS_STATCNT(afs_nfsrdwr);
-
- /* can't read or write other things */
- if (vType(avc) != VREG)
- return EISDIR;
-
- if (auio->uio_resid == 0)
- return (0);
-
- afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, (afs_int32) avc,
- ICL_TYPE_LONG, (arw == UIO_WRITE ? 1 : 0), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(auio->uio_offset), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(auio->uio_resid));
-
-#ifndef AFS_64BIT_CLIENT
- if (AfsLargeFileUio(auio)) /* file is larger than 2 GB */
- return (EFBIG);
-#endif
-
-#ifdef AFS_SUN5_ENV
- if (!acred)
- osi_Panic("rdwr: !acred");
-#else
- if (!acred)
- acred = u.u_cred;
-#endif
- if (code = afs_InitReq(&treq, acred))
- return code;
-
- /* It's not really possible to know if a write cause a growth in the
- * cache size, we we wait for a cache drain for any write.
- */
- afs_MaybeWakeupTruncateDaemon();
- while ((arw == UIO_WRITE)
- && (afs_blocksUsed > (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100)) {
- if (afs_blocksUsed - afs_blocksDiscarded >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 1;
- afs_osi_Sleep(&afs_WaitForCacheDrain);
- }
- afs_MaybeFreeDiscardedDCache();
- afs_MaybeWakeupTruncateDaemon();
- }
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- return afs_CheckCode(code, &treq, 45);
-
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, acred); /* hold bozon lock, but not basic vnode lock */
-
- ObtainWriteLock(&avc->lock, 250);
-
- /* adjust parameters when appending files */
- if ((ioflag & IO_APPEND) && arw == UIO_WRITE) {
-#if defined(AFS_SUN56_ENV)
- auio->uio_loffset = 0;
-#endif
- auio->uio_offset = avc->m.Length; /* write at EOF position */
- }
- if (auio->uio_offset < 0 || (auio->uio_offset + auio->uio_resid) < 0) {
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return EINVAL;
- }
-#ifndef AFS_64BIT_CLIENT
- /* file is larger than 2GB */
- if (AfsLargeFileSize(auio->uio_offset, auio->uio_resid)) {
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return EFBIG;
- }
-#endif
-
- didFakeOpen = 0; /* keep track of open so we can do close */
- if (arw == UIO_WRITE) {
- /* do ulimit processing; shrink resid or fail */
-#if defined(AFS_SUN56_ENV)
- if (auio->uio_loffset + auio->afsio_resid > auio->uio_llimit) {
- if (auio->uio_llimit >= auio->uio_llimit) {
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return EFBIG;
- } else {
- /* track # of bytes we should write, but won't because of
- * ulimit; we must add this into the final resid value
- * so caller knows we punted some data.
- */
- extraResid = auio->uio_resid;
- auio->uio_resid = auio->uio_llimit - auio->uio_loffset;
- extraResid -= auio->uio_resid;
- }
- }
-#else
-#ifdef AFS_SUN52_ENV
- if (auio->afsio_offset + auio->afsio_resid > auio->uio_limit) {
- if (auio->afsio_offset >= auio->uio_limit) {
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return EFBIG;
- } else {
- /* track # of bytes we should write, but won't because of
- * ulimit; we must add this into the final resid value
- * so caller knows we punted some data.
- */
- extraResid = auio->uio_resid;
- auio->uio_resid = auio->uio_limit - auio->afsio_offset;
- extraResid -= auio->uio_resid;
- }
- }
-#endif
-#endif /* SUN56 */
- mode = S_WRITE; /* segment map-in mode */
- afs_FakeOpen(avc); /* do this for writes, so data gets put back
- * when we want it to be put back */
- didFakeOpen = 1; /* we'll be doing a fake open */
- /* 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 = auio->afsio_resid + auio->afsio_offset; /* new file size */
- appendLength = size;
- origLength = avc->m.Length;
- if (size > avc->m.Length) {
- afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(size));
- avc->m.Length = size; /* file grew */
- }
- avc->states |= CDirty; /* Set the dirty bit */
- avc->m.Date = osi_Time(); /* Set file date (for ranlib) */
- } else {
- mode = S_READ; /* map-in read-only */
- origLength = avc->m.Length;
- }
-
- if (acred && AFS_NFSXLATORREQ(acred)) {
- if (arw == UIO_READ) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- return EACCES;
- }
- }
-#ifdef AFS_SUN5_ENV
- crhold(acred);
- if (avc->credp) {
- crfree(avc->credp);
- }
- avc->credp = acred;
-#endif
- }
- counter = 0; /* don't call afs_DoPartialWrite first time through. */
- while (1) {
- /* compute the amount of data to move into this block,
- * based on auio->afsio_resid. Note that we copy data in units of
- * MAXBSIZE, not PAGESIZE. This is because segmap_getmap panics if you
- * call it with an offset based on blocks smaller than MAXBSIZE
- * (implying that it should be named BSIZE, since it is clearly both a
- * max and a min). */
- size = auio->afsio_resid; /* transfer size */
- fileBase = auio->afsio_offset; /* start file position for xfr */
- pageBase = fileBase & ~(MAXBSIZE - 1); /* file position of the page */
- pageOffset = fileBase & (MAXBSIZE - 1); /* xfr start's offset within page */
- tsize = MAXBSIZE - pageOffset; /* how much more fits 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 (arw == UIO_READ) { /* we're doing a read operation */
- /* don't read past EOF */
- if (fileBase + tsize > origLength) {
- tsize = origLength - fileBase;
- eof = 1; /* we did hit the EOF */
- if (tsize < 0)
- tsize = 0; /* better safe than sorry */
- }
- sflags = 0;
- } else {
-#ifdef AFS_SUN5_ENV
- /* 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 (counter > 0 && code == 0 && AFS_CHUNKOFFSET(fileBase) == 0) {
- code = afs_DoPartialWrite(avc, &treq);
- if (code)
- break;
- }
-#endif /* AFS_SUN5_ENV */
- /* write case, we ask segmap_release to call putpage. Really, we
- * don't have to do this on every page mapin, but for now we're
- * lazy, and don't modify the rest of AFS to scan for modified
- * pages on a close or other "synchronize with file server"
- * operation. This makes things a little cleaner, but probably
- * hurts performance. */
- sflags = SM_WRITE;
- }
- if (tsize <= 0) {
- code = 0;
- break; /* nothing to transfer, we're done */
- }
-#ifdef AFS_SUN5_ENV
- if (arw == UIO_WRITE)
- avc->states |= CDirty; /* may have been cleared by DoPartialWrite */
-
- /* Before dropping lock, hold the chunk (create it if necessary). This
- * serves two purposes: (1) Ensure Cache Truncate Daemon doesn't try
- * to purge the chunk's pages while we have them locked. This would
- * cause deadlock because we might be waiting for the CTD to free up
- * a chunk. (2) If we're writing past the original EOF, and we're
- * at the base of the chunk, then make sure it exists online
- * before we do the uiomove, since the segmap_release will
- * write out to the chunk, causing it to get fetched if it hasn't
- * been created yet. The code that would otherwise notice that
- * we're fetching a chunk past EOF won't work, since we've
- * already adjusted the file size above.
- */
- ObtainWriteLock(&avc->vlock, 551);
- while (avc->vstates & VPageCleaning) {
- ReleaseWriteLock(&avc->vlock);
- ReleaseWriteLock(&avc->lock);
- afs_osi_Sleep(&avc->vstates);
- ObtainWriteLock(&avc->lock, 334);
- ObtainWriteLock(&avc->vlock, 552);
- }
- ReleaseWriteLock(&avc->vlock);
- {
- afs_size_t toff, tlen;
- dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
- if (!dcp) {
- code = ENOENT;
- break;
- }
- }
-#endif
- ReleaseWriteLock(&avc->lock); /* uiomove may page fault */
- AFS_GUNLOCK();
-#if defined(AFS_SUN56_ENV)
- data = segmap_getmap(segkmap, AFSTOV(avc), (u_offset_t) pageBase);
-#else
- data = segmap_getmap(segkmap, AFSTOV(avc), pageBase);
-#endif
-#ifndef AFS_SUN5_ENV
- code =
- afs_fc2errno(as_fault
- (&kas, data + pageOffset, tsize, F_SOFTLOCK, mode));
- if (code == 0) {
- AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
- as_fault(&kas, data + pageOffset, tsize, F_SOFTUNLOCK, mode);
- code2 = segmap_release(segkmap, data, sflags);
- if (!code)
- code = code2;
- } else {
- (void)segmap_release(segkmap, data, 0);
- }
-#else
-#if defined(AFS_SUN56_ENV)
- raddr = (caddr_t) (((uintptr_t) data + pageOffset) & PAGEMASK);
-#else
- raddr = (caddr_t) (((u_int) data + pageOffset) & PAGEMASK);
-#endif
- rsize =
- (((u_int) data + pageOffset + tsize + PAGEOFFSET) & PAGEMASK) -
- (u_int) raddr;
- if (code == 0) {
- /* if we're doing a write, and we're starting at the rounded
- * down page base, and we're writing enough data to cover all
- * created pages, then we must be writing all of the pages
- * in this MAXBSIZE window that we're creating.
- */
- created = 0;
- if (arw == UIO_WRITE && ((long)raddr == (long)data + pageOffset)
- && tsize >= rsize) {
- /* probably the dcache backing this guy is around, but if
- * not, we can't do this optimization, since we're creating
- * writable pages, which must be backed by a chunk.
- */
- AFS_GLOCK();
- dcp_newpage = afs_FindDCache(avc, pageBase);
- if (dcp_newpage
- && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)) {
- ObtainWriteLock(&avc->lock, 251);
- ObtainWriteLock(&avc->vlock, 576);
- ObtainReadLock(&dcp_newpage->lock);
- if ((avc->activeV == 0)
- && hsame(avc->m.DataVersion, dcp_newpage->f.versionNo)
- && !(dcp_newpage->dflags & (DFFetching))) {
- AFS_GUNLOCK();
- segmap_pagecreate(segkmap, raddr, rsize, 1);
- AFS_GLOCK();
- ObtainWriteLock(&afs_xdcache, 252);
- /* Mark the pages as created and dirty */
- afs_indexFlags[dcp_newpage->index]
- |= (IFAnyPages | IFDirtyPages);
- ReleaseWriteLock(&afs_xdcache);
- created = 1;
- }
- ReleaseReadLock(&dcp_newpage->lock);
- afs_PutDCache(dcp_newpage);
- ReleaseWriteLock(&avc->vlock);
- ReleaseWriteLock(&avc->lock);
- } else if (dcp_newpage)
- afs_PutDCache(dcp_newpage);
- AFS_GUNLOCK();
- }
- if (!created)
- code =
- afs_fc2errno(segmap_fault
- (kas.a_hat, segkmap, raddr, rsize,
- F_SOFTLOCK, mode));
- }
- if (code == 0) {
- AFS_UIOMOVE(data + pageOffset, tsize, arw, auio, code);
- segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTUNLOCK,
- mode);
- }
- if (code == 0) {
- code = segmap_release(segkmap, data, sflags);
- } else {
- (void)segmap_release(segkmap, data, 0);
- }
-#endif /* AFS_SUN5_ENV */
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 253);
-#ifdef AFS_SUN5_ENV
- counter++;
- if (dcp)
- afs_PutDCache(dcp);
-#endif /* AFS_SUN5_ENV */
- if (code)
- break;
- }
- if (didFakeOpen) {
- afs_FakeClose(avc, acred);
- }
-#ifdef AFS_SUN5_ENV
- if (arw == UIO_WRITE && (avc->states & CDirty)) {
- code2 = afs_DoPartialWrite(avc, &treq);
- if (!code)
- code = code2;
- }
-#endif /* AFS_SUN5_ENV */
-
- if (!code && avc->vc_error) {
- code = avc->vc_error;
- }
- ReleaseWriteLock(&avc->lock);
- afs_BozonUnlock(&avc->pvnLock, avc);
- if (!code) {
-#ifdef AFS_SUN53_ENV
- if ((ioflag & FSYNC) && (arw == UIO_WRITE)
- && !AFS_NFSXLATORREQ(acred))
- code = afs_fsync(avc, 0, acred);
-#else
- if ((ioflag & IO_SYNC) && (arw == UIO_WRITE)
- && !AFS_NFSXLATORREQ(acred))
- code = afs_fsync(avc, acred);
-#endif
- }
-#ifdef AFS_SUN52_ENV
- /*
- * If things worked, add in as remaining in request any bytes
- * we didn't write due to file size ulimit.
- */
- if (code == 0 && extraResid > 0)
- auio->uio_resid += extraResid;
-#endif
- return afs_CheckCode(code, &treq, 46);
-}
-
-afs_map(vp, off, as, addr, len, prot, maxprot, flags, cred)
- struct vnode *vp;
- struct as *as;
-#ifdef AFS_SUN5_ENV
- offset_t off;
- caddr_t *addr;
-#else
- u_int off;
- addr_t *addr;
-#endif
- u_int len;
-#ifdef AFS_SUN5_ENV
- u_char prot, maxprot;
-#else
- u_int prot, maxprot;
-#endif
- u_int flags;
- struct AFS_UCRED *cred;
-{
- struct segvn_crargs crargs;
- register afs_int32 code;
- struct vrequest treq;
- register struct vcache *avc = VTOAFS(vp);
-
- AFS_STATCNT(afs_map);
-
-
- /* check for reasonableness on segment bounds; apparently len can be < 0 */
- if (off < 0 || off + len < 0) {
- return (EINVAL);
- }
-#ifndef AFS_64BIT_CLIENT
- if (AfsLargeFileSize(off, len)) { /* file is larger than 2 GB */
- code = EFBIG;
- goto out;
- }
-#endif
-
-#if defined(AFS_SUN5_ENV)
- if (vp->v_flag & VNOMAP) /* File isn't allowed to be mapped */
- return (ENOSYS);
-
- if (vp->v_filocks) /* if locked, disallow mapping */
- return (EAGAIN);
-#endif
- AFS_GLOCK();
- if (code = afs_InitReq(&treq, cred))
- goto out;
-
- if (vp->v_type != VREG) {
- code = ENODEV;
- goto out;
- }
-
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- goto out;
- }
- afs_BozonLock(&avc->pvnLock, avc);
- osi_FlushPages(avc, cred); /* ensure old pages are gone */
- avc->states |= CMAPPED; /* flag cleared at afs_inactive */
- afs_BozonUnlock(&avc->pvnLock, avc);
-
- AFS_GUNLOCK();
-#ifdef AFS_SUN5_ENV
- as_rangelock(as);
-#endif
- if ((flags & MAP_FIXED) == 0) {
-#if defined(AFS_SUN57_ENV)
- map_addr(addr, len, off, 1, flags);
-#elif defined(AFS_SUN56_ENV)
- map_addr(addr, len, off, 1);
-#else
- map_addr(addr, len, (off_t) off, 1);
-#endif
- if (*addr == NULL) {
-#ifdef AFS_SUN5_ENV
- as_rangeunlock(as);
-#endif
- code = ENOMEM;
- goto out1;
- }
- } else
- (void)as_unmap(as, *addr, len); /* unmap old address space use */
- /* setup the create parameter block for the call */
- crargs.vp = AFSTOV(avc);
- crargs.offset = (u_int) off;
- crargs.cred = cred;
- crargs.type = flags & MAP_TYPE;
- crargs.prot = prot;
- crargs.maxprot = maxprot;
- crargs.amp = (struct anon_map *)0;
-#if defined(AFS_SUN5_ENV)
- crargs.flags = flags & ~MAP_TYPE;
-#endif
-
- code = as_map(as, *addr, len, segvn_create, (char *)&crargs);
-#ifdef AFS_SUN5_ENV
- as_rangeunlock(as);
-#endif
- out1:
- AFS_GLOCK();
- code = afs_CheckCode(code, &treq, 47);
- AFS_GUNLOCK();
- return code;
- out:
- code = afs_CheckCode(code, &treq, 48);
- AFS_GUNLOCK();
- return code;
-}
-
-/* Sun 4.0.X-specific code. It computes the number of bytes that need
- to be zeroed at the end of a page by pvn_vptrunc, given that you're
- trying to get vptrunc to truncate a file to alen bytes. The result
- will be passed to pvn_vptrunc by the truncate code */
-#ifndef AFS_SUN5_ENV /* Not good for Solaris */
-afs_PageLeft(alen)
- register afs_int32 alen;
-{
- register afs_int32 nbytes;
-
- AFS_STATCNT(afs_PageLeft);
- nbytes = PAGESIZE - (alen & PAGEOFFSET); /* amount to zap in last page */
- /* now check if we'd zero the entire last page. Don't need to do this
- * since pvn_vptrunc will handle this case properly (it will invalidate
- * this page) */
- if (nbytes == PAGESIZE)
- nbytes = 0;
- if (nbytes < 0)
- nbytes = 0; /* just in case */
- return nbytes;
-}
-#endif
-
-
-/*
- * For Now We use standard local kernel params for AFS system values. Change this
- * at some point.
- */
-#if defined(AFS_SUN5_ENV)
-afs_pathconf(vp, cmd, outdatap, credp)
- register struct AFS_UCRED *credp;
-#else
-afs_cntl(vp, cmd, indatap, outdatap, inflag, outflag)
- int inflag, outflag;
- char *indatap;
-#endif
- struct vnode *vp;
- int cmd;
- u_long *outdatap;
-{
- AFS_STATCNT(afs_cntl);
- switch (cmd) {
- case _PC_LINK_MAX:
- *outdatap = MAXLINK;
- break;
- case _PC_NAME_MAX:
- *outdatap = MAXNAMLEN;
- break;
- case _PC_PATH_MAX:
- *outdatap = MAXPATHLEN;
- break;
- case _PC_CHOWN_RESTRICTED:
- *outdatap = 1;
- break;
- case _PC_NO_TRUNC:
- *outdatap = 1;
- break;
-#if !defined(AFS_SUN5_ENV)
- case _PC_MAX_CANON:
- *outdatap = CANBSIZ;
- break;
- case _PC_VDISABLE:
- *outdatap = VDISABLE;
- break;
- case _PC_PIPE_BUF:
- return EINVAL;
- break;
-#endif
- default:
- return EINVAL;
- }
- return 0;
-}
-
-#endif /* AFS_SUN_ENV */
-
-#if defined(AFS_SUN5_ENV)
-
-afs_ioctl(vnp, com, arg, flag, credp, rvalp)
- struct vnode *vnp;
- int com, arg, flag;
- cred_t *credp;
- int *rvalp;
-{
- return (ENOTTY);
-}
-
-void
-afs_rwlock(vnp, wlock)
- struct vnode *vnp;
- int wlock;
-{
- rw_enter(&(VTOAFS(vnp))->rwlock, (wlock ? RW_WRITER : RW_READER));
-}
-
-
-void
-afs_rwunlock(vnp, wlock)
- struct vnode *vnp;
- int wlock;
-{
- rw_exit(&(VTOAFS(vnp))->rwlock);
-}
-
-
-/* NOT SUPPORTED */
-afs_seek(vnp, ooff, noffp)
- struct vnode *vnp;
- offset_t ooff;
- offset_t *noffp;
-{
- register int code = 0;
-
- if ((*noffp < 0 || *noffp > MAXOFF_T))
- code = EINVAL;
- return code;
-}
-
-int
-afs_frlock(vnp, cmd, ap, flag, off,
-#ifdef AFS_SUN59_ENV
- flkcb,
-#endif
- credp)
- struct vnode *vnp;
- int cmd;
-#if defined(AFS_SUN56_ENV)
- struct flock64 *ap;
-#else
- struct flock *ap;
-#endif
- int flag;
- offset_t off;
-#ifdef AFS_SUN59_ENV
- struct flk_callback *flkcb;
-#endif
- struct AFS_UCRED *credp;
-{
- register afs_int32 code = 0;
- /*
- * Implement based on afs_lockctl
- */
- AFS_GLOCK();
-#ifdef AFS_SUN59_ENV
- if (flkcb)
- afs_warn("Don't know how to deal with flk_callback's!\n");
-#endif
- if ((cmd == F_GETLK) || (cmd == F_O_GETLK) || (cmd == F_SETLK)
- || (cmd == F_SETLKW)) {
-#ifdef AFS_SUN53_ENV
- ap->l_pid = ttoproc(curthread)->p_pid;
- ap->l_sysid = 0;
-#else
- ap->l_pid = ttoproc(curthread)->p_epid;
- ap->l_sysid = ttoproc(curthread)->p_sysid;
-#endif
-
- AFS_GUNLOCK();
-#ifdef AFS_SUN56_ENV
- code = convoff(vnp, ap, 0, off);
-#else
- code = convoff(vnp, ap, 0, (off_t) off);
-#endif
- if (code)
- return code;
- AFS_GLOCK();
- }
-
- code = afs_lockctl(VTOAFS(vnp), ap, cmd, credp);
- AFS_GUNLOCK();
- return code;
-}
-
-
-int
-afs_space(vnp, cmd, ap, flag, off, credp)
- struct vnode *vnp;
- int cmd;
-#if defined(AFS_SUN56_ENV)
- struct flock64 *ap;
-#else
- struct flock *ap;
-#endif
- int flag;
- offset_t off;
- struct AFS_UCRED *credp;
-{
- register afs_int32 code = EINVAL;
- struct vattr vattr;
-
- if ((cmd == F_FREESP)
-#ifdef AFS_SUN56_ENV
- && ((code = convoff(vnp, ap, 0, off)) == 0)) {
-#else
- && ((code = convoff(vnp, ap, 0, (off_t) off)) == 0)) {
-#endif
- AFS_GLOCK();
- if (!ap->l_len) {
- vattr.va_mask = AT_SIZE;
- vattr.va_size = ap->l_start;
- code = afs_setattr(VTOAFS(vnp), &vattr, 0, credp);
- }
- AFS_GUNLOCK();
- }
- return (code);
-}
-
-
-#endif
-
-int
-afs_dump(vp, addr, i1, i2)
- struct vnode *vp;
- caddr_t addr;
- int i1, i2;
-{
- AFS_STATCNT(afs_dump);
- afs_warn("AFS_DUMP. MUST IMPLEMENT THIS!!!\n");
- return EINVAL;
-}
-
-
-/* Nothing fancy here; just compare if vnodes are identical ones */
-afs_cmp(vp1, vp2)
- struct vnode *vp1, *vp2;
-{
- AFS_STATCNT(afs_cmp);
- return (vp1 == vp2);
-}
-
-
-int
-afs_realvp(struct vnode *vp, struct vnode **vpp)
-{
- AFS_STATCNT(afs_realvp);
- return EINVAL;
-}
-
-
-int
-afs_pageio(vp, pp, ui1, ui2, i1, credp)
- struct vnode *vp;
- struct page *pp;
- u_int ui1, ui2;
- int i1;
- struct cred *credp;
-{
- afs_warn("afs_pageio: Not implemented\n");
- return EINVAL;
-}
-
-int
-afs_dumpctl(vp, i
-#ifdef AFS_SUN59_ENV
- , blkp
-#endif
- )
- struct vnode *vp;
- int i;
-#ifdef AFS_SUN59_ENV
- int *blkp;
-#endif
-{
- afs_warn("afs_dumpctl: Not implemented\n");
- return EINVAL;
-}
-
-#ifdef AFS_SUN54_ENV
-extern void
-afs_dispose(vp, p, fl, dn, cr)
- struct vnode *vp;
- struct page *p;
- int fl, dn;
- struct cred *cr;
-{
- fs_dispose(vp, p, fl, dn, cr);
-}
-
-int
-afs_setsecattr(vp, vsecattr, flag, creds)
- struct vnode *vp;
- vsecattr_t *vsecattr;
- int flag;
- struct cred *creds;
-{
- return ENOSYS;
-}
-
-int
-afs_getsecattr(vp, vsecattr, flag, creds)
- struct vnode *vp;
- vsecattr_t *vsecattr;
- int flag;
- struct cred *creds;
-{
- return fs_fab_acl(vp, vsecattr, flag, creds);
-}
-#endif
-
-#ifdef AFS_GLOBAL_SUNLOCK
-extern int gafs_open(), gafs_close(), afs_ioctl(), gafs_access();
-extern int gafs_getattr(), gafs_setattr(), gafs_lookup(), gafs_create();
-extern int gafs_remove(), gafs_link(), gafs_rename(), gafs_mkdir();
-extern int gafs_rmdir(), gafs_readdir(), gafs_fsync(), gafs_symlink();
-extern int gafs_fid(), gafs_readlink(), fs_setfl(), afs_pathconf();
-extern int afs_lockctl();
-extern void gafs_inactive();
-
-struct vnodeops Afs_vnodeops = {
- gafs_open,
- gafs_close,
- afs_vmread,
- afs_vmwrite,
- afs_ioctl,
- fs_setfl,
- gafs_getattr,
- gafs_setattr,
- gafs_access,
- gafs_lookup,
- gafs_create,
- gafs_remove,
- gafs_link,
- gafs_rename,
- gafs_mkdir,
- gafs_rmdir,
- gafs_readdir,
- gafs_symlink,
- gafs_readlink,
- gafs_fsync,
- gafs_inactive,
- gafs_fid,
- afs_rwlock,
- afs_rwunlock,
- afs_seek,
- afs_cmp,
- afs_frlock,
- afs_space,
- afs_realvp,
- afs_getpage,
- afs_putpage,
- afs_map,
- afs_addmap,
- afs_delmap,
- fs_poll,
- afs_dump,
- afs_pathconf,
- afs_pageio,
- afs_dumpctl,
-#ifdef AFS_SUN54_ENV
- afs_dispose,
- afs_setsecattr,
- afs_getsecattr,
-#endif
-#if defined(AFS_SUN56_ENV)
- fs_shrlock,
-#endif
-};
-struct vnodeops *afs_ops = &Afs_vnodeops;
-
-
-
-gafs_open(avcp, aflags, acred)
- register struct vcache **avcp;
- afs_int32 aflags;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_open(avcp, aflags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_close(avc, aflags, count, offset, acred)
- offset_t offset;
- int count;
- register struct vcache *avc;
- afs_int32 aflags;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_close(avc, aflags, count, offset, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_getattr(avc, attrs, flags, acred)
- int flags;
- register struct vcache *avc;
- register struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_getattr(avc, attrs, flags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_setattr(avc, attrs, flags, acred)
- int flags;
- register struct vcache *avc;
- register struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_setattr(avc, attrs, flags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_access(avc, amode, flags, acred)
- int flags;
- register struct vcache *avc;
- register afs_int32 amode;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_access(avc, amode, flags, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_lookup(adp, aname, avcp, pnp, flags, rdir, acred)
- struct pathname *pnp;
- int flags;
- struct vnode *rdir;
- register struct vcache *adp, **avcp;
- char *aname;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_lookup(adp, aname, avcp, pnp, flags, rdir, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_create(adp, aname, attrs, aexcl, amode, avcp, acred)
- register struct vcache *adp;
- char *aname;
- struct vattr *attrs;
- enum vcexcl aexcl;
- int amode;
- struct vcache **avcp;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_create(adp, aname, attrs, aexcl, amode, avcp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-gafs_remove(adp, aname, acred)
- register struct vcache *adp;
- char *aname;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_remove(adp, aname, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-gafs_link(adp, avc, aname, acred)
- register struct vcache *avc;
- register struct vcache *adp;
- char *aname;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_link(adp, avc, aname, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-gafs_rename(aodp, aname1, andp, aname2, acred)
- register struct vcache *aodp, *andp;
- char *aname1, *aname2;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_rename(aodp, aname1, andp, aname2, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-gafs_mkdir(adp, aname, attrs, avcp, acred)
- register struct vcache *adp;
- register struct vcache **avcp;
- char *aname;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_mkdir(adp, aname, attrs, avcp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_rmdir(adp, aname, cdirp, acred)
- struct vnode *cdirp;
- register struct vcache *adp;
- char *aname;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_rmdir(adp, aname, cdirp, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_readdir(avc, auio, acred, eofp)
- int *eofp;
- register struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_readdir(avc, auio, acred, eofp);
- AFS_GUNLOCK();
- return (code);
-}
-
-gafs_symlink(adp, aname, attrs, atargetName, acred)
- register struct vcache *adp;
- register char *atargetName;
- char *aname;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_symlink(adp, aname, attrs, atargetName, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-
-gafs_readlink(avc, auio, acred)
- register struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_readlink(avc, auio, acred);
- AFS_GUNLOCK();
- return (code);
-}
-
-#ifdef AFS_SUN53_ENV
-gafs_fsync(avc, flag, acred)
- int flag;
-#else
-gafs_fsync(avc, acred)
-#endif
- register struct vcache *avc;
- struct AFS_UCRED *acred;
-{
- register int code;
-
- AFS_GLOCK();
-#ifdef AFS_SUN53_ENV
- code = afs_fsync(avc, flag, acred);
-#else
- code = afs_fsync(avc, acred);
-#endif
- AFS_GUNLOCK();
- return (code);
-}
-
-void
-afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
-{
- struct vnode *vp = AFSTOV(avc);
- if (afs_shuttingdown)
- return;
-
- /*
- * In Solaris and HPUX s800 and HP-UX10.0 they actually call us with
- * v_count 1 on last reference!
- */
- mutex_enter(&vp->v_lock);
- if (avc->vrefCount <= 0)
- osi_Panic("afs_inactive : v_count <=0\n");
-
- /*
- * If more than 1 don't unmap the vnode but do decrement the ref count
- */
- vp->v_count--;
- if (vp->v_count > 0) {
- mutex_exit(&vp->v_lock);
- return;
- }
- mutex_exit(&vp->v_lock);
-
- /*
- * Solaris calls VOP_OPEN on exec, but doesn't call VOP_CLOSE when
- * the executable exits. So we clean up the open count here.
- *
- * Only do this for mvstat 0 vnodes: when using fakestat, we can't
- * lose the open count for volume roots (mvstat 2), even though they
- * will get VOP_INACTIVE'd when released by afs_PutFakeStat().
- */
- if (avc->opens > 0 && avc->mvstat == 0 && !(avc->states & CCore))
- avc->opens = avc->execsOrWriters = 0;
-
- afs_InactiveVCache(avc, acred);
-}
-
-void
-gafs_inactive(avc, acred)
- register struct vcache *avc;
- struct AFS_UCRED *acred;
-{
- AFS_GLOCK();
- afs_inactive(avc, acred);
- AFS_GUNLOCK();
-}
-
-
-gafs_fid(avc, fidpp)
- struct vcache *avc;
- struct fid **fidpp;
-{
- register int code;
-
- AFS_GLOCK();
- code = afs_fid(avc, fidpp);
- AFS_GUNLOCK();
- return (code);
-}
-
-#endif /* AFS_GLOBAL_SUNLOCK */
+++ /dev/null
-#error kernel code not supported on SunOS 4 \r
+++ /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
- */
-
-/*
- * User space client specific interface glue
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/UKERNEL/afs_usrops.c,v 1.26 2004/05/10 13:51:16 shadow Exp $");
-
-
-#ifdef UKERNEL
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include <net/if.h>
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs_usrops.h"
-#include "afs/afs_stats.h"
-#include "afs/auth.h"
-#include "afs/cellconfig.h"
-#include "afs/vice.h"
-#include "afs/kautils.h"
-#include "afs/afsutil.h"
-#include "rx/rx_globals.h"
-
-#define VFS 1
-#undef VIRTUE
-#undef VICE
-
-#define CACHEINFOFILE "cacheinfo"
-#define AFSLOGFILE "AFSLog"
-#define DCACHEFILE "CacheItems"
-#define VOLINFOFILE "VolumeItems"
-#define CELLINFOFILE "CellItems"
-#define MAXIPADDRS 64
-
-#ifndef MIN
-#define MIN(A,B) ((A)<(B)?(A):(B))
-#endif
-#ifndef MAX
-#define MAX(A,B) ((A)>(B)?(A):(B))
-#endif
-
-extern int cacheDiskType;
-
-char afs_LclCellName[64];
-
-struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
-int afs_FileFlags[MAX_OSI_FILES];
-int afs_FileOffsets[MAX_OSI_FILES];
-
-#define MAX_CACHE_LOOPS 4
-
-struct usr_vfs afs_RootVfs;
-struct usr_vnode *afs_RootVnode = NULL;
-struct usr_vnode *afs_CurrentDir = NULL;
-
-afs_int32 cacheBlocks; /* Num blocks in cache */
-afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
-afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
-char cacheBaseDir[1024]; /* AFS cache directory */
-char confDir[1024]; /* AFS configuration directory */
-char afs_mountDir[1024]; /* AFS mount point */
-int afs_mountDirLen; /* strlen of AFS mount point */
-char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
-char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
-char fullpn_CellInfoFile[1024]; /* Full pathname of CELLINFOFILE */
-char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
-char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
-char fullpn_VFile[1024]; /* Full pathname of data cache files */
-char *vFileNumber; /* Ptr to number in file pathname */
-char rootVolume[64] = "root.afs"; /* AFS root volume name */
-afs_int32 isHomeCell; /* Is current cell info for home cell */
-int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
-int ownerRWmode = 0600; /* Read/write OK by owner */
-static int nDaemons = 2; /* Number of background daemons */
-static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
-static int dCacheSize = 300; /* # of dcache entries */
-static int vCacheSize = 50; /* # of volume cache entries */
-static int cacheFlags = 0; /* Flags to cache manager */
-static int preallocs = 400; /* Def # of allocated memory blocks */
-int afsd_verbose = 0; /* Are we being chatty? */
-int afsd_debug = 0; /* Are we printing debugging info? */
-int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
-
-#define AFSD_INO_T afs_uint32
-char **pathname_for_V; /* Array of cache file pathnames */
-int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
-int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
-int missing_CellInfoFile = 1;
-struct afs_cacheParams cparams; /* params passed to cache manager */
-struct afsconf_dir *afs_cdir; /* config dir */
-
-static int HandleMTab();
-
-int afs_bufferpages = 100;
-int usr_udpcksum = 0;
-
-usr_key_t afs_global_u_key;
-
-struct usr_proc *afs_global_procp;
-struct usr_ucred *afs_global_ucredp;
-struct usr_sysent usr_sysent[200];
-
-#ifdef AFS_USR_OSF_ENV
-char V = 'V';
-#else /* AFS_USR_OSF_ENV */
-long V = 'V';
-#endif /* AFS_USR_OSF_ENV */
-
-struct usr_ucred afs_osi_cred, *afs_osi_credp;
-usr_mutex_t afs_global_lock;
-usr_thread_t afs_global_owner;
-usr_mutex_t rx_global_lock;
-usr_thread_t rx_global_owner;
-usr_mutex_t osi_inode_lock;
-usr_mutex_t osi_waitq_lock;
-usr_mutex_t osi_authenticate_lock;
-afs_lock_t afs_ftf;
-afs_lock_t osi_flplock;
-afs_lock_t osi_fsplock;
-void *vnodefops;
-
-#ifndef NETSCAPE_NSAPI
-
-/*
- * Mutex and condition variable used to implement sleep
- */
-pthread_mutex_t usr_sleep_mutex;
-pthread_cond_t usr_sleep_cond;
-
-#endif /* !NETSCAPE_NSAPI */
-
-int call_syscall(long, long, long, long, long, long);
-
-
-/*
- * Hash table mapping addresses onto wait structures for
- * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
- */
-typedef struct osi_wait {
- caddr_t addr;
- usr_cond_t cond;
- int flag;
- struct osi_wait *next;
- struct osi_wait *prev;
- time_t expiration;
- struct osi_wait *timedNext;
- struct osi_wait *timedPrev;
-} osi_wait_t;
-
-/*
- * Head of the linked list of available waitq structures.
- */
-osi_wait_t *osi_waithash_avail;
-
-/*
- * List of timed waits, NSAPI does not provide a cond_timed
- * wait, so we need to keep track of the timed waits ourselves and
- * periodically check for expirations
- */
-osi_wait_t *osi_timedwait_head;
-osi_wait_t *osi_timedwait_tail;
-
-struct {
- osi_wait_t *head;
- osi_wait_t *tail;
-} osi_waithash_table[OSI_WAITHASH_SIZE];
-
-/*
- * Never call afs_brelse
- */
-int
-ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
-{
- usr_assert(0);
-}
-
-/*
- * I am not sure what to do with these, they assert for now
- */
-int
-iodone(struct usr_buf *bp)
-{
- usr_assert(0);
-}
-
-struct usr_file *
-getf(int fd)
-{
- usr_assert(0);
-}
-
-/*
- * Every user is a super user
- */
-int
-afs_osi_suser(void *credp)
-{
- return 1;
-}
-
-int
-afs_suser(void *credp)
-{
- return 1;
-}
-
-/*
- * These are no-ops in user space
- */
-
-void
-afs_osi_SetTime(osi_timeval_t * atv)
-{
- return;
-}
-
-/*
- * xflock should never fall through, the only files we know
- * about are AFS files
- */
-int
-usr_flock(void)
-{
- usr_assert(0);
-}
-
-/*
- * ioctl should never fall through, the only files we know
- * about are AFS files
- */
-int
-usr_ioctl(void)
-{
- usr_assert(0);
-}
-
-/*
- * We do not support the inode related system calls
- */
-int
-afs_syscall_icreate(void)
-{
- usr_assert(0);
-}
-
-int
-afs_syscall_iincdec(void)
-{
- usr_assert(0);
-}
-
-int
-afs_syscall_iopen(void)
-{
- usr_assert(0);
-}
-
-int
-afs_syscall_ireadwrite(void)
-{
- usr_assert(0);
-}
-
-/*
- * these routines are referenced in the vfsops structure, but
- * should never get called
- */
-int
-vno_close(void)
-{
- usr_assert(0);
-}
-
-int
-vno_ioctl(void)
-{
- usr_assert(0);
-}
-
-int
-vno_rw(void)
-{
- usr_assert(0);
-}
-
-int
-vno_select(void)
-{
- usr_assert(0);
-}
-
-/*
- * uiomove copies data between kernel buffers and uio buffers
- */
-int
-usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
-{
- int nio;
- int len;
- char *ptr;
- struct iovec *iovp;
-
- nio = uio->uio_iovcnt;
- iovp = uio->uio_iov;
-
- if (nio <= 0)
- return EFAULT;
-
- /*
- * copy the data
- */
- ptr = kbuf;
- while (nio > 0 && n > 0) {
- len = MIN(n, iovp->iov_len);
- if (rw == UIO_READ) {
- memcpy(iovp->iov_base, ptr, len);
- } else {
- memcpy(ptr, iovp->iov_base, len);
- }
- n -= len;
- ptr += len;
- uio->uio_resid -= len;
- uio->uio_offset += len;
- iovp->iov_base = (char *)(iovp->iov_base) + len;
- iovp->iov_len -= len;
- iovp++;
- nio--;
- }
-
- if (n > 0)
- return EFAULT;
- return 0;
-}
-
-/*
- * routines to manage user credentials
- */
-struct usr_ucred *
-usr_crcopy(struct usr_ucred *credp)
-{
- struct usr_ucred *newcredp;
-
- newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
- *newcredp = *credp;
- newcredp->cr_ref = 1;
- return newcredp;
-}
-
-struct usr_ucred *
-usr_crget(void)
-{
- struct usr_ucred *newcredp;
-
- newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
- newcredp->cr_ref = 1;
- return newcredp;
-}
-
-int
-usr_crfree(struct usr_ucred *credp)
-{
- credp->cr_ref--;
- if (credp->cr_ref == 0) {
- afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
- }
-}
-
-int
-usr_crhold(struct usr_ucred *credp)
-{
- credp->cr_ref++;
-}
-
-void
-usr_vattr_null(struct usr_vattr *vap)
-{
- int n;
- char *cp;
-
- n = sizeof(struct usr_vattr);
- cp = (char *)vap;
- while (n--) {
- *cp++ = -1;
- }
-}
-
-/*
- * Initialize the thread specific data used to simulate the
- * kernel environment for each thread. The user structure
- * is stored in the thread specific data.
- */
-void
-uafs_InitThread(void)
-{
- int st;
- struct usr_user *uptr;
-
- /*
- * initialize the thread specific user structure. Use malloc to
- * allocate the data block, so pthread_finish can free the buffer
- * when this thread terminates.
- */
- uptr =
- (struct usr_user *)malloc(sizeof(struct usr_user) +
- sizeof(struct usr_ucred));
- usr_assert(uptr != NULL);
- uptr->u_error = 0;
- uptr->u_prio = 0;
- uptr->u_procp = afs_global_procp;
- uptr->u_cred = (struct usr_ucred *)(uptr + 1);
- *uptr->u_cred = *afs_global_ucredp;
- st = usr_setspecific(afs_global_u_key, (void *)uptr);
- usr_assert(st == 0);
-}
-
-/*
- * routine to get the user structure from the thread specific data.
- * this routine is used to implement the global 'u' structure. Initializes
- * the thread if needed.
- */
-struct usr_user *
-get_user_struct(void)
-{
- struct usr_user *uptr;
- int st;
- st = usr_getspecific(afs_global_u_key, (void **)&uptr);
- usr_assert(st == 0);
- if (uptr == NULL) {
- uafs_InitThread();
- st = usr_getspecific(afs_global_u_key, (void **)&uptr);
- usr_assert(st == 0);
- usr_assert(uptr != NULL);
- }
- return uptr;
-}
-
-/*
- * Hash an address for the waithash table
- */
-#define WAITHASH(X) \
- (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
-
-/*
- * Sleep on an event
- */
-void
-afs_osi_Sleep(void *x)
-{
- int index;
- osi_wait_t *waitp;
- int rxGlockOwner = ISAFS_RXGLOCK();
- int glockOwner = ISAFS_GLOCK();
-
- usr_mutex_lock(&osi_waitq_lock);
- if (glockOwner) {
- AFS_GUNLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGUNLOCK();
- }
- index = WAITHASH(x);
- if (osi_waithash_avail == NULL) {
- waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
- usr_cond_init(&waitp->cond);
- } else {
- waitp = osi_waithash_avail;
- osi_waithash_avail = osi_waithash_avail->next;
- }
- waitp->addr = x;
- waitp->flag = 0;
- DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
- osi_waithash_table[index].tail, next, prev);
- waitp->expiration = 0;
- waitp->timedNext = NULL;
- waitp->timedPrev = NULL;
- while (waitp->flag == 0) {
- usr_cond_wait(&waitp->cond, &osi_waitq_lock);
- }
- DLL_DELETE(waitp, osi_waithash_table[index].head,
- osi_waithash_table[index].tail, next, prev);
- waitp->next = osi_waithash_avail;
- osi_waithash_avail = waitp;
- usr_mutex_unlock(&osi_waitq_lock);
- if (glockOwner) {
- AFS_GLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGLOCK();
- }
-}
-
-int
-afs_osi_SleepSig(void *x)
-{
- afs_osi_Sleep(x);
- return 0;
-}
-
-int
-afs_osi_Wakeup(void *x)
-{
- int index;
- osi_wait_t *waitp;
-
- index = WAITHASH(x);
- usr_mutex_lock(&osi_waitq_lock);
- waitp = osi_waithash_table[index].head;
- while (waitp) {
- if (waitp->addr == x && waitp->flag == 0) {
- waitp->flag = 1;
- usr_cond_signal(&waitp->cond);
- }
- waitp = waitp->next;
- }
- usr_mutex_unlock(&osi_waitq_lock);
-}
-
-int
-afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
-{
- int index;
- osi_wait_t *waitp;
- struct timespec tv;
- int ret;
- int rxGlockOwner = ISAFS_RXGLOCK();
- int glockOwner = ISAFS_GLOCK();
-
- tv.tv_sec = msec / 1000;
- tv.tv_nsec = (msec % 1000) * 1000000;
- if (handle == NULL) {
- if (glockOwner) {
- AFS_GUNLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGUNLOCK();
- }
- usr_thread_sleep(&tv);
- ret = 0;
- if (glockOwner) {
- AFS_GLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGLOCK();
- }
- } else {
- usr_mutex_lock(&osi_waitq_lock);
- if (glockOwner) {
- AFS_GUNLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGUNLOCK();
- }
- index = WAITHASH((caddr_t) handle);
- if (osi_waithash_avail == NULL) {
- waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
- usr_cond_init(&waitp->cond);
- } else {
- waitp = osi_waithash_avail;
- osi_waithash_avail = osi_waithash_avail->next;
- }
- waitp->addr = (caddr_t) handle;
- waitp->flag = 0;
- DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
- osi_waithash_table[index].tail, next, prev);
- tv.tv_sec += time(NULL);
- waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
- DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
- timedNext, timedPrev);
- usr_cond_wait(&waitp->cond, &osi_waitq_lock);
- if (waitp->flag) {
- ret = 2;
- } else {
- ret = 0;
- }
- DLL_DELETE(waitp, osi_waithash_table[index].head,
- osi_waithash_table[index].tail, next, prev);
- DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
- timedPrev);
- waitp->next = osi_waithash_avail;
- osi_waithash_avail = waitp;
- usr_mutex_unlock(&osi_waitq_lock);
- if (glockOwner) {
- AFS_GLOCK();
- }
- if (rxGlockOwner) {
- AFS_RXGLOCK();
- }
- }
- return ret;
-}
-
-void
-afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
-{
- afs_osi_Wakeup(handle);
-}
-
-/*
- * Netscape NSAPI doesn't have a cond_timed_wait, so we need
- * to explicitly signal cond_timed_waits when their timers expire
- */
-int
-afs_osi_CheckTimedWaits(void)
-{
- time_t curTime;
- osi_wait_t *waitp;
-
- curTime = time(NULL);
- usr_mutex_lock(&osi_waitq_lock);
- waitp = osi_timedwait_head;
- while (waitp != NULL) {
- usr_assert(waitp->expiration != 0);
- if (waitp->expiration <= curTime) {
- waitp->flag = 1;
- usr_cond_signal(&waitp->cond);
- }
- waitp = waitp->timedNext;
- }
- usr_mutex_unlock(&osi_waitq_lock);
-}
-
-/*
- * I-node numbers are indeces into a table containing a filename
- * i-node structure and a vnode structure. When we create an i-node,
- * we copy the name into the array and initialize enough of the fields
- * in the inode and vnode structures to get the client to work.
- */
-typedef struct {
- struct usr_inode i_node;
- char *name;
-} osi_file_table_t;
-osi_file_table_t *osi_file_table;
-int n_osi_files = 0;
-int max_osi_files = 0;
-
-/*
- * Allocate a slot in the file table if there is not one there already,
- * copy in the file name and kludge up the vnode and inode structures
- */
-int
-lookupname(char *fnamep, int segflg, int followlink,
- struct usr_vnode **dirvpp, struct usr_vnode **compvpp)
-{
- int i;
- int code;
- struct usr_inode *ip;
- struct usr_vnode *vp;
-
- /*usr_assert(followlink == 0); */
- usr_assert(dirvpp == NULL);
-
- /*
- * Assume relative pathnames refer to files in AFS
- */
- if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
- AFS_GLOCK();
- code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
- AFS_GUNLOCK();
- return code;
- }
-
- usr_mutex_lock(&osi_inode_lock);
-
- for (i = 0; i < n_osi_files; i++) {
- if (strcmp(fnamep, osi_file_table[i].name) == 0) {
- *compvpp = &osi_file_table[i].i_node.i_vnode;
- (*compvpp)->v_count++;
- usr_mutex_unlock(&osi_inode_lock);
- return 0;
- }
- }
-
- if (n_osi_files == max_osi_files) {
- usr_mutex_unlock(&osi_inode_lock);
- return ENOSPC;
- }
-
- osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep) + 1);
- usr_assert(osi_file_table[n_osi_files].name != NULL);
- strcpy(osi_file_table[n_osi_files].name, fnamep);
- ip = &osi_file_table[i].i_node;
- vp = &ip->i_vnode;
- vp->v_data = (caddr_t) ip;
- ip->i_dev = -1;
- n_osi_files++;
- ip->i_number = n_osi_files;
- vp->v_count = 2;
- usr_mutex_unlock(&osi_inode_lock);
- *compvpp = vp;
- return 0;
-}
-
-/*
- * open a file given its i-node number
- */
-void *
-osi_UFSOpen(afs_int32 ino)
-{
- int rc;
- struct osi_file *fp;
- struct stat st;
-
- AFS_ASSERT_GLOCK();
-
- if (ino > n_osi_files) {
- u.u_error = ENOENT;
- return NULL;
- }
-
- AFS_GUNLOCK();
- fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
- usr_assert(fp != NULL);
- fp->fd = open(osi_file_table[ino - 1].name, O_RDWR | O_CREAT, 0);
- if (fp->fd < 0) {
- u.u_error = errno;
- afs_osi_Free((char *)fp, sizeof(struct osi_file));
- AFS_GLOCK();
- return NULL;
- }
- rc = fstat(fp->fd, &st);
- if (rc < 0) {
- u.u_error = errno;
- afs_osi_Free((void *)fp, sizeof(struct osi_file));
- AFS_GLOCK();
- return NULL;
- }
- fp->size = st.st_size;
- fp->offset = 0;
- fp->inum = ino;
- fp->vnode = (struct usr_vnode *)fp;
-
- AFS_GLOCK();
- return fp;
-}
-
-int
-osi_UFSClose(struct osi_file *fp)
-{
- int rc;
-
- AFS_ASSERT_GLOCK();
-
- AFS_GUNLOCK();
- rc = close(fp->fd);
- if (rc < 0) {
- u.u_error = errno;
- afs_osi_Free((void *)fp, sizeof(struct osi_file));
- AFS_GLOCK();
- return -1;
- }
- afs_osi_Free((void *)fp, sizeof(struct osi_file));
- AFS_GLOCK();
- return 0;
-}
-
-int
-osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
-{
- int rc;
-
- AFS_ASSERT_GLOCK();
-
- AFS_GUNLOCK();
- rc = ftruncate(fp->fd, len);
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->size = len;
- AFS_GLOCK();
- return 0;
-}
-
-int
-afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
-{
- int rc, ret;
- int code;
- struct stat st;
-
- AFS_ASSERT_GLOCK();
-
- AFS_GUNLOCK();
- if (offset >= 0) {
- rc = lseek(fp->fd, offset, SEEK_SET);
- } else {
- rc = lseek(fp->fd, fp->offset, SEEK_SET);
- }
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->offset = rc;
- ret = read(fp->fd, buf, len);
- if (ret < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->offset += ret;
- rc = fstat(fp->fd, &st);
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->size = st.st_size;
- AFS_GLOCK();
- return ret;
-}
-
-int
-afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
-{
- int rc, ret;
- int code;
- struct stat st;
-
- AFS_ASSERT_GLOCK();
-
- AFS_GUNLOCK();
- if (offset >= 0) {
- rc = lseek(fp->fd, offset, SEEK_SET);
- } else {
- rc = lseek(fp->fd, fp->offset, SEEK_SET);
- }
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->offset = rc;
- ret = write(fp->fd, buf, len);
- if (ret < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->offset += ret;
- rc = fstat(fp->fd, &st);
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- fp->size = st.st_size;
- AFS_GLOCK();
- return ret;
-}
-
-int
-afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
-{
- int rc;
- struct stat st;
-
- AFS_GUNLOCK();
- rc = fstat(fp->fd, &st);
- if (rc < 0) {
- u.u_error = errno;
- AFS_GLOCK();
- return -1;
- }
- stp->size = st.st_size;
- stp->blksize = st.st_blksize;
- stp->mtime = st.st_mtime;
- stp->atime = st.st_atime;
- AFS_GLOCK();
- return 0;
-}
-
-/*
- * VOP_RDWR routine
- */
-int
-afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
- int flags, struct usr_ucred *credP)
-{
- int rc;
- struct osi_file *fp = (struct osi_file *)vnodeP;
-
- /*
- * We don't support readv/writev.
- */
- usr_assert(uioP->uio_iovcnt == 1);
- usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
-
- if (rw == UIO_WRITE) {
- usr_assert(uioP->uio_fmode == FWRITE);
- rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
- uioP->uio_iov[0].iov_len);
- } else {
- usr_assert(uioP->uio_fmode == FREAD);
- rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
- uioP->uio_iov[0].iov_len);
- }
- if (rc < 0) {
- return u.u_error;
- }
-
- uioP->uio_resid -= rc;
- uioP->uio_offset += rc;
- uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
- uioP->uio_iov[0].iov_len -= rc;
- return 0;
-}
-
-/*
- * Use malloc/free routines with check patterns before and after each block
- */
-
-static char *afs_check_string1 = "UAFS";
-static char *afs_check_string2 = "AFS_OSI_";
-
-void *
-afs_osi_Alloc(size_t size)
-{
- return malloc(size);
-}
-
-void
-afs_osi_Free(void *ptr, size_t size)
-{
- free(ptr);
-}
-
-void
-afs_osi_FreeStr(char *ptr)
-{
- free(ptr);
-}
-
-void *
-osi_AllocLargeSpace(size_t size)
-{
- AFS_STATCNT(osi_AllocLargeSpace);
- return afs_osi_Alloc(size);
-}
-
-void
-osi_FreeLargeSpace(void *ptr)
-{
- AFS_STATCNT(osi_FreeLargeSpace);
- afs_osi_Free(ptr, 0);
-}
-
-void *
-osi_AllocSmallSpace(size_t size)
-{
- AFS_STATCNT(osi_AllocSmallSpace);
- return afs_osi_Alloc(size);
-}
-
-void
-osi_FreeSmallSpace(void *ptr)
-{
- AFS_STATCNT(osi_FreeSmallSpace);
- afs_osi_Free(ptr, 0);
-}
-
-void
-shutdown_osi(void)
-{
- AFS_STATCNT(shutdown_osi);
- return;
-}
-
-void
-shutdown_osinet(void)
-{
- AFS_STATCNT(shutdown_osinet);
- return;
-}
-
-void
-shutdown_osifile(void)
-{
- AFS_STATCNT(shutdown_osifile);
- return;
-}
-
-int
-afs_nfsclient_init(void)
-{
- return 0;
-}
-
-void
-shutdown_nfsclnt(void)
-{
- return;
-}
-
-void
-afs_osi_Invisible(void)
-{
- return;
-}
-
-int
-osi_GetTime(struct timeval *tv)
-{
- gettimeofday(tv, NULL);
- return 0;
-}
-
-int
-osi_SetTime(struct timeval *tv)
-{
- return 0;
-}
-
-int
-osi_Active(struct vcache *avc)
-{
- AFS_STATCNT(osi_Active);
- if (avc->opens > 0)
- return (1);
- return 0;
-}
-
-int
-afs_osi_MapStrategy(int (*aproc) (), struct usr_buf *bp)
-{
- afs_int32 returnCode;
- returnCode = (*aproc) (bp);
- return returnCode;
-}
-
-void
-osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
-{
- ObtainSharedLock(&avc->lock, 555);
- if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0)
- || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
- ReleaseSharedLock(&avc->lock);
- return;
- }
- UpgradeSToWLock(&avc->lock, 565);
- hset(avc->mapDV, avc->m.DataVersion);
- ReleaseWriteLock(&avc->lock);
- return;
-}
-
-void
-osi_FlushText_really(register struct vcache *vp)
-{
- if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
- hset(vp->flushDV, vp->m.DataVersion);
- }
- return;
-}
-
-int
-osi_SyncVM(struct vcache *avc)
-{
- return 0;
-}
-
-void
-osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
-{
- return;
-}
-
-void
-osi_Init(void)
-{
- int i;
- int rc;
- usr_thread_t tid;
-
- /*
- * Allocate the table used to implement psuedo-inodes.
- */
- max_osi_files = cacheFiles + 100;
- osi_file_table = (osi_file_table_t *)
- afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
- usr_assert(osi_file_table != NULL);
-
-#ifndef NETSCAPE_NSAPI
- /*
- * Initialize the mutex and condition variable used to implement
- * time sleeps.
- */
- pthread_mutex_init(&usr_sleep_mutex, NULL);
- pthread_cond_init(&usr_sleep_cond, NULL);
-#endif /* !NETSCAPE_NSAPI */
-
- /*
- * Initialize the hash table used for sleep/wakeup
- */
- for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
- DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
- }
- DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
- osi_waithash_avail = NULL;
-
- /*
- * Initialize the AFS file table
- */
- for (i = 0; i < MAX_OSI_FILES; i++) {
- afs_FileTable[i] = NULL;
- }
-
- /*
- * Initialize the global locks
- */
- usr_mutex_init(&afs_global_lock);
- usr_mutex_init(&rx_global_lock);
- usr_mutex_init(&osi_inode_lock);
- usr_mutex_init(&osi_waitq_lock);
- usr_mutex_init(&osi_authenticate_lock);
-
- /*
- * Initialize the AFS OSI credentials
- */
- afs_osi_cred = *afs_global_ucredp;
- afs_osi_credp = &afs_osi_cred;
-}
-
-/* ParseArgs is now obsolete, being handled by cmd */
-
-/*---------------------------------------------------------------------
- * GetVFileNumber
- *
- * Description:
- * Given the final component of a filename expected to be a data cache file,
- * return the integer corresponding to the file. Note: we reject names that
- * are not a ``V'' followed by an integer. We also reject those names having
- * the right format but lying outside the range [0..cacheFiles-1].
- *
- * Arguments:
- * fname : Char ptr to the filename to parse.
- *
- * Returns:
- * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
- * -1 otherwise.
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * None.
- *------------------------------------------------------------------------*/
-
-int
-GetVFileNumber(char *fname)
-{
- int computedVNumber; /*The computed file number we return */
- int filenameLen; /*Number of chars in filename */
- int currDigit; /*Current digit being processed */
-
- /*
- * The filename must have at least two characters, the first of which must be a ``V''
- * and the second of which cannot be a zero unless the file is exactly two chars long.
- */
- filenameLen = strlen(fname);
- if (filenameLen < 2)
- return (-1);
- if (fname[0] != 'V')
- return (-1);
- if ((filenameLen > 2) && (fname[1] == '0'))
- return (-1);
-
- /*
- * Scan through the characters in the given filename, failing immediately if a non-digit
- * is found.
- */
- for (currDigit = 1; currDigit < filenameLen; currDigit++)
- if (isdigit(fname[currDigit]) == 0)
- return (-1);
-
- /*
- * All relevant characters are digits. Pull out the decimal number they represent.
- * Reject it if it's out of range, otherwise return it.
- */
- computedVNumber = atoi(++fname);
- if (computedVNumber < cacheFiles)
- return (computedVNumber);
- else
- return (-1);
-}
-
-/*---------------------------------------------------------------------
- * CreateCacheFile
- *
- * Description:
- * Given a full pathname for a file we need to create for the workstation AFS
- * cache, go ahead and create the file.
- *
- * Arguments:
- * fname : Full pathname of file to create.
- *
- * Returns:
- * 0 iff the file was created,
- * -1 otherwise.
- *
- * Environment:
- * The given cache file has been found to be missing.
- *
- * Side Effects:
- * As described.
- *------------------------------------------------------------------------*/
-
-int
-CreateCacheFile(char *fname)
-{
- static char rn[] = "CreateCacheFile"; /*Routine name */
- int cfd; /*File descriptor to AFS cache file */
- int closeResult; /*Result of close() */
-
- if (afsd_verbose)
- printf("%s: Creating cache file '%s'\n", rn, fname);
- cfd = open(fname, createAndTrunc, ownerRWmode);
- if (cfd <= 0) {
- printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
- cfd, errno);
- return (-1);
- }
- closeResult = close(cfd);
- if (closeResult) {
- printf
- ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
- rn, fname, errno);
- return (-1);
- }
-
- return (0);
-}
-
-/*---------------------------------------------------------------------
- * SweepAFSCache
- *
- * Description:
- * Sweep through the AFS cache directory, recording the inode number for
- * each valid data cache file there. Also, delete any file that doesn't beint32
- * in the cache directory during this sweep, and remember which of the other
- * residents of this directory were seen. After the sweep, we create any data
- * cache files that were missing.
- *
- * Arguments:
- * vFilesFound : Set to the number of data cache files found.
- *
- * Returns:
- * 0 if everything went well,
- * -1 otherwise.
- *
- * Environment:
- * This routine may be called several times. If the number of data cache files
- * found is less than the global cacheFiles, then the caller will need to call it
- * again to record the inodes of the missing zero-length data cache files created
- * in the previous call.
- *
- * Side Effects:
- * Fills up the global pathname_for_V array, may create and/or
- * delete files as explained above.
- *------------------------------------------------------------------------*/
-
-int
-SweepAFSCache(int *vFilesFound)
-{
- static char rn[] = "SweepAFSCache"; /*Routine name */
- char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
- char *fileToDelete; /*Ptr to last component of above */
- DIR *cdirp; /*Ptr to cache directory structure */
-#undef dirent
- struct dirent *currp; /*Current directory entry */
- int vFileNum; /*Data cache file's associated number */
-
- if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
- if (afsd_debug)
- printf("%s: Memory Cache, no cache sweep done\n", rn);
- *vFilesFound = 0;
- return 0;
- }
-
- if (afsd_debug)
- printf("%s: Opening cache directory '%s'\n", rn, cacheBaseDir);
-
- if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
- printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
- cacheBaseDir);
- return (-1);
- }
- cdirp = opendir(cacheBaseDir);
- if (cdirp == (DIR *) 0) {
- printf("%s: Can't open AFS cache directory, '%s'.\n", rn,
- cacheBaseDir);
- return (-1);
- }
-
- /*
- * Scan the directory entries, remembering data cache file inodes and the existance
- * of other important residents. Delete all files that don't belong here.
- */
- *vFilesFound = 0;
- sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
- fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
-
- for (currp = readdir(cdirp); currp; currp = readdir(cdirp)) {
- if (afsd_debug) {
- printf("%s: Current directory entry:\n", rn);
- printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
- currp->d_reclen, currp->d_name);
- }
-
- /*
- * Guess current entry is for a data cache file.
- */
- vFileNum = GetVFileNumber(currp->d_name);
- if (vFileNum >= 0) {
- /*
- * Found a valid data cache filename. Remember this file's name
- * and bump the number of files found.
- */
- pathname_for_V[vFileNum] =
- afs_osi_Alloc(strlen(currp->d_name) + strlen(cacheBaseDir) +
- 2);
- usr_assert(pathname_for_V[vFileNum] != NULL);
- sprintf(pathname_for_V[vFileNum], "%s/%s", cacheBaseDir,
- currp->d_name);
- (*vFilesFound)++;
- } else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
- /*
- * Found the file holding the dcache entries.
- */
- missing_DCacheFile = 0;
- } else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
- /*
- * Found the file holding the volume info.
- */
- missing_VolInfoFile = 0;
- } else if (strcmp(currp->d_name, CELLINFOFILE) == 0) {
- missing_CellInfoFile = 0;
- } else if ((strcmp(currp->d_name, ".") == 0)
- || (strcmp(currp->d_name, "..") == 0)
- || (strcmp(currp->d_name, "lost+found") == 0)) {
- /*
- * Don't do anything - this file is legit, and is to be left alone.
- */
- } else {
- /*
- * This file doesn't belong in the cache. Nuke it.
- */
- sprintf(fileToDelete, "%s", currp->d_name);
- if (afsd_verbose)
- printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
- if (unlink(fullpn_FileToDelete)) {
- printf("%s: Can't unlink '%s', errno is %d\n", rn,
- fullpn_FileToDelete, errno);
- }
- }
- }
-
- /*
- * Create all the cache files that are missing.
- */
- if (missing_DCacheFile) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n", rn, fullpn_DCacheFile);
- if (CreateCacheFile(fullpn_DCacheFile))
- printf("%s: Can't create '%s'\n", rn, fullpn_DCacheFile);
- }
- if (missing_VolInfoFile) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n", rn, fullpn_VolInfoFile);
- if (CreateCacheFile(fullpn_VolInfoFile))
- printf("%s: Can't create '%s'\n", rn, fullpn_VolInfoFile);
- }
- if (missing_CellInfoFile) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n", rn, fullpn_CellInfoFile);
- if (CreateCacheFile(fullpn_CellInfoFile))
- printf("%s: Can't create '%s'\n", rn, fullpn_CellInfoFile);
- }
-
- if (*vFilesFound < cacheFiles) {
- /*
- * We came up short on the number of data cache files found. Scan through the inode
- * list and create all missing files.
- */
- for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
- if (pathname_for_V[vFileNum] == (AFSD_INO_T) 0) {
- sprintf(vFileNumber, "%d", vFileNum);
- if (afsd_verbose)
- printf("%s: Creating '%s'\n", rn, fullpn_VFile);
- if (CreateCacheFile(fullpn_VFile))
- printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
- }
- }
-
- /*
- * Close the directory, return success.
- */
- if (afsd_debug)
- printf("%s: Closing cache directory.\n", rn);
- closedir(cdirp);
- return (0);
-}
-
-static
-ConfigCell(register struct afsconf_cell *aci, char *arock,
- struct afsconf_dir *adir)
-{
- register int isHomeCell;
- register int i;
- afs_int32 cellFlags = 0;
- afs_int32 hosts[MAXHOSTSPERCELL];
-
- /* figure out if this is the home cell */
- isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
- if (!isHomeCell)
- cellFlags = 2; /* not home, suid is forbidden */
-
- /* build address list */
- for (i = 0; i < MAXHOSTSPERCELL; i++)
- memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
-
- if (aci->linkedCell)
- cellFlags |= 4; /* Flag that linkedCell arg exists,
- * for upwards compatibility */
-
- /* configure one cell */
- call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2, (long)hosts, /* server addresses */
- (long)aci->name, /* cell name */
- (long)cellFlags, /* is this the home cell? */
- (long)aci->linkedCell); /* Linked cell, if any */
- return 0;
-}
-
-static int
-ConfigCellAlias(aca, arock, adir)
- struct afsconf_cellalias *aca;
- char *arock;
- struct afsconf_dir *adir;
-{
- call_syscall(AFSOP_ADDCELLALIAS, (long)aca->aliasName,
- (long)aca->realName, 0, 0, 0);
- return 0;
-}
-
-/*
- * Set the UDP port number RX uses for UDP datagrams
- */
-void
-uafs_SetRxPort(int port)
-{
- usr_assert(usr_rx_port == 0);
- usr_rx_port = port;
-}
-
-
-/*
- * Initialize the user space client.
- */
-void
-uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
- char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
- int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
- int chunkSizeParam, int closeSynchParam, int debugParam,
- int nDaemonsParam, int cacheFlagsParam, char *logFile)
-{
- int st;
- struct usr_proc *procp;
- struct usr_ucred *ucredp;
- int i;
- int rc;
- int currVFile; /* Current AFS cache file number */
- int lookupResult; /* Result of GetLocalCellName() */
- int cacheIteration; /* cache verification loop counter */
- int vFilesFound; /* Num data cache files found in sweep */
- FILE *logfd;
- afs_int32 vfs1_type = -1;
- struct afs_ioctl iob;
- char tbuffer[1024];
- char *p;
- char lastchar;
- afs_int32 buffer[MAXIPADDRS];
- afs_int32 maskbuffer[MAXIPADDRS];
- afs_int32 mtubuffer[MAXIPADDRS];
-
- /*
- * Use the thread specific data to implement the user structure
- */
- usr_keycreate(&afs_global_u_key, free);
-
- /*
- * Initialize the global ucred structure
- */
- afs_global_ucredp = (struct usr_ucred *)
- afs_osi_Alloc(sizeof(struct usr_ucred));
- usr_assert(afs_global_ucredp != NULL);
- afs_global_ucredp->cr_ref = 1;
- afs_global_ucredp->cr_uid = geteuid();
- afs_global_ucredp->cr_gid = getegid();
- afs_global_ucredp->cr_ruid = getuid();
- afs_global_ucredp->cr_rgid = getgid();
- afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
- afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
- st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
- usr_assert(st >= 0);
- afs_global_ucredp->cr_ngroups = (unsigned long)st;
- for (i = st; i < NGROUPS; i++) {
- afs_global_ucredp->cr_groups[i] = NOGROUP;
- }
-
- /*
- * Initialize the global process structure
- */
- afs_global_procp = (struct usr_proc *)
- afs_osi_Alloc(sizeof(struct usr_proc));
- usr_assert(afs_global_procp != NULL);
- afs_global_procp->p_pid = getpid();
- afs_global_procp->p_ppid = (pid_t) 1;
- afs_global_procp->p_ucred = afs_global_ucredp;
-
- /*
- * Initialize the AFS mount point, default is '/afs'.
- * Strip duplicate/trailing slashes from mount point string.
- * afs_mountDirLen is set to strlen(afs_mountDir).
- */
- if (mountDirParam) {
- sprintf(tbuffer, "%s", mountDirParam);
- } else {
- sprintf(tbuffer, "afs");
- }
- afs_mountDir[0] = '/';
- afs_mountDirLen = 1;
- for (lastchar = '/', p = &tbuffer[0]; *p != '\0'; p++) {
- if (lastchar != '/' || *p != '/') {
- afs_mountDir[afs_mountDirLen++] = lastchar = *p;
- }
- }
- if (lastchar == '/' && afs_mountDirLen > 1)
- afs_mountDirLen--;
- afs_mountDir[afs_mountDirLen] = '\0';
- usr_assert(afs_mountDirLen > 1);
-
- /*
- * Initialize cache parameters using the input arguments
- */
-
- cacheBlocks = cacheBlocksParam;
- if (cacheFilesParam != 0) {
- cacheFiles = cacheFilesParam;
- } else {
- cacheFiles = cacheBlocks / 10;
- }
- if (cacheStatEntriesParam != 0) {
- cacheStatEntries = cacheStatEntriesParam;
- }
- strcpy(cacheBaseDir, cacheBaseDirParam);
- if (nDaemons != 0) {
- nDaemons = nDaemonsParam;
- } else {
- nDaemons = 3;
- }
- afsd_verbose = debugParam;
- afsd_debug = debugParam;
- chunkSize = chunkSizeParam;
- if (dCacheSizeParam != 0) {
- dCacheSize = dCacheSizeParam;
- } else {
- dCacheSize = cacheFiles / 2;
- }
- if (vCacheSizeParam != 0) {
- vCacheSize = vCacheSizeParam;
- }
- strcpy(confDir, confDirParam);
- afsd_CloseSynch = closeSynchParam;
- if (cacheFlagsParam >= 0) {
- cacheFlags = cacheFlagsParam;
- }
- if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
- cacheFiles = dCacheSize;
- }
-
- sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
- if (logFile == NULL) {
- sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
- } else {
- strcpy(fullpn_AFSLogFile, logFile);
- }
-
- printf("\n%s: Initializing user space AFS client\n\n", rn);
- printf(" mountDir: %s\n", afs_mountDir);
- printf(" confDir: %s\n", confDir);
- printf(" cacheBaseDir: %s\n", cacheBaseDir);
- printf(" cacheBlocks: %d\n", cacheBlocks);
- printf(" cacheFiles: %d\n", cacheFiles);
- printf(" cacheStatEntries: %d\n", cacheStatEntries);
- printf(" dCacheSize: %d\n", dCacheSize);
- printf(" vCacheSize: %d\n", vCacheSize);
- printf(" chunkSize: %d\n", chunkSize);
- printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
- printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
- printf(" nDaemons: %d\n", nDaemons);
- printf(" cacheFlags: %d\n", cacheFlags);
- printf(" logFile: %s\n", fullpn_AFSLogFile);
- printf("\n");
- fflush(stdout);
-
- /*
- * Initialize the AFS client
- */
- osi_Init();
-
- /*
- * Pull out all the configuration info for the workstation's AFS cache and
- * the cellular community we're willing to let our users see.
- */
- afs_cdir = afsconf_Open(confDir);
- if (!afs_cdir) {
- printf("afsd: some file missing or bad in %s\n", confDir);
- exit(1);
- }
-
- lookupResult =
- afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
- sizeof(afs_LclCellName));
- if (lookupResult) {
- printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
- lookupResult);
- } else {
- if (afsd_verbose)
- printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
- }
-
- /*
- * Set the primary cell name.
- */
- call_syscall(AFSOP_SET_THISCELL, (long)afs_LclCellName, 0, 0, 0, 0);
-
- if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
- if (CreateCacheFile(fullpn_AFSLogFile)) {
- printf
- ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
- rn, fullpn_AFSLogFile);
- exit(1);
- }
- } else
- fclose(logfd);
-
- /*
- * Create and zero the pathname table for the desired cache files.
- */
- pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
- if (pathname_for_V == NULL) {
- printf("%s: malloc() failed for cache file table with %d entries.\n",
- rn, cacheFiles);
- exit(1);
- }
- memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
- if (afsd_debug)
- printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n", rn,
- cacheFiles, pathname_for_V, (cacheFiles * sizeof(AFSD_INO_T)));
-
- /*
- * Set up all the pathnames we'll need for later.
- */
- sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
- sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
- sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
- sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
- vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
-
- /*
- * Start the RX listener.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
- fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE, FALSE, FALSE);
-
- /*
- * Start the RX event handler.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
- fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
-
- /*
- * Set up all the kernel processes needed for AFS.
- */
-
- /* initialize AFS callback interface */
- {
- /* parse multihomed address files */
- char reason[1024];
- st = parseNetFiles(buffer, maskbuffer, mtubuffer, MAXIPADDRS, reason,
- AFSDIR_CLIENT_NETINFO_FILEPATH,
- AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
- if (st > 0)
- call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st,
- (long)(&buffer[0]), (long)(&maskbuffer[0]),
- (long)(&mtubuffer[0]));
- else {
- printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
- reason);
- exit(1);
- }
- }
-
- if (afsd_verbose)
- printf("%s: Forking rx callback listener.\n", rn);
- /* Child */
- if (preallocs < cacheStatEntries + 50)
- preallocs = cacheStatEntries + 50;
- fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
-
- if (afsd_verbose)
- printf("%s: Initializing AFS daemon.\n", rn);
- call_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT, 1, 0, 0, 0);
-
- /*
- * Tell the kernel some basic information about the workstation's cache.
- */
- if (afsd_verbose)
- printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
- " %d optimum cache files, %d blocks in the cache,"
- " flags = 0x%x, dcache entries %d\n", rn, cacheStatEntries,
- cacheFiles, cacheBlocks, cacheFlags, dCacheSize);
- memset(&cparams, 0, sizeof(cparams));
- cparams.cacheScaches = cacheStatEntries;
- cparams.cacheFiles = cacheFiles;
- cparams.cacheBlocks = cacheBlocks;
- cparams.cacheDcaches = dCacheSize;
- cparams.cacheVolumes = vCacheSize;
- cparams.chunkSize = chunkSize;
- cparams.setTimeFlag = FALSE;
- cparams.memCacheFlag = cacheFlags;
- call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
- if (afsd_CloseSynch)
- call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
-
- /*
- * Sweep the workstation AFS cache directory, remembering the inodes of
- * valid files and deleting extraneous files. Keep sweeping until we
- * have the right number of data cache files or we've swept too many
- * times.
- */
- if (afsd_verbose)
- printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
- cacheIteration = 0;
- /* Memory-cache based system doesn't need any of this */
- if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
- do {
- cacheIteration++;
- if (SweepAFSCache(&vFilesFound)) {
- printf("%s: Error on sweep %d of workstation AFS cache \
- directory.\n", rn, cacheIteration);
- exit(1);
- }
- if (afsd_verbose)
- printf
- ("%s: %d out of %d data cache files found in sweep %d.\n",
- rn, vFilesFound, cacheFiles, cacheIteration);
- } while ((vFilesFound < cacheFiles)
- && (cacheIteration < MAX_CACHE_LOOPS));
- } else if (afsd_verbose)
- printf("%s: Using memory cache, not swept\n", rn);
-
- /*
- * Pass the kernel the name of the workstation cache file holding the
- * dcache entries.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
- fullpn_DCacheFile);
- /* once again, meaningless for a memory-based cache. */
- if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
- call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
- 0, 0, 0);
-
- call_syscall(AFSCALL_CALL, AFSOP_CELLINFO, (long)fullpn_CellInfoFile, 0,
- 0, 0);
-
- /*
- * Pass the kernel the name of the workstation cache file holding the
- * volume information.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
- fullpn_VolInfoFile);
- call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO, (long)fullpn_VolInfoFile, 0,
- 0, 0);
-
- /*
- * Pass the kernel the name of the afs logging file holding the volume
- * information.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
- fullpn_AFSLogFile);
- if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
- call_syscall(AFSCALL_CALL, AFSOP_AFSLOG, (long)fullpn_AFSLogFile, 0,
- 0, 0);
-
- /*
- * Tell the kernel about each cell in the configuration.
- */
- afsconf_CellApply(afs_cdir, ConfigCell, NULL);
- afsconf_CellAliasApply(afs_cdir, ConfigCellAlias, NULL);
-
- if (afsd_verbose)
- printf("%s: Forking AFS daemon.\n", rn);
- fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
-
- if (afsd_verbose)
- printf("%s: Forking check server daemon.\n", rn);
- fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
-
- if (afsd_verbose)
- printf("%s: Forking %d background daemons.\n", rn, nDaemons);
- for (i = 0; i < nDaemons; i++) {
- fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
- }
-
- if (afsd_verbose)
- printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn, rootVolume);
- call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
-
- /*
- * Give the kernel the names of the AFS files cached on the workstation's
- * disk.
- */
- if (afsd_debug)
- printf
- ("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
- rn, cacheFiles, cacheBaseDir);
- if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
- for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
- call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
- (long)pathname_for_V[currVFile], 0, 0, 0);
- }
- /*end for */
-#ifndef NETSCAPE_NSAPI
- /*
- * Copy our tokens from the kernel to the user space client
- */
- for (i = 0; i < 200; i++) {
- /*
- * Get the i'th token from the kernel
- */
- memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
- memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
- iob.in = tbuffer;
- iob.in_size = sizeof(int);
- iob.out = tbuffer;
- iob.out_size = sizeof(tbuffer);
-
-#if defined(AFS_USR_SUN5_ENV) || defined(AFS_USR_OSF_ENV) || defined(AFS_USR_HPUX_ENV) || defined(AFS_USR_LINUX22_ENV) || defined(AFS_USR_DARWIN_ENV) || defined(AFS_USR_FBSD_ENV)
- rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
-#elif defined(AFS_USR_SGI_ENV)
- rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
-#else /* AFS_USR_AIX_ENV */
- rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
-#endif
- if (rc < 0) {
- usr_assert(errno == EDOM || errno == ENOSYS);
- break;
- }
-
- /*
- * Now pass the token into the user space kernel
- */
- rc = uafs_SetTokens(tbuffer, iob.out_size);
- usr_assert(rc == 0);
- }
-#endif /* !NETSCAPE_NSAPI */
-
- /*
- * All the necessary info has been passed into the kernel to run an AFS
- * system. Give the kernel our go-ahead.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_GO\n", rn);
- call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
-
- /*
- * At this point, we have finished passing the kernel all the info
- * it needs to set up the AFS. Mount the AFS root.
- */
- printf("%s: All AFS daemons started.\n", rn);
-
- if (afsd_verbose)
- printf("%s: Forking trunc-cache daemon.\n", rn);
- fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
-
- /*
- * Mount the AFS filesystem
- */
- AFS_GLOCK();
- rc = afs_mount(&afs_RootVfs, NULL, NULL);
- usr_assert(rc == 0);
- rc = afs_root(&afs_RootVfs, &afs_RootVnode);
- usr_assert(rc == 0);
- AFS_GUNLOCK();
-
- /*
- * initialize the current directory to the AFS root
- */
- afs_CurrentDir = afs_RootVnode;
- VN_HOLD(afs_CurrentDir);
-
- return;
-}
-
-void
-uafs_Shutdown(void)
-{
- int rc;
-
- printf("\n");
-
- AFS_GLOCK();
- VN_RELE(afs_CurrentDir);
- rc = afs_unmount(&afs_RootVfs);
- usr_assert(rc == 0);
- AFS_GUNLOCK();
-
- printf("\n");
-}
-
-/*
- * Donate the current thread to the RX server pool.
- */
-void
-uafs_RxServerProc(void)
-{
- osi_socket sock;
- int threadID;
- struct rx_call *newcall = NULL;
-
- rxi_MorePackets(2); /* alloc more packets */
- threadID = rxi_availProcs++;
-
- while (1) {
- sock = OSI_NULLSOCKET;
- rxi_ServerProc(threadID, newcall, &sock);
- if (sock == OSI_NULLSOCKET) {
- break;
- }
- newcall = NULL;
- threadID = -1;
- rxi_ListenerProc(sock, &threadID, &newcall);
- /* assert(threadID != -1); */
- /* assert(newcall != NULL); */
- }
-}
-
-struct syscallThreadArgs {
- long syscall;
- long afscall;
- long param1;
- long param2;
- long param3;
- long param4;
-};
-
-#ifdef NETSCAPE_NSAPI
-void
-syscallThread(void *argp)
-#else /* NETSCAPE_NSAPI */
-void *
-syscallThread(void *argp)
-#endif /* NETSCAPE_NSAPI */
-{
- int i;
- struct usr_ucred *crp;
- struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
-
- /*
- * AFS daemons run authenticated
- */
- u.u_viceid = getuid();
- crp = u.u_cred;
- crp->cr_uid = getuid();
- crp->cr_ruid = getuid();
- crp->cr_suid = getuid();
- crp->cr_groups[0] = getgid();
- crp->cr_ngroups = 1;
- for (i = 1; i < NGROUPS; i++) {
- crp->cr_groups[i] = NOGROUP;
- }
-
- call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
- sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
-
- afs_osi_Free(argp, -1);
-}
-
-fork_syscall(syscall, afscall, param1, param2, param3, param4)
- long syscall, afscall, param1, param2, param3, param4;
-{
- usr_thread_t tid;
- struct syscallThreadArgs *sysArgsP;
-
- sysArgsP = (struct syscallThreadArgs *)
- afs_osi_Alloc(sizeof(struct syscallThreadArgs));
- usr_assert(sysArgsP != NULL);
- sysArgsP->syscall = syscall;
- sysArgsP->afscall = afscall;
- sysArgsP->param1 = param1;
- sysArgsP->param2 = param2;
- sysArgsP->param3 = param3;
- sysArgsP->param4 = param4;
-
- usr_thread_create(&tid, syscallThread, sysArgsP);
- usr_thread_detach(tid);
-}
-
-call_syscall(syscall, afscall, param1, param2, param3, param4)
- long syscall, afscall, param1, param2, param3, param4;
-{
- int code = 0;
- struct a {
- long syscall;
- long afscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- } a;
-
- a.syscall = syscall;
- a.afscall = afscall;
- a.parm1 = param1;
- a.parm2 = param2;
- a.parm3 = param3;
- a.parm4 = param4;
-
- u.u_error = 0;
- u.u_ap = (char *)&a;
-
- code = Afs_syscall();
- return code;
-}
-
-int
-uafs_SetTokens(char *tbuffer, int tlen)
-{
- int rc;
- struct afs_ioctl iob;
- char outbuf[1024];
-
- iob.in = tbuffer;
- iob.in_size = tlen;
- iob.out = &outbuf[0];
- iob.out_size = sizeof(outbuf);
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return 0;
-}
-
-int
-uafs_RPCStatsEnableProc(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_ENABLE;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-int
-uafs_RPCStatsDisableProc(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_DISABLE;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-int
-uafs_RPCStatsClearProc(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_CLEAR;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-int
-uafs_RPCStatsEnablePeer(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_ENABLE;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-int
-uafs_RPCStatsDisablePeer(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_DISABLE;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-int
-uafs_RPCStatsClearPeer(void)
-{
- int rc;
- struct afs_ioctl iob;
- afs_int32 flag;
-
- flag = AFSCALL_RXSTATS_CLEAR;
- iob.in = (char *)&flag;
- iob.in_size = sizeof(afs_int32);
- iob.out = NULL;
- iob.out_size = 0;
- rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
- if (rc != 0) {
- errno = rc;
- return -1;
- }
- return rc;
-}
-
-/*
- * Lookup a file or directory given its path.
- * Call VN_HOLD on the output vnode if successful.
- * Returns zero on success, error code on failure.
- *
- * Note: Caller must hold the AFS global lock.
- */
-int
-uafs_LookupName(char *path, struct usr_vnode *parentVp,
- struct usr_vnode **vpp, int follow, int no_eval_mtpt)
-{
- int code;
- int linkCount;
- struct usr_vnode *vp;
- struct usr_vnode *nextVp;
- struct usr_vnode *linkVp;
- char *tmpPath;
- char *pathP;
- char *nextPathP;
-
- AFS_ASSERT_GLOCK();
-
- /*
- * Absolute paths must start with the AFS mount point.
- */
- if (path[0] != '/') {
- vp = parentVp;
- } else {
- path = uafs_afsPathName(path);
- if (path == NULL) {
- return ENOENT;
- }
- vp = afs_RootVnode;
- }
-
- /*
- * Loop through the path looking for the new directory
- */
- tmpPath = afs_osi_Alloc(strlen(path) + 1);
- usr_assert(tmpPath != NULL);
- strcpy(tmpPath, path);
- VN_HOLD(vp);
- pathP = tmpPath;
- while (pathP != NULL && *pathP != '\0') {
- usr_assert(*pathP != '/');
-
- /*
- * terminate the current component and skip over slashes
- */
- nextPathP = afs_strchr(pathP, '/');
- if (nextPathP != NULL) {
- while (*nextPathP == '/') {
- *(nextPathP++) = '\0';
- }
- }
-
- /*
- * Don't call afs_lookup on non-directories
- */
- if (vp->v_type != VDIR) {
- VN_RELE(vp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return ENOTDIR;
- }
-
- if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
- /*
- * The AFS root is its own parent
- */
- nextVp = afs_RootVnode;
- } else {
- /*
- * We need execute permission to search a directory
- */
- code = afs_access(vp, VEXEC, u.u_cred);
- if (code != 0) {
- VN_RELE(vp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return code;
- }
-
- /*
- * lookup the next component in the path, we can release the
- * subdirectory since we hold the global lock
- */
- nextVp = NULL;
-#ifdef AFS_WEB_ENHANCEMENTS
- if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
- code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
- else
- code =
- afs_lookup(vp, pathP, &nextVp, u.u_cred,
- AFS_LOOKUP_NOEVAL);
-#else
- code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
-#endif /* AFS_WEB_ENHANCEMENTS */
- if (code != 0) {
- VN_RELE(vp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return code;
- }
- }
-
- /*
- * Follow symbolic links for parent directories and
- * for leaves when the follow flag is set.
- */
- if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
- linkCount = 0;
- while (nextVp->v_type == VLNK) {
- if (++linkCount > MAX_OSI_LINKS) {
- VN_RELE(vp);
- VN_RELE(nextVp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return code;
- }
- code = uafs_LookupLink(nextVp, vp, &linkVp);
- if (code) {
- VN_RELE(vp);
- VN_RELE(nextVp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return code;
- }
- VN_RELE(nextVp);
- nextVp = linkVp;
- }
- }
-
- VN_RELE(vp);
- vp = nextVp;
- pathP = nextPathP;
- }
-
- /*
- * Special case, nextPathP is non-null if pathname ends in slash
- */
- if (nextPathP != NULL && vp->v_type != VDIR) {
- VN_RELE(vp);
- afs_osi_Free(tmpPath, strlen(path) + 1);
- return ENOTDIR;
- }
-
- afs_osi_Free(tmpPath, strlen(path) + 1);
- *vpp = vp;
- return 0;
-}
-
-/*
- * Lookup the target of a symbolic link
- * Call VN_HOLD on the output vnode if successful.
- * Returns zero on success, error code on failure.
- *
- * Note: Caller must hold the AFS global lock.
- */
-int
-uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
- struct usr_vnode **vpp)
-{
- int code;
- int len;
- char *pathP;
- struct usr_vnode *linkVp;
- struct usr_uio uio;
- struct iovec iov[1];
-
- AFS_ASSERT_GLOCK();
-
- pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
- usr_assert(pathP != NULL);
-
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = pathP;
- iov[0].iov_len = MAX_OSI_PATH + 1;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = 0;
- uio.uio_segflg = 0;
- uio.uio_fmode = FREAD;
- uio.uio_resid = MAX_OSI_PATH + 1;
-
- /*
- * Read the link data
- */
- code = afs_readlink(vp, &uio, u.u_cred);
- if (code) {
- afs_osi_Free(pathP, MAX_OSI_PATH + 1);
- return code;
- }
- len = MAX_OSI_PATH + 1 - uio.uio_resid;
- pathP[len] = '\0';
-
- /*
- * Find the target of the symbolic link
- */
- code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
- if (code) {
- afs_osi_Free(pathP, MAX_OSI_PATH + 1);
- return code;
- }
-
- afs_osi_Free(pathP, MAX_OSI_PATH + 1);
- *vpp = linkVp;
- return 0;
-}
-
-/*
- * Lookup the parent of a file or directory given its path
- * Call VN_HOLD on the output vnode if successful.
- * Returns zero on success, error code on failure.
- *
- * Note: Caller must hold the AFS global lock.
- */
-int
-uafs_LookupParent(char *path, struct usr_vnode **vpp)
-{
- int len;
- int code;
- char *pathP;
- struct usr_vnode *parentP;
-
- AFS_ASSERT_GLOCK();
-
- /*
- * Absolute path names must start with the AFS mount point.
- */
- if (*path == '/') {
- pathP = uafs_afsPathName(path);
- if (pathP == NULL) {
- return ENOENT;
- }
- }
-
- /*
- * Find the length of the parent path
- */
- len = strlen(path);
- while (len > 0 && path[len - 1] == '/') {
- len--;
- }
- if (len == 0) {
- return EINVAL;
- }
- while (len > 0 && path[len - 1] != '/') {
- len--;
- }
- if (len == 0) {
- return EINVAL;
- }
-
- pathP = afs_osi_Alloc(len);
- usr_assert(pathP != NULL);
- memcpy(pathP, path, len - 1);
- pathP[len - 1] = '\0';
-
- /*
- * look up the parent
- */
- code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
- afs_osi_Free(pathP, len);
- if (code != 0) {
- return code;
- }
- if (parentP->v_type != VDIR) {
- VN_RELE(parentP);
- return ENOTDIR;
- }
-
- *vpp = parentP;
- return 0;
-}
-
-/*
- * Return a pointer to the first character in the last component
- * of a pathname
- */
-char *
-uafs_LastPath(char *path)
-{
- int len;
-
- len = strlen(path);
- while (len > 0 && path[len - 1] == '/') {
- len--;
- }
- while (len > 0 && path[len - 1] != '/') {
- len--;
- }
- if (len == 0) {
- return NULL;
- }
- return path + len;
-}
-
-/*
- * Set the working directory.
- */
-int
-uafs_chdir(char *path)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_chdir_r(path);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_chdir_r(char *path)
-{
- int code;
- struct vnode *dirP;
-
- code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
- if (dirP->v_type != VDIR) {
- VN_RELE(dirP);
- errno = ENOTDIR;
- return -1;
- }
- VN_RELE(afs_CurrentDir);
- afs_CurrentDir = dirP;
- return 0;
-}
-
-/*
- * Create a directory.
- */
-int
-uafs_mkdir(char *path, int mode)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_mkdir_r(path, mode);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_mkdir_r(char *path, int mode)
-{
- int code;
- char *nameP;
- struct vnode *parentP;
- struct vnode *dirP;
- struct usr_vattr attrs;
-
- if (uafs_IsRoot(path)) {
- return EACCES;
- }
-
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(path);
- if (nameP != NULL) {
- code = uafs_LookupParent(path, &parentP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- parentP = afs_CurrentDir;
- nameP = path;
- VN_HOLD(parentP);
- }
-
- /*
- * Make sure the directory has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(parentP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Create the directory
- */
- usr_vattr_null(&attrs);
- attrs.va_type = VREG;
- attrs.va_mode = mode;
- attrs.va_uid = u.u_cred->cr_uid;
- attrs.va_gid = u.u_cred->cr_gid;
- dirP = NULL;
- code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
- VN_RELE(parentP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- VN_RELE(dirP);
- return 0;
-}
-
-/*
- * Return 1 if path is the AFS root, otherwise return 0
- */
-int
-uafs_IsRoot(char *path)
-{
- while (*path == '/' && *(path + 1) == '/') {
- path++;
- }
- if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
- return 0;
- }
- path += afs_mountDirLen;
- while (*path == '/') {
- path++;
- }
- if (*path != '\0') {
- return 0;
- }
- return 1;
-}
-
-/*
- * Open a file
- * Note: file name may not end in a slash.
- */
-int
-uafs_open(char *path, int flags, int mode)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_open_r(path, flags, mode);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_open_r(char *path, int flags, int mode)
-{
- int fd;
- int code;
- int openFlags;
- int fileMode;
- struct usr_vnode *fileP;
- struct usr_vnode *dirP;
- struct usr_vattr attrs;
- char *nameP;
-
- if (uafs_IsRoot(path)) {
- fileP = afs_RootVnode;
- VN_HOLD(fileP);
- } else {
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(path);
- if (nameP != NULL) {
- code = uafs_LookupParent(path, &dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- dirP = afs_CurrentDir;
- nameP = path;
- VN_HOLD(dirP);
- }
-
- /*
- * Make sure the filename has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(dirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Get the VNODE for this file
- */
- if (flags & O_CREAT) {
- usr_vattr_null(&attrs);
- attrs.va_type = VREG;
- attrs.va_mode = mode;
- attrs.va_uid = u.u_cred->cr_uid;
- attrs.va_gid = u.u_cred->cr_gid;
- if (flags & O_TRUNC) {
- attrs.va_size = 0;
- }
- fileP = NULL;
- code =
- afs_create(dirP, nameP, &attrs,
- (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
- &fileP, u.u_cred);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- fileP = NULL;
- code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- /*
- * Check whether we have access to this file
- */
- fileMode = 0;
- if (flags & (O_RDONLY | O_RDWR)) {
- fileMode |= VREAD;
- }
- if (flags & (O_WRONLY | O_RDWR)) {
- fileMode |= VWRITE;
- }
- if (!fileMode)
- fileMode = VREAD; /* since O_RDONLY is 0 */
- code = afs_access(fileP, fileMode, u.u_cred);
- if (code != 0) {
- VN_RELE(fileP);
- errno = code;
- return -1;
- }
-
- /*
- * Get the file attributes, all we need is the size
- */
- code = afs_getattr(fileP, &attrs, u.u_cred);
- if (code != 0) {
- VN_RELE(fileP);
- errno = code;
- return -1;
- }
- }
- }
-
- /*
- * Setup the open flags
- */
- openFlags = 0;
- if (flags & O_TRUNC) {
- openFlags |= FTRUNC;
- }
- if (flags & O_APPEND) {
- openFlags |= FAPPEND;
- }
- if (flags & O_SYNC) {
- openFlags |= FSYNC;
- }
- if (flags & O_SYNC) {
- openFlags |= FSYNC;
- }
- if (flags & (O_RDONLY | O_RDWR)) {
- openFlags |= FREAD;
- }
- if (flags & (O_WRONLY | O_RDWR)) {
- openFlags |= FWRITE;
- }
-
- /*
- * Truncate if necessary
- */
- if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
- usr_vattr_null(&attrs);
- attrs.va_size = 0;
- code = afs_setattr(fileP, &attrs, u.u_cred);
- if (code != 0) {
- VN_RELE(fileP);
- errno = code;
- return -1;
- }
- }
-
- /*
- * do the open
- */
- code = afs_open(&fileP, openFlags, u.u_cred);
- if (code != 0) {
- VN_RELE(fileP);
- errno = code;
- return -1;
- }
-
- /*
- * Put the vnode pointer into the file table
- */
- for (fd = 0; fd < MAX_OSI_FILES; fd++) {
- if (afs_FileTable[fd] == NULL) {
- afs_FileTable[fd] = fileP;
- afs_FileFlags[fd] = openFlags;
- if (flags & O_APPEND) {
- afs_FileOffsets[fd] = attrs.va_size;
- } else {
- afs_FileOffsets[fd] = 0;
- }
- break;
- }
- }
- if (fd == MAX_OSI_FILES) {
- VN_RELE(fileP);
- errno = ENFILE;
- return -1;
- }
-
- return fd;
-}
-
-/*
- * Create a file
- */
-int
-uafs_creat(char *path, int mode)
-{
- int rc;
- rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
- return rc;
-}
-
-int
-uafs_creat_r(char *path, int mode)
-{
- int rc;
- rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
- return rc;
-}
-
-/*
- * Write to a file
- */
-int
-uafs_write(int fd, char *buf, int len)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_write_r(fd, buf, len);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_write_r(int fd, char *buf, int len)
-{
- int code;
- struct usr_uio uio;
- struct iovec iov[1];
- struct usr_vnode *fileP;
-
- /*
- * Make sure this is an open file
- */
- fileP = afs_FileTable[fd];
- if (fileP == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = buf;
- iov[0].iov_len = len;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = afs_FileOffsets[fd];
- uio.uio_segflg = 0;
- uio.uio_fmode = FWRITE;
- uio.uio_resid = len;
-
- /*
- * do the write
- */
-
- code = afs_write(fileP, &uio, afs_FileFlags[fd], u.u_cred, 0);
- if (code) {
- errno = code;
- return -1;
- }
-
- afs_FileOffsets[fd] = uio.uio_offset;
- return (len - uio.uio_resid);
-}
-
-/*
- * Read from a file
- */
-int
-uafs_read(int fd, char *buf, int len)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_read_r(fd, buf, len);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_read_r(int fd, char *buf, int len)
-{
- int code;
- struct usr_uio uio;
- struct iovec iov[1];
- struct usr_vnode *fileP;
- struct usr_buf *bufP;
-
- /*
- * Make sure this is an open file
- */
- fileP = afs_FileTable[fd];
- if (fileP == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = buf;
- iov[0].iov_len = len;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = afs_FileOffsets[fd];
- uio.uio_segflg = 0;
- uio.uio_fmode = FREAD;
- uio.uio_resid = len;
-
- /*
- * do the read
- */
- code = afs_read(fileP, &uio, u.u_cred, 0, &bufP, 0);
- if (code) {
- errno = code;
- return -1;
- }
-
- afs_FileOffsets[fd] = uio.uio_offset;
- return (len - uio.uio_resid);
-}
-
-/*
- * Copy the attributes of a file into a stat structure.
- *
- * NOTE: Caller must hold the global AFS lock.
- */
-int
-uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
-{
- int code;
- struct usr_vattr attrs;
-
- AFS_ASSERT_GLOCK();
-
- /*
- * Get the attributes
- */
- code = afs_getattr(vp, &attrs, u.u_cred);
- if (code != 0) {
- return code;
- }
-
- /*
- * Copy the attributes, zero fields that aren't set
- */
- memset((void *)stats, 0, sizeof(struct stat));
- stats->st_dev = -1;
- stats->st_ino = attrs.va_nodeid;
- stats->st_mode = attrs.va_mode;
- stats->st_nlink = attrs.va_nlink;
- stats->st_uid = attrs.va_uid;
- stats->st_gid = attrs.va_gid;
- stats->st_rdev = attrs.va_rdev;
- stats->st_size = attrs.va_size;
- stats->st_atime = attrs.va_atime.tv_sec;
- stats->st_mtime = attrs.va_mtime.tv_sec;
- stats->st_ctime = attrs.va_ctime.tv_sec;
- stats->st_blksize = attrs.va_blocksize;
- stats->st_blocks = attrs.va_blocks;
-
- return 0;
-}
-
-/*
- * Get the attributes of a file, do follow links
- */
-int
-uafs_stat(char *path, struct stat *buf)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_stat_r(path, buf);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_stat_r(char *path, struct stat *buf)
-{
- int code;
- struct vnode *vp;
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
- code = uafs_GetAttr(vp, buf);
- VN_RELE(vp);
- if (code) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * Get the attributes of a file, don't follow links
- */
-int
-uafs_lstat(char *path, struct stat *buf)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_lstat_r(path, buf);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_lstat_r(char *path, struct stat *buf)
-{
- int code;
- struct vnode *vp;
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
- code = uafs_GetAttr(vp, buf);
- VN_RELE(vp);
- if (code) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * Get the attributes of an open file
- */
-int
-uafs_fstat(int fd, struct stat *buf)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_fstat_r(fd, buf);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_fstat_r(int fd, struct stat *buf)
-{
- int code;
- struct vnode *vp;
-
- vp = afs_FileTable[fd];
- if (vp == NULL) {
- errno = EBADF;
- return -1;
- }
- code = uafs_GetAttr(vp, buf);
- VN_RELE(vp);
- if (code) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * change the permissions on a file
- */
-int
-uafs_chmod(char *path, int mode)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_chmod_r(path, mode);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_chmod_r(char *path, int mode)
-{
- int code;
- struct vnode *vp;
- struct usr_vattr attrs;
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
- usr_vattr_null(&attrs);
- attrs.va_mode = mode;
- code = afs_setattr(vp, &attrs, u.u_cred);
- VN_RELE(vp);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * change the permissions on an open file
- */
-int
-uafs_fchmod(int fd, int mode)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_fchmod_r(fd, mode);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_fchmod_r(int fd, int mode)
-{
- int code;
- struct vnode *vp;
- struct usr_vattr attrs;
-
- vp = afs_FileTable[fd];
- if (vp == NULL) {
- errno = EBADF;
- return -1;
- }
- usr_vattr_null(&attrs);
- attrs.va_mode = mode;
- code = afs_setattr(vp, &attrs, u.u_cred);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * truncate a file
- */
-int
-uafs_truncate(char *path, int length)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_truncate_r(path, length);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_truncate_r(char *path, int length)
-{
- int code;
- struct vnode *vp;
- struct usr_vattr attrs;
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
- usr_vattr_null(&attrs);
- attrs.va_size = length;
- code = afs_setattr(vp, &attrs, u.u_cred);
- VN_RELE(vp);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * truncate an open file
- */
-int
-uafs_ftruncate(int fd, int length)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_ftruncate_r(fd, length);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_ftruncate_r(int fd, int length)
-{
- int code;
- struct vnode *vp;
- struct usr_vattr attrs;
-
- vp = afs_FileTable[fd];
- if (vp == NULL) {
- errno = EBADF;
- return -1;
- }
- usr_vattr_null(&attrs);
- attrs.va_size = length;
- code = afs_setattr(vp, &attrs, u.u_cred);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * set the read/write file pointer of an open file
- */
-int
-uafs_lseek(int fd, int offset, int whence)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_lseek_r(fd, offset, whence);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_lseek_r(int fd, int offset, int whence)
-{
- int code;
- int newpos;
- struct usr_vattr attrs;
- struct usr_vnode *vp;
-
- vp = afs_FileTable[fd];
- if (vp == NULL) {
- errno = EBADF;
- return -1;
- }
- switch (whence) {
- case SEEK_CUR:
- newpos = afs_FileOffsets[fd] + offset;
- break;
- case SEEK_SET:
- newpos = offset;
- break;
- case SEEK_END:
- code = afs_getattr(vp, &attrs, u.u_cred);
- if (code != 0) {
- errno = code;
- return -1;
- }
- newpos = attrs.va_size + offset;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
- if (newpos < 0) {
- errno = EINVAL;
- return -1;
- }
- afs_FileOffsets[fd] = newpos;
- return newpos;
-}
-
-/*
- * sync a file
- */
-int
-uafs_fsync(int fd)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_fsync_r(fd);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_fsync_r(int fd)
-{
- int code;
- struct usr_vnode *fileP;
-
-
- fileP = afs_FileTable[fd];
- if (fileP == NULL) {
- errno = EBADF;
- return -1;
- }
-
- code = afs_fsync(fileP, u.u_cred);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Close a file
- */
-int
-uafs_close(int fd)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_close_r(fd);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_close_r(int fd)
-{
- int code;
- struct usr_vnode *fileP;
-
- fileP = afs_FileTable[fd];
- if (fileP == NULL) {
- errno = EBADF;
- return -1;
- }
- afs_FileTable[fd] = NULL;
-
- code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
- VN_RELE(fileP);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Create a hard link from the source to the target
- * Note: file names may not end in a slash.
- */
-int
-uafs_link(char *existing, char *new)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_link_r(existing, new);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_link_r(char *existing, char *new)
-{
- int code;
- struct usr_vnode *existP;
- struct usr_vnode *dirP;
- char *nameP;
-
- if (uafs_IsRoot(new)) {
- return EACCES;
- }
-
- /*
- * Look up the existing node.
- */
- code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(new);
- if (nameP != NULL) {
- code = uafs_LookupParent(new, &dirP);
- if (code != 0) {
- VN_RELE(existP);
- errno = code;
- return -1;
- }
- } else {
- dirP = afs_CurrentDir;
- nameP = new;
- VN_HOLD(dirP);
- }
-
- /*
- * Make sure the filename has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(existP);
- VN_RELE(dirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Create the link
- */
- code = afs_link(existP, dirP, nameP, u.u_cred);
- VN_RELE(existP);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * Create a symbolic link from the source to the target
- * Note: file names may not end in a slash.
- */
-int
-uafs_symlink(char *target, char *source)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_symlink_r(target, source);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_symlink_r(char *target, char *source)
-{
- int code;
- struct usr_vnode *dirP;
- struct usr_vattr attrs;
- char *nameP;
-
- if (uafs_IsRoot(source)) {
- return EACCES;
- }
-
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(source);
- if (nameP != NULL) {
- code = uafs_LookupParent(source, &dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- dirP = afs_CurrentDir;
- nameP = source;
- VN_HOLD(dirP);
- }
-
- /*
- * Make sure the filename has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(dirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Create the link
- */
- usr_vattr_null(&attrs);
- attrs.va_type = VLNK;
- attrs.va_mode = 0777;
- attrs.va_uid = u.u_cred->cr_uid;
- attrs.va_gid = u.u_cred->cr_gid;
- code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- return 0;
-}
-
-/*
- * Read a symbolic link into the buffer
- */
-int
-uafs_readlink(char *path, char *buf, int len)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_readlink_r(path, buf, len);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_readlink_r(char *path, char *buf, int len)
-{
- int code;
- struct usr_vnode *vp;
- struct usr_uio uio;
- struct iovec iov[1];
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- if (vp->v_type != VLNK) {
- VN_RELE(vp);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = buf;
- iov[0].iov_len = len;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = 0;
- uio.uio_segflg = 0;
- uio.uio_fmode = FREAD;
- uio.uio_resid = len;
-
- /*
- * Read the the link
- */
- code = afs_readlink(vp, &uio, u.u_cred);
- VN_RELE(vp);
- if (code) {
- errno = code;
- return -1;
- }
-
- /*
- * return the number of bytes read
- */
- return (len - uio.uio_resid);
-}
-
-/*
- * Remove a file (or directory)
- * Note: file name may not end in a slash.
- */
-int
-uafs_unlink(char *path)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_unlink_r(path);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_unlink_r(char *path)
-{
- int code;
- int openFlags;
- struct usr_vnode *fileP;
- struct usr_vnode *dirP;
- char *nameP;
-
- if (uafs_IsRoot(path)) {
- return EACCES;
- }
-
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(path);
- if (nameP != NULL) {
- code = uafs_LookupParent(path, &dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- dirP = afs_CurrentDir;
- nameP = path;
- VN_HOLD(dirP);
- }
-
- /*
- * Make sure the filename has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(dirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Remove the file
- */
- code = afs_remove(dirP, nameP, u.u_cred);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Rename a file (or directory)
- */
-int
-uafs_rename(char *old, char *new)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_rename_r(old, new);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_rename_r(char *old, char *new)
-{
- int code;
- char *onameP;
- char *nnameP;
- struct usr_vnode *odirP;
- struct usr_vnode *ndirP;
-
- if (uafs_IsRoot(new)) {
- return EACCES;
- }
-
- /*
- * Look up the parent directories.
- */
- onameP = uafs_LastPath(old);
- if (onameP != NULL) {
- code = uafs_LookupParent(old, &odirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- odirP = afs_CurrentDir;
- onameP = old;
- VN_HOLD(odirP);
- }
- nnameP = uafs_LastPath(new);
- if (nnameP != NULL) {
- code = uafs_LookupParent(new, &ndirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- ndirP = afs_CurrentDir;
- nnameP = new;
- VN_HOLD(ndirP);
- }
-
- /*
- * Make sure the filename has at least one character
- */
- if (*onameP == '\0' || *nnameP == '\0') {
- VN_RELE(odirP);
- VN_RELE(ndirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Rename the file
- */
- code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
- VN_RELE(odirP);
- VN_RELE(ndirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Remove a or directory
- * Note: file name may not end in a slash.
- */
-int
-uafs_rmdir(char *path)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_rmdir_r(path);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_rmdir_r(char *path)
-{
- int code;
- int openFlags;
- struct usr_vnode *fileP;
- struct usr_vnode *dirP;
- char *nameP;
-
- if (uafs_IsRoot(path)) {
- return EACCES;
- }
-
- /*
- * Look up the parent directory.
- */
- nameP = uafs_LastPath(path);
- if (nameP != NULL) {
- code = uafs_LookupParent(path, &dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
- } else {
- dirP = afs_CurrentDir;
- nameP = path;
- VN_HOLD(dirP);
- }
-
- /*
- * Make sure the directory name has at least one character
- */
- if (*nameP == '\0') {
- VN_RELE(dirP);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * Remove the directory
- */
- code = afs_rmdir(dirP, nameP, u.u_cred);
- VN_RELE(dirP);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Flush a file from the AFS cache
- */
-int
-uafs_FlushFile(char *path)
-{
- int code;
- struct afs_ioctl iob;
-
- iob.in = NULL;
- iob.in_size = 0;
- iob.out = NULL;
- iob.out_size = 0;
-
- code =
- call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
- 0);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- return 0;
-}
-
-int
-uafs_FlushFile_r(char *path)
-{
- int retval;
- AFS_GUNLOCK();
- retval = uafs_FlushFile(path);
- AFS_GLOCK();
- return retval;
-}
-
-/*
- * open a directory
- */
-usr_DIR *
-uafs_opendir(char *path)
-{
- usr_DIR *retval;
- AFS_GLOCK();
- retval = uafs_opendir_r(path);
- AFS_GUNLOCK();
- return retval;
-}
-
-usr_DIR *
-uafs_opendir_r(char *path)
-{
- usr_DIR *dirp;
- struct usr_vnode *fileP;
- int fd;
-
- /*
- * Open the directory for reading
- */
- fd = uafs_open_r(path, O_RDONLY, 0);
- if (fd < 0) {
- return NULL;
- }
-
- fileP = afs_FileTable[fd];
- if (fileP == NULL) {
- return NULL;
- }
-
- if (fileP->v_type != VDIR) {
- uafs_close_r(fd);
- errno = ENOTDIR;
- return NULL;
- }
-
- /*
- * Set up the directory structures
- */
- dirp =
- (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
- sizeof(struct usr_dirent));
- usr_assert(dirp != NULL);
- dirp->dd_buf = (char *)(dirp + 1);
- dirp->dd_fd = fd;
- dirp->dd_loc = 0;
- dirp->dd_size = 0;
-
- errno = 0;
- return dirp;
-}
-
-/*
- * Read directory entries into a file system independent format.
- * This routine was developed to support AFS cache consistency testing.
- * You should use uafs_readdir instead.
- */
-int
-uafs_getdents(int fd, struct min_direct *buf, int len)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_getdents_r(fd, buf, len);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_getdents_r(int fd, struct min_direct *buf, int len)
-{
- int code;
- struct usr_uio uio;
- struct usr_vnode *vp;
- struct iovec iov[1];
-
- /*
- * Make sure this is an open file
- */
- vp = afs_FileTable[fd];
- if (vp == NULL) {
- AFS_GUNLOCK();
- errno = EBADF;
- return -1;
- }
-
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = (char *)buf;
- iov[0].iov_len = len;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = afs_FileOffsets[fd];
- uio.uio_segflg = 0;
- uio.uio_fmode = FREAD;
- uio.uio_resid = len;
-
- /*
- * read the next chunk from the directory
- */
- code = afs_readdir(vp, &uio, u.u_cred);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- afs_FileOffsets[fd] = uio.uio_offset;
- return (len - uio.uio_resid);
-}
-
-/*
- * read from a directory (names only)
- */
-struct usr_dirent *
-uafs_readdir(usr_DIR * dirp)
-{
- struct usr_dirent *retval;
- AFS_GLOCK();
- retval = uafs_readdir_r(dirp);
- AFS_GUNLOCK();
- return retval;
-}
-
-struct usr_dirent *
-uafs_readdir_r(usr_DIR * dirp)
-{
- int rc;
- int code;
- int len;
- struct usr_uio uio;
- struct usr_vnode *vp;
- struct iovec iov[1];
- struct usr_dirent *direntP;
- struct min_direct *directP;
-
- /*
- * Make sure this is an open file
- */
- vp = afs_FileTable[dirp->dd_fd];
- if (vp == NULL) {
- errno = EBADF;
- return NULL;
- }
-
- /*
- * If there are no entries in the stream buffer
- * then read another chunk
- */
- directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
- if (dirp->dd_size == 0 || directP->d_fileno == 0) {
- /*
- * set up the uio buffer
- */
- iov[0].iov_base = dirp->dd_buf;
- iov[0].iov_len = USR_DIRSIZE;
- uio.uio_iov = &iov[0];
- uio.uio_iovcnt = 1;
- uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
- uio.uio_segflg = 0;
- uio.uio_fmode = FREAD;
- uio.uio_resid = USR_DIRSIZE;
-
- /*
- * read the next chunk from the directory
- */
- code = afs_readdir(vp, &uio, u.u_cred);
- if (code != 0) {
- errno = code;
- return NULL;
- }
- afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
-
- dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
- dirp->dd_loc = 0;
- directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
- }
-
- /*
- * Check for end of file
- */
- if (dirp->dd_size == 0 || directP->d_fileno == 0) {
- errno = 0;
- return NULL;
- }
- len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
- usr_assert(len <= dirp->dd_size);
-
- /*
- * Copy the next entry into the usr_dirent structure and advance
- */
- direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
- direntP->d_ino = directP->d_fileno;
- direntP->d_off = direntP->d_reclen;
- direntP->d_reclen =
- sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
- memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
- direntP->d_name[directP->d_namlen] = '\0';
- dirp->dd_loc += len;
- dirp->dd_size -= len;
-
- return direntP;
-}
-
-/*
- * Close a directory
- */
-int
-uafs_closedir(usr_DIR * dirp)
-{
- int retval;
- AFS_GLOCK();
- retval = uafs_closedir_r(dirp);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_closedir_r(usr_DIR * dirp)
-{
- int fd;
- int rc;
-
- fd = dirp->dd_fd;
- afs_osi_Free((char *)dirp,
- sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
- rc = uafs_close_r(fd);
- return rc;
-}
-
-/*
- * Do AFS authentication
- */
-int
-uafs_klog(char *user, char *cell, char *passwd, char **reason)
-{
- int code;
- afs_int32 password_expires = -1;
-
- usr_mutex_lock(&osi_authenticate_lock);
- code =
- ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
- KA_USERAUTH_DOSETPAG2, user, NULL, cell,
- passwd, 0, &password_expires, 0, reason);
- usr_mutex_unlock(&osi_authenticate_lock);
- return code;
-}
-
-int
-uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
-{
- int retval;
- AFS_GUNLOCK();
- retval = uafs_klog(user, cell, passwd, reason);
- AFS_GLOCK();
- return retval;
-}
-
-/*
- * Destroy AFS credentials from the kernel cache
- */
-int
-uafs_unlog(void)
-{
- int code;
-
- usr_mutex_lock(&osi_authenticate_lock);
- code = ktc_ForgetAllTokens();
- usr_mutex_unlock(&osi_authenticate_lock);
- return code;
-}
-
-int
-uafs_unlog_r(void)
-{
- int retval;
- AFS_GUNLOCK();
- retval = uafs_unlog();
- AFS_GLOCK();
- return retval;
-}
-
-/*
- * Strip the AFS mount point from a pathname string. Return
- * NULL if the path is a relative pathname or if the path
- * doesn't start with the AFS mount point string.
- */
-char *
-uafs_afsPathName(char *path)
-{
- char *p;
- char lastchar;
- int i;
-
- if (path[0] != '/')
- return NULL;
- lastchar = '/';
- for (i = 1, p = path + 1; *p != '\0'; p++) {
- /* Ignore duplicate slashes */
- if (*p == '/' && lastchar == '/')
- continue;
- /* Is this a subdirectory of the AFS mount point? */
- if (afs_mountDir[i] == '\0' && *p == '/') {
- /* strip leading slashes */
- while (*(++p) == '/');
- return p;
- }
- /* Reject paths that are not within AFS */
- if (*p != afs_mountDir[i])
- return NULL;
- lastchar = *p;
- i++;
- }
- /* Is this the AFS mount point? */
- if (afs_mountDir[i] == '\0') {
- usr_assert(*p == '\0');
- return p;
- }
- return NULL;
-}
-
-#ifdef AFS_WEB_ENHANCEMENTS
-/*
- * uafs_klog_nopag
- * klog but don't allocate a new pag
- */
-int
-uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
-{
- int code;
- afs_int32 password_expires = -1;
-
- usr_mutex_lock(&osi_authenticate_lock);
- code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
- /*+KA_USERAUTH_DOSETPAG2 */ , user,
- NULL, cell, passwd, 0,
- &password_expires, 0, reason);
- usr_mutex_unlock(&osi_authenticate_lock);
- return code;
-}
-
-/*
- * uafs_getcellstatus
- * get the cell status
- */
-int
-uafs_getcellstatus(char *cell, afs_int32 * status)
-{
- int rc;
- struct afs_ioctl iob;
-
- iob.in = cell;
- iob.in_size = strlen(cell) + 1;
- iob.out = 0;
- iob.out_size = 0;
-
- rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
- (long)&iob, 0, 0);
-
- if (rc < 0) {
- errno = rc;
- return -1;
- }
-
- *status = (afs_int32) iob.out;
- return 0;
-}
-
-/*
- * uafs_getvolquota
- * Get quota of volume associated with path
- */
-int
-uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
-{
- int rc;
- struct afs_ioctl iob;
- VolumeStatus *status;
- char buf[1024];
-
- iob.in = 0;
- iob.in_size = 0;
- iob.out = buf;
- iob.out_size = 1024;
-
- rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
- 0, 0);
-
- if (rc != 0) {
- errno = rc;
- return -1;
- }
-
- status = (VolumeStatus *) buf;
- *BlocksInUse = status->BlocksInUse;
- *MaxQuota = status->MaxQuota;
- return 0;
-}
-
-/*
- * uafs_setvolquota
- * Set quota of volume associated with path
- */
-int
-uafs_setvolquota(char *path, afs_int32 MaxQuota)
-{
- int rc;
- struct afs_ioctl iob;
- VolumeStatus *status;
- char buf[1024];
-
- iob.in = buf;
- iob.in_size = 1024;
- iob.out = 0;
- iob.out_size = 0;
-
- memset(buf, 0, sizeof(VolumeStatus));
- status = (VolumeStatus *) buf;
- status->MaxQuota = MaxQuota;
- status->MinQuota = -1;
-
- rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
- 0, 0);
-
- if (rc != 0) {
- errno = rc;
- return -1;
- }
-
- return 0;
-}
-
-/*
- * uafs_statmountpoint
- * Determine whether a dir. is a mount point or not
- * return 1 if mount point, 0 if not
- */
-int
-uafs_statmountpoint(char *path)
-{
- int retval;
- int code;
- char buf[256];
-
- AFS_GLOCK();
- retval = uafs_statmountpoint_r(path);
- AFS_GUNLOCK();
- return retval;
-}
-
-int
-uafs_statmountpoint_r(char *path)
-{
- int code;
- struct vnode *vp;
- struct vcache *avc;
- struct vrequest treq;
- int r;
-
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
- if (code != 0) {
- errno = code;
- return -1;
- }
-
- avc = VTOAFS(vp);
-
- r = avc->mvstat;
- VN_RELE(vp);
- return r;
-}
-
-/*
- * uafs_getRights
- * Get a list of rights for the current user on path.
- */
-int
-uafs_getRights(char *path)
-{
- int code, rc;
- struct vnode *vp;
- int afs_rights;
-
- AFS_GLOCK();
- code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
- if (code != 0) {
- errno = code;
- AFS_GUNLOCK();
- return -1;
- }
-
- afs_rights =
- PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
- | PRSFS_LOCK | PRSFS_ADMINISTER;
-
- afs_rights = afs_getRights(vp, afs_rights, u.u_cred);
-
- AFS_GUNLOCK();
- return afs_rights;
-}
-#endif /* AFS_WEB_ENHANCEMENTS */
-
-#endif /* UKERNEL */
+++ /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
- */
-
-#ifndef __AFS_USROPS_H__
-#define __AFS_USROPS_H__ 1
-
-#if !defined(UKERNEL)
-#include <afs/sysincludes.h>
-#endif /* !defined(UKERNEL) */
-
-/*
- * Macros to manipulate doubly linked lists
- */
-#define DLL_INIT_LIST(_HEAD, _TAIL) \
- { _HEAD = NULL ; _TAIL = NULL; }
-
-#define DLL_INSERT_TAIL(_ELEM, _HEAD, _TAIL, _NEXT, _PREV) \
-{ \
- if (_HEAD == NULL) { \
- _ELEM->_NEXT = NULL; \
- _ELEM->_PREV = NULL; \
- _HEAD = _ELEM; \
- _TAIL = _ELEM; \
- } else { \
- _ELEM->_NEXT = NULL; \
- _ELEM->_PREV = _TAIL; \
- _TAIL->_NEXT = _ELEM; \
- _TAIL = _ELEM; \
- } \
-}
-
-#define DLL_DELETE(_ELEM, _HEAD, _TAIL, _NEXT, _PREV) \
-{ \
- if (_ELEM->_NEXT == NULL) { \
- _TAIL = _ELEM->_PREV; \
- } else { \
- _ELEM->_NEXT->_PREV = _ELEM->_PREV; \
- } \
- if (_ELEM->_PREV == NULL) { \
- _HEAD = _ELEM->_NEXT; \
- } else { \
- _ELEM->_PREV->_NEXT = _ELEM->_NEXT; \
- } \
- _ELEM->_NEXT = NULL; \
- _ELEM->_PREV = NULL; \
-}
-
-extern struct afsconf_dir *afs_cdir;
-extern char afs_LclCellName[64];
-
-extern int afs_osicred_Initialized;
-
-extern struct usr_vnode *afs_RootVnode;
-
-extern struct usr_vnode *afs_CurrentDir;
-extern struct usr_vnode *afs_FileTable[];
-extern int afs_FileFlags[];
-extern int afs_FileOffsets[];
-
-extern char afs_mountDir[];
-extern int afs_mountDirLen;
-
-extern void uafs_InitClient(void);
-extern void uafs_InitThread(void);
-extern void uafs_Init(char *, char *, char *, char *, int, int, int, int, int,
- int, int, int, int, int, char *);
-extern void uafs_RxServerProc(void);
-extern int uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentP,
- struct usr_vnode **vpp);
-extern int uafs_LookupName(char *path, struct usr_vnode *parentP,
- struct usr_vnode **vpp, int follow,
- int no_eval_mtpt);
-extern int uafs_LookupParent(char *path, struct usr_vnode **vpp);
-extern int uafs_GetAttr(struct usr_vnode *vp, struct stat *stats);
-
-extern int uafs_SetTokens(char *buf, int len);
-extern int uafs_SetTokens_r(char *buf, int len);
-extern int uafs_mkdir(char *path, int mode);
-extern int uafs_mkdir_r(char *path, int mode);
-extern int uafs_chdir(char *path);
-extern int uafs_chdir_r(char *path);
-extern int uafs_open(char *path, int flags, int mode);
-extern int uafs_open_r(char *path, int flags, int mode);
-extern int uafs_creat(char *path, int mode);
-extern int uafs_creat_r(char *path, int mode);
-extern int uafs_write(int fd, char *buf, int len);
-extern int uafs_write_r(int fd, char *buf, int len);
-extern int uafs_read(int fd, char *buf, int len);
-extern int uafs_read_r(int fd, char *buf, int len);
-extern int uafs_fsync(int fd);
-extern int uafs_fsync_r(int fd);
-extern int uafs_close(int fd);
-extern int uafs_close_r(int fd);
-extern int uafs_stat(char *path, struct stat *stats);
-extern int uafs_stat_r(char *path, struct stat *stats);
-extern int uafs_lstat(char *path, struct stat *stats);
-extern int uafs_lstat_r(char *path, struct stat *stats);
-extern int uafs_fstat(int fd, struct stat *stats);
-extern int uafs_fstat_r(int fd, struct stat *stats);
-extern int uafs_truncate(char *path, int len);
-extern int uafs_truncate_r(char *path, int len);
-extern int uafs_ftruncate(int fd, int len);
-extern int uafs_ftruncate_r(int fd, int len);
-extern int uafs_lseek(int fd, int offset, int whence);
-extern int uafs_lseek_r(int fd, int offset, int whence);
-extern int uafs_chmod(char *path, int mode);
-extern int uafs_chmod_r(char *path, int mode);
-extern int uafs_fchmod(int fd, int mode);
-extern int uafs_fchmod_r(int fd, int mode);
-extern int uafs_symlink(char *target, char *source);
-extern int uafs_symlink_r(char *target, char *source);
-extern int uafs_unlink(char *path);
-extern int uafs_unlink_r(char *path);
-extern int uafs_rmdir(char *path);
-extern int uafs_rmdir_r(char *path);
-extern int uafs_readlink(char *path, char *buf, int len);
-extern int uafs_readlink_r(char *path, char *buf, int len);
-extern int uafs_link(char *existing, char *new);
-extern int uafs_link_r(char *existing, char *new);
-extern int uafs_rename(char *old, char *new);
-extern int uafs_rename_r(char *old, char *new);
-extern int uafs_FlushFile(char *path);
-extern int uafs_FlushFile_r(char *path);
-extern usr_DIR *uafs_opendir(char *path);
-extern usr_DIR *uafs_opendir_r(char *path);
-extern struct usr_dirent *uafs_readdir(usr_DIR * dirp);
-extern struct usr_dirent *uafs_readdir_r(usr_DIR * dirp);
-extern int uafs_getdents(int fd, struct min_direct *buf, int len);
-extern int uafs_getdents_r(int fd, struct min_direct *buf, int len);
-extern int uafs_closedir(usr_DIR * dirp);
-extern int uafs_closedir_r(usr_DIR * dirp);
-extern void uafs_ThisCell(char *namep);
-extern void uafs_ThisCell_r(char *namep);
-extern int uafs_klog(char *user, char *cell, char *passwd, char **reason);
-extern int uafs_klog_r(char *user, char *cell, char *passwd, char **reason);
-extern int uafs_unlog(void);
-extern int uafs_unlog_r(void);
-extern void uafs_SetRxPort(int);
-extern char *uafs_afsPathName(char *);
-extern int uafs_RPCStatsEnableProc(void);
-extern int uafs_RPCStatsDisableProc(void);
-extern int uafs_RPCStatsEnablePeer(void);
-extern int uafs_RPCStatsDisablePeer(void);
-
-#endif /* __AFS_USROPS_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
- */
-
-/* AFS based headers */
-#include "afs/stds.h"
-#include "rx/rx.h"
-#include "afs/afs_osi.h"
-#include "afs/lock.h"
-#include "afs/volerrors.h"
-#include "afs/voldefs.h"
-#include "afsint.h"
-#include "afs/exporter.h"
-#include "vldbint.h"
-#include "afs/afs.h"
-#include "afs/afs_chunkops.h"
-#include "rx/rxkad.h"
-#include "afs/prs_fs.h"
-#include "afs/dir.h"
-#include "afs/afs_axscache.h"
-#include "afs/icl.h"
-#include "afs/afs_stats.h"
-#include "afs/afs_prototypes.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
- */
-
-/*
- * afs_xsetgroups (asserts FALSE)
- * setpag (aliased to use_setpag in sysincludes.h)
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/UKERNEL/osi_groups.c,v 1.7 2003/07/15 23:14:28 shadow Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-
-
-int
-afs_xsetgroups()
-{
- usr_assert(0);
-}
-
-static int
-afs_getgroups(struct AFS_UCRED *cred, gid_t * gidset)
-{
- int ngrps, savengrps;
- gid_t *gp;
-
- AFS_STATCNT(afs_getgroups);
-
- gidset[0] = gidset[1] = 0;
- savengrps = ngrps = cred->cr_ngroups;
- gp = cred->cr_groups;
- while (ngrps--)
- *gidset++ = *gp++;
- return savengrps;
-}
-
-
-
-static int
-afs_setgroups(struct AFS_UCRED **cred, int ngroups, gid_t * gidset,
- int change_parent)
-{
- int ngrps;
- int i;
- gid_t *gp;
-
- AFS_STATCNT(afs_setgroups);
-
- if (ngroups > NGROUPS_MAX)
- return EINVAL;
- if (!change_parent)
- *cred = (struct AFS_UCRED *)crcopy(*cred);
- (*cred)->cr_ngroups = ngroups;
- gp = (*cred)->cr_groups;
- while (ngroups--)
- *gp++ = *gidset++;
- return (0);
-}
-
-int
-usr_setpag(struct usr_ucred **cred, afs_uint32 pagvalue, afs_uint32 * newpag,
- int change_parent)
-{
- gid_t *gidset;
- int ngroups, code;
- int j;
-
- AFS_STATCNT(setpag);
-
- gidset = (gid_t *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- ngroups = afs_getgroups(*cred, gidset);
-
- if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
- /* We will have to shift grouplist to make room for pag */
- if ((sizeof gidset[0]) * (ngroups + 2) > AFS_SMALLOCSIZ) {
- osi_FreeSmallSpace((char *)gidset);
- 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]);
- if ((code = afs_setgroups(cred, ngroups, gidset, change_parent))) {
- osi_FreeSmallSpace((char *)gidset);
- return (code);
- }
- osi_FreeSmallSpace((char *)gidset);
-
- 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
- */
-
-/*
- * Solaris 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 "afs/sysincludes.h"
-
-#define MAX_OSI_PATH 1024
-#define MAX_OSI_FILES 1024
-#define MAX_OSI_LINKS 25
-#define OSI_WAITHASH_SIZE 128 /* must be power of two */
-#define MAX_HOSTADDR 32
-
-#define AFS_UCRED usr_ucred
-
-#define AFS_KALLOC(A) afs_osi_Alloc(A)
-
-/*
- * Time related macros
- */
-#define afs_hz HZ
-#define osi_Time() (time(NULL))
-
-#define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0)
-#define afs_suser suser
-
-/*
- * Global lock support.
- */
-
-extern usr_thread_t afs_global_owner;
-extern usr_mutex_t afs_global_lock;
-
-#define ISAFS_GLOCK() (usr_thread_self() == afs_global_owner)
-
-#define AFS_GLOCK() \
- do { \
- usr_mutex_lock(&afs_global_lock); \
- afs_global_owner = usr_thread_self(); \
- } while(0)
-#define AFS_GUNLOCK() \
- do { \
- AFS_ASSERT_GLOCK(); \
- memset(&afs_global_owner, 0, sizeof(usr_thread_t)); \
- usr_mutex_unlock(&afs_global_lock); \
- } while(0)
-#define AFS_ASSERT_GLOCK() \
- do { if (!ISAFS_GLOCK()) { osi_Panic("afs global lock not held"); } } while(0)
-
-extern int afs_bufferpages;
-
-#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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/UKERNEL/osi_vfsops.c,v 1.10 2003/07/15 23:14:29 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-
-
-int afs_mount();
-int afs_unmount();
-int afs_root();
-int afs_statfs();
-int afs_sync();
-
-struct vfsops Afs_vfsops = {
- afs_mount,
- afs_unmount,
- afs_root,
- afs_statfs,
- afs_sync,
-};
-
-struct vfs *afs_globalVFS = 0;
-struct vcache *afs_globalVp = 0;
-int afs_rootCellIndex = 0;
-
-#if !defined(AFS_USR_AIX_ENV)
-#include "sys/syscall.h"
-#endif
-
-afs_mount(afsp, path, data)
- char *path;
- caddr_t data;
- struct vfs *afsp;
-{
- AFS_STATCNT(afs_mount);
-
- if (afs_globalVFS) {
- /* Don't allow remounts since some system (like AIX) don't handle it well */
- return (setuerror(EBUSY));
- }
- afs_globalVFS = afsp;
- afsp->vfs_bsize = 8192;
- afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
- afsp->vfs_fsid.val[1] = (afs_int32) AFS_VFSFSID;
-
- return 0;
-}
-
-afs_unmount(afsp)
- struct vfs *afsp;
-{
- AFS_STATCNT(afs_unmount);
- afs_globalVFS = 0;
- afs_shutdown();
- return 0;
-}
-
-afs_root(OSI_VFS_ARG(afsp), avpp)
- OSI_VFS_DECL(afsp);
- struct vnode **avpp;
-{
- register afs_int32 code = 0;
- struct vrequest treq;
- register struct vcache *tvp = 0;
- OSI_VFS_CONVERT(afsp)
-
- AFS_STATCNT(afs_root);
- if (afs_globalVp && (afs_globalVp->states & CStatd)) {
- tvp = afs_globalVp;
- } else {
- if (afs_globalVp) {
- afs_PutVCache(afs_globalVp);
- afs_globalVp = NULL;
- }
-
- if (!(code = afs_InitReq(&treq, u.u_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) {
- VN_HOLD(AFSTOV(tvp));
-
- AFSTOV(tvp)->v_flag |= VROOT; /* No-op on Ultrix 2.2 */
- afs_globalVFS = afsp;
- *avpp = AFSTOV(tvp);
- }
-
- afs_Trace3(afs_iclSetp, CM_TRACE_GOPEN, ICL_TYPE_POINTER, *avpp,
- ICL_TYPE_INT32, 0, ICL_TYPE_INT32, code);
- return code;
-}
-
-afs_sync(afsp)
- struct vfs *afsp;
-{
- AFS_STATCNT(afs_sync);
- return 0;
-}
-
-afs_statfs(afsp, abp)
- register struct vfs *afsp;
- struct statfs *abp;
-{
- AFS_STATCNT(afs_statfs);
- abp->f_type = 0;
- abp->f_bsize = afsp->vfs_bsize;
- abp->f_fsid.val[0] = AFS_VFSMAGIC; /* magic */
- abp->f_fsid.val[1] = (afs_int32) AFS_VFSFSID;
- return 0;
-}
-
-afs_mountroot()
-{
- AFS_STATCNT(afs_mountroot);
- return (EINVAL);
-}
-
-afs_swapvp()
-{
- AFS_STATCNT(afs_swapvp);
- return (EINVAL);
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/UKERNEL/osi_vm.c,v 1.7 2003/07/15 23:14:29 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-void
-osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
-{
- return;
-}
-
-int
-osi_VM_FlushVCache(struct vcache *avc, int *slept)
-{
- return 0;
-}
-
-void
-osi_VM_StoreAllSegments(struct vcache *avc)
-{
- return;
-}
-
-void
-osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
-{
- return;
-}
-
-void
-osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
-{
- return;
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/UKERNEL/osi_vnodeops.c,v 1.7 2003/07/15 23:14:29 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-extern int afs_noop();
-extern int afs_badop();
-
-extern int afs_open();
-extern int afs_close();
-extern int afs_getattr();
-extern int afs_setattr();
-extern int afs_access();
-extern int afs_lookup();
-extern int afs_create();
-extern int afs_remove();
-extern int afs_link();
-extern int afs_rename();
-extern int afs_mkdir();
-extern int afs_rmdir();
-extern int afs_readdir();
-extern int afs_symlink();
-extern int afs_readlink();
-extern int afs_fsync();
-extern int afs_lockctl();
-extern int afs_fid();
-
-int
-afs_vrdwr(struct usr_vnode *avc, struct usr_uio *uio, int rw, int io,
- struct usr_ucred *cred)
-{
- int rc;
-
- if (rw == UIO_WRITE) {
- rc = afs_write(avc, uio, io, cred, 0);
- } else {
- rc = afs_read(avc, uio, cred, 0, 0, 0);
- }
-
- return rc;
-}
-
-int
-afs_inactive(struct vcache *avc, struct AFS_UCRED *acred)
-{
- struct vnode *vp = AFSTOV(avc);
- if (afs_shuttingdown)
- return;
-
- usr_assert(avc->vrefCount == 0);
- afs_InactiveVCache(avc, acred);
-}
-
-struct usr_vnodeops Afs_vnodeops = {
- afs_open,
- afs_close,
- afs_vrdwr,
- afs_badop, /* ioctl */
- afs_noop, /* select */
- afs_getattr,
- afs_setattr,
- afs_access,
- afs_lookup,
- afs_create,
- afs_remove,
- afs_link,
- afs_rename,
- afs_mkdir,
- afs_rmdir,
- afs_readdir,
- afs_symlink,
- afs_readlink,
- afs_fsync,
- afs_inactive,
- afs_badop, /* bmap */
- afs_badop, /* strategy */
- afs_badop, /* bread */
- afs_badop, /* brelse */
- afs_lockctl,
- afs_fid
-};
-
-struct usr_vnodeops *afs_ops = &Afs_vnodeops;
+++ /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
- */
-
-#ifndef __AFS_SYSINCLUDESH__
-#define __AFS_SYSINCLUDESH__ 1
-
-#include <stdio.h>
-#if !defined(AFS_USR_DARWIN_ENV) && !defined(AFS_USR_FBSD_ENV) /* must be included after KERNEL undef'd */
-#include <errno.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <setjmp.h>
-
-#ifdef AFS_USR_SUN5_ENV
-#include <signal.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/sockio.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#endif /* AFS_USR_SUN5_ENV */
-
-
-#ifdef AFS_USR_AIX_ENV
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <sys/stropts.h>
-#include <netdb.h>
-#include <sys/timers.h>
-#include <arpa/inet.h>
-#endif /* AFS_USR_AIX_ENV */
-
-#ifdef AFS_USR_SGI_ENV
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/sockio.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#endif /* AFS_USR_SGI_ENV */
-
-#ifdef AFS_USR_HPUX_ENV
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#endif /* AFS_USR_HPUX_ENV */
-
-#ifdef AFS_USR_OSF_ENV
-#ifdef KERNEL
-#undef KERNEL
-#define AFS_USR_UNDEF_KERNEL_ENV 1
-#endif
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#endif /* AFS_USR_OSF_ENV */
-
-#ifdef AFS_USR_LINUX22_ENV
-#include <sys/ioctl.h> /* _IOW() */
-#include <sys/uio.h> /* struct iovec */
-#include <sys/time.h> /* struct timeval */
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#define FREAD 0x0001
-#endif /* AFS_USR_LINUX22_ENV */
-
-#if defined(AFS_USR_DARWIN_ENV) || defined(AFS_USR_FBSD_ENV)
-#ifdef KERNEL
-#undef KERNEL
-#define AFS_USR_UNDEF_KERNEL_ENV 1
-#endif
-#include <errno.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#ifndef O_SYNC
-#define O_SYNC O_FSYNC
-#endif
-#endif /* AFS_USR_DARWIN_ENV || AFS_USR_FBSD_ENV */
-
-#ifdef AFS_AFSDB_ENV
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif /* AFS_AFSDB_ENV */
-
-/* glibc 2.2 has pthread_attr_setstacksize */
-#if (defined(AFS_LINUX22_ENV) && !defined(AFS_USR_LINUX22_ENV)) || (defined(AFS_USR_LINUX22_ENV) && (__GLIBC_MINOR__ < 2))
-#define pthread_attr_setstacksize(a,b) 0
-#endif
-
-#include <sys/stat.h> /* afs_usrops.h uses struct stat in prototypes */
-
-#ifdef NETSCAPE_NSAPI
-
-#include <nsapi.h>
-
-#else /* NETSCAPE_NSAPI */
-
-#include <pthread.h>
-
-#endif /* NETSCAPE_NSAPI */
-
-#ifdef AFS_USR_UNDEF_KERNEL_ENV
-#undef AFS_USR_UNDEF_KERNEL_ENV
-#define KERNEL 1
-#endif
-
-/*
- * User space versions of kernel data structures.
- */
-
-#ifndef MAXNAMLEN
-#define MAXNAMLEN 512
-#endif
-
-#ifndef PAGESIZE
-#define PAGESIZE 4096
-#endif
-
-/*
- * This file contains data types and definitions for running
- * the AFS client in user space. Kernel data structures
- * are renamed from XXXX to usr_XXXX.
- */
-
-#ifdef UKERNEL
-
-#ifdef AFS_USR_SGI_ENV
-#undef socket
-#endif /* AFS_USR_SGI_ENV */
-
-#if defined(AFS_USR_DARWIN_ENV) || defined(AFS_USR_FBSD_ENV)
-#undef if_mtu
-#undef if_metric
-#endif
-
-#define mount usr_mount
-#define fs usr_fs
-#define uio usr_uio
-#define fileops usr_fileops
-#define vnodeops usr_vnodeops
-#define vnode usr_vnode
-#define inode usr_inode
-#define whymountroot_t usr_whymountroot_t
-#define vfsops usr_vfsops
-#define vfs usr_vfs
-#define vattr usr_vattr
-#define buf usr_buf
-#define statfs usr_statfs
-#define ucred usr_ucred
-#define user usr_user
-#define proc usr_proc
-#define file usr_file
-#define dirent usr_dirent
-#define flock usr_flock
-#define fid usr_fid
-#define sysent usr_sysent
-#define in_ifaddr usr_in_ifaddr
-#define ifaddr usr_ifaddr
-#define ifnet usr_ifnet
-#define socket usr_socket
-#define crget usr_crget
-#define crcopy usr_crcopy
-#define crhold usr_crhold
-#define crfree usr_crfree
-#define vtype_t usr_vtype_t
-#define vcexcl usr_vcexcl
-#define m_free usr_m_free
-#define m_freem usr_m_freem
-#define m_adj usr_m_adj
-#define m_pullup usr_m_pullup
-#define uiomove usr_uiomove
-#define EXCL usr_EXCL
-#define NONEXCL usr_NONEXCL
-#define uio_rw usr_uio_rw
-#ifdef ino_t
-#undef ino_t
-#endif
-#define ino_t usr_ino_t
-#define offset_t usr_offset_t
-#define getpid() usr_getpid()
-#define setpag(A,B,C,D) usr_setpag((A),(B),(C),(D))
-#ifdef pid_t
-#undef pid_t
-#endif
-#define pid_t int
-
-enum usr_vcexcl { usr_NONEXCL, usr_EXCL };
-typedef long offset_t;
-#ifdef AFS_USR_OSF_ENV
-typedef int usr_ino_t;
-#else /* AFS_USR_OSF_ENV */
-typedef long usr_ino_t;
-#endif /* AFS_USR_OSF_ENV */
-
-#if defined(AFS_USR_AIX_ENV) || defined(AFS_USR_SGI_ENV)
-#define SYS_setgroups 101
-#endif
-
-#define ioctl() usr_ioctl()
-
-#define label_t jmp_buf
-
-#ifdef VFSTOM
-#undef VFSTOM
-#endif
-
-#define VFSTOM(VP) ((struct usr_mount *)(VP)->vfs_mount)
-
-#ifdef VINACT
-#undef VINACT
-#endif
-#ifdef VLOCK
-#undef VLOCK
-#endif
-#ifdef VNOMAP
-#undef VNOMAP
-#endif
-#ifdef VROOT
-#undef VROOT
-#endif
-#ifdef VSHARE
-#undef VSHARE
-#endif
-#ifdef VTEXT
-#undef VTEXT
-#endif
-#ifdef VWAIT
-#undef VWAIT
-#endif
-#ifdef VWASMAP
-#undef VWASMAP
-#endif
-#ifdef VXLOCK
-#undef VXLOCK
-#endif
-
-#define VINACT 0x0001
-#define VLOCK 0x0002
-#define VNOMAP 0x0004
-#define VROOT 0x0008
-#define VSHARE 0x0010
-#define VTEXT 0x0020
-#define VWAIT 0x0040
-#define VWASMAP 0x0080
-#define VXLOCK 0x0100
-
-#ifdef VNON
-#undef VNON
-#endif
-#ifdef VREG
-#undef VREG
-#endif
-#ifdef VDIR
-#undef VDIR
-#endif
-#ifdef VBLK
-#undef VBLK
-#endif
-#ifdef VCHR
-#undef VCHR
-#endif
-#ifdef VLNK
-#undef VLNK
-#endif
-#ifdef VFIFO
-#undef VFIFO
-#endif
-#ifdef VDOOR
-#undef VDOOR
-#endif
-#ifdef VBAD
-#undef VBAD
-#endif
-#ifdef VSOCK
-#undef VSOCK
-#endif
-
-#define VNON 0
-#define VREG 1
-#define VDIR 2
-#define VBLK 3
-#define VCHR 4
-#define VLNK 5
-#define VFIFO 6
-#define VDOOR 7
-#define VBAD 8
-#define VSOCK 9
-
-typedef int usr_vtype_t;
-
-#ifdef VOP_RDWR
-#undef VOP_RDWR
-#endif
-
-#define VOP_RDWR afs_osi_VOP_RDWR
-
-#ifdef NDADDR
-#undef NDADDR
-#endif
-#ifdef NIADDR
-#undef NIADDR
-#endif
-
-#define NDADDR 12
-#define NIADDR 3
-
-#ifdef DTYPE_VNODE
-#undef DTYPE_VNODE
-#endif
-
-#define DTYPE_VNODE 1
-
-#ifdef IUPD
-#undef IUPD
-#endif
-#ifdef IACC
-#undef IACC
-#endif
-#ifdef IMOD
-#undef IMOD
-#endif
-#ifdef ICHG
-#undef ICHG
-#endif
-#ifdef INOACC
-#undef INOACC
-#endif
-#ifdef IMODTIME
-#undef IMODTIME
-#endif
-#ifdef IREF
-#undef IREF
-#endif
-#ifdef ISYNC
-#undef ISYNC
-#endif
-#ifdef IFASTSYMLNK
-#undef IFASTSYMLNK
-#endif
-#ifdef IMODACC
-#undef IMODACC
-#endif
-#ifdef IATTCHG
-#undef IATTCHG
-#endif
-#ifdef IBDWRITE
-#undef IBDWRITE
-#endif
-#ifdef IBAD
-#undef IBAD
-#endif
-#ifdef IDEL
-#undef IDEL
-#endif
-
-#define IUPD 0x0001
-#define IACC 0x0002
-#define IMOD 0x0004
-#define ICHG 0x0008
-#define INOACC 0x0010
-#define IMODTIME 0x0020
-#define IREF 0x0040
-#define ISYNC 0x0080
-#define IFASTSYMLNK 0x0100
-#define IMODACC 0x0200
-#define IATTCHG 0x0400
-#define IBDWRITE 0x0800
-#define IBAD 0x1000
-#define IDEL 0x2000
-
-#ifdef IFMT
-#undef IFMT
-#endif
-#ifdef IFIFO
-#undef IFIFO
-#endif
-#ifdef IFCHR
-#undef IFCHR
-#endif
-#ifdef IFDIR
-#undef IFDIR
-#endif
-#ifdef IFBLK
-#undef IFBLK
-#endif
-#ifdef IFREG
-#undef IFREG
-#endif
-#ifdef IFLNK
-#undef IFLNK
-#endif
-#ifdef IFSHAD
-#undef IFSHAD
-#endif
-#ifdef IFSOCK
-#undef IFSOCK
-#endif
-
-#define IFMT 0170000
-#define IFIFO 0010000
-#define IFCHR 0020000
-#define IFDIR 0040000
-#define IFBLK 0060000
-#define IFREG 0100000
-#define IFLNK 0120000
-#define IFSHAD 0130000
-#define IFSOCK 0140000
-
-#ifdef ISUID
-#undef ISUID
-#endif
-#ifdef ISGID
-#undef ISGID
-#endif
-#ifdef ISVTX
-#undef ISVTX
-#endif
-#ifdef IREAD
-#undef IREAD
-#endif
-#ifdef IWRITE
-#undef IWRITE
-#endif
-#ifdef IEXEC
-#undef IEXEC
-#endif
-
-#define ISUID 04000
-#define ISGID 02000
-#define ISVTX 01000
-#define IREAD 0400
-#define IWRITE 0200
-#define IEXEC 0100
-
-#ifdef I_SYNC
-#undef I_SYNC
-#endif
-#ifdef I_DSYNC
-#undef I_DSYNC
-#endif
-#ifdef I_ASYNC
-#undef I_ASYNC
-#endif
-
-#define I_SYNC 1
-#define I_DSYNC 2
-#define I_ASYNC 0
-
-#ifdef I_FREE
-#undef I_FREE
-#endif
-#ifdef I_DIR
-#undef I_DIR
-#endif
-#ifdef I_IBLK
-#undef I_IBLK
-#endif
-#ifdef I_CHEAP
-#undef I_CHEAP
-#endif
-#ifdef I_SHAD
-#undef I_SHAD
-#endif
-#ifdef I_QUOTA
-#undef I_QUOTA
-#endif
-
-#define I_FREE 0x00000001
-#define I_DIR 0x00000002
-#define I_IBLK 0x00000004
-#define I_CHEAP 0x00000008
-#define I_SHAD 0x00000010
-#define I_QUOTA 0x00000020
-
-#ifdef VTOI
-#undef VTOI
-#endif
-#ifdef ITOV
-#undef ITOV
-#endif
-
-#define VTOI(VP) ((struct usr_inode *)(VP)->v_data)
-#define ITOV(IP) ((struct usr_vnode *)&(IP)->i_vnode)
-
-#ifdef VN_HOLD
-#undef VN_HOLD
-#endif
-#ifdef VN_RELE
-#undef VN_RELE
-#endif
-
-#ifdef ROOT_INIT
-#undef ROOT_INIT
-#endif
-#ifdef ROOT_REMOUNT
-#undef ROOT_REMOUNT
-#endif
-#ifdef ROOT_UNMOUNT
-#undef ROOT_UNMOUNT
-#endif
-#ifdef ROOT_FRONTMOUNT
-#undef ROOT_FRONTMOUNT
-#endif
-#ifdef ROOT_BACKMOUNT
-#undef ROOT_BACKMOUNT
-#endif
-
-#define ROOT_INIT 0x0001
-#define ROOT_REMOUNT 0X0002
-#define ROOT_UNMOUNT 0x0003
-#define ROOT_FRONTMOUNT 0x0004
-#define ROOT_BACKMOUNT 0x0005
-
-#ifdef MAXFIDSZ
-#undef MAXFIDSZ
-#endif
-
-#define MAXFIDSZ 64
-
-#ifdef FSTYPSZ
-#undef FSTYPSZ
-#endif
-
-#define FSTYPSZ 16
-
-#ifdef VFS_MOUNT
-#undef VFS_MOUNT
-#endif
-#ifdef VFS_UNMOUNT
-#undef VFS_UNMOUNT
-#endif
-#ifdef VFS_ROOT
-#undef VFS_ROOT
-#endif
-#ifdef VFS_STATFS
-#undef VFS_STATFFS
-#endif
-#ifdef VFS_SYNC
-#undef VFS_SYNC
-#endif
-#ifdef VFS_VGET
-#undef VFS_VGET
-#endif
-#ifdef VFS_MOUNTROOT
-#undef VFS_MOUNTROOT
-#endif
-#ifdef VFS_SWAPVP
-#undef VFS_SWAPVP
-#endif
-#ifdef VFS_MOUNT
-#undef VFS_MOUNT
-#endif
-
-#define VFS_STATFS(vfsp, sp) ((sp)->f_bsize=4096, 0)
-
-#ifdef FAPPEND
-#undef FAPPEND
-#endif
-#ifdef FSYNC
-#undef FSYNC
-#endif
-#ifdef FTRUNC
-#undef FTRUNC
-#endif
-#ifdef FWRITE
-#undef FWRITE
-#endif
-#ifdef IO_APPEND
-#undef IO_APPEND
-#endif
-#ifdef IO_SYNC
-#undef IO_SYNC
-#endif
-
-#define FAPPEND 0x0100
-#define IO_APPEND FAPPEND
-#define FSYNC 0x0200
-#define IO_SYNC FSYNC
-#define FTRUNC 0x0400
-#define FWRITE 0x0800
-
-#ifdef F_GETLK
-#undef F_GETLK
-#endif
-#ifdef F_RDLCK
-#undef F_RDLCK
-#endif
-#ifdef F_SETLK
-#undef F_SETLK
-#endif
-#ifdef F_SETLKW
-#undef F_SETLKW
-#endif
-#ifdef F_UNLCK
-#undef F_UNLCK
-#endif
-#ifdef F_WRLCK
-#undef F_WRLCK
-#endif
-
-#define F_GETLK 0x0001
-#define F_RDLCK 0x0002
-#define F_SETLK 0x0003
-#define F_SETLKW 0x0004
-#define F_UNLCK 0x0005
-#define F_WRLCK 0x0006
-
-#ifdef LOCK_SH
-#undef LOCK_SH
-#endif
-#ifdef LOCK_EX
-#undef LOCK_EX
-#endif
-#ifdef LOCK_NB
-#undef LOCK_NB
-#endif
-#ifdef LOCK_UN
-#undef LOCK_UN
-#endif
-
-#define LOCK_SH F_RDLCK
-#define LOCK_UN F_UNLCK
-#define LOCK_EX F_WRLCK
-#define LOCK_NB 0x0007
-
-#ifdef FEXLOCK
-#undef FEXLOCK
-#endif
-#ifdef FSHLOCK
-#undef FSHLOCK
-#endif
-
-#define FEXLOCK F_WRLCK
-#define FSHLOCK F_RDLCK
-
-#ifdef SSYS
-#undef SSYS
-#endif
-
-#define SSYS 0x0001
-
-enum usr_uio_rw { USR_UIO_READ, USR_UIO_WRITE };
-
-#ifdef UIO_READ
-#undef UIO_READ
-#endif
-#ifdef UIO_WRITE
-#undef UIO_WRITE
-#endif
-
-#define UIO_READ 0x0000
-#define UIO_WRITE 0x0001
-
-#ifdef UIO_USERSPACE
-#undef UIO_USERSPACE
-#endif
-#ifdef UIO_SYSSPACE
-#undef UIO_SYSSPACE
-#endif
-
-#define UIO_USERSPACE 0x0000
-#define UIO_SYSSPACE 0x0001
-
-#ifdef B_AGE
-#undef B_AGE
-#endif
-#ifdef B_ASYNC
-#undef B_ASYNC
-#endif
-#ifdef B_DELWRI
-#undef B_DELWRI
-#endif
-#ifdef B_DIRTY
-#undef B_DIRTY
-#endif
-#ifdef B_DONE
-#undef B_DONE
-#endif
-#ifdef B_ERROR
-#undef B_ERROR
-#endif
-#ifdef B_FREE
-#undef B_FREE
-#endif
-#ifdef B_NOCACHE
-#undef B_NOCACHE
-#endif
-#ifdef B_PFSTORE
-#undef B_PFSTORE
-#endif
-#ifdef B_READ
-#undef B_READ
-#endif
-#ifdef B_UBC
-#undef B_UBC
-#endif
-#ifdef B_WANTED
-#undef B_WANTED
-#endif
-#ifdef B_WRITE
-#undef B_WRITE
-#endif
-
-#define B_AGE 0x0001
-#define B_ASYNC 0x0002
-#define B_DELWRI 0x0004
-#define B_DIRTY 0x0008
-#define B_DONE 0x0010
-#define B_ERROR 0x0020
-#define B_FREE 0x0040
-#define B_NOCACHE 0x0080
-#define B_PFSTORE 0x0100
-#define B_READ 0x0200
-#define B_UBC 0x0400
-#define B_WANTED 0x0800
-#define B_WRITE 0x1000
-
-#ifdef MFREE
-#undef MFREE
-#endif
-#ifdef MINUSE
-#undef MINUSE
-#endif
-#ifdef MINTER
-#undef MINTER
-#endif
-#ifdef MUPDATE
-#undef MUPDATE
-#endif
-
-#define MFREE 0
-#define MINUSE 1
-#define MINTER 2
-#define MUPDATE 4
-
-#ifdef MSIZE
-#undef MSIZE
-#endif
-#ifdef MMAXOFF
-#undef MMAXOFF
-#endif
-
-#define MSIZE 16384
-#define MMAXOFF 16384
-
-#ifdef IA_SIN
-#undef IA_SIN
-#endif
-
-#define IA_SIN(IA) (&(IA)->ia_addr)
-
-#ifdef mtod
-#undef mtod
-#endif
-#ifdef dtom
-#undef dtom
-#endif
-#ifdef mtocl
-#undef mtocl
-#endif
-
-#define mtod(m,t) ((t)((m)->m_data))
-
-#ifdef NBPG
-#undef NBPG
-#endif
-#define NBPG 4096
-
-#define panic(S) do{fprintf(stderr, S);assert(0);}while(0)
-#define abort() assert(0)
-#define usr_assert(A) assert(A)
-
-#ifdef NETSCAPE_NSAPI
-
-/*
- * All CONDVARs created with the same CRITICAL end up being the
- * same CONDVAR, not a new one. If we want to use more than
- * one usr_cond_t with the same usr_mutex_t, then we need a CRITICAL
- * for each CONDVAR, otherwise we cannot know which thread we are
- * waking when we do the signal.
- */
-typedef struct {
- int waiters;
- CRITICAL lock;
- CONDVAR cond;
-} usr_cond_t;
-
-#define usr_mutex_t CRITICAL
-#define usr_thread_t SYS_THREAD
-#define usr_key_t int
-
-#define usr_mutex_init(A) (*(A)=crit_init(), 0)
-#define usr_mutex_destroy(A) (crit_terminate(*(A)), 0)
-#define usr_mutex_lock(A) crit_enter(*(A))
-#define usr_mutex_trylock(A) (crit_enter(*(A)),1)
-#define usr_mutex_unlock(A) crit_exit(*(A))
-
-#define usr_cond_init(A) \
- ((A)->waiters = 0, \
- (A)->lock = crit_init(), \
- (A)->cond = condvar_init((A)->lock), 0)
-
-#define usr_cond_destroy(A) \
- (condvar_terminate((A)->cond), \
- crit_terminate((A)->lock), 0)
-
-#define usr_cond_signal(A) \
-{ \
- crit_enter((A)->lock); \
- if ((A)->waiters != 0) { \
- condvar_notify((A)->cond);\
- (A)->waiters -= 1; \
- } \
- crit_exit((A)->lock); \
-}
-
-#define usr_cond_broadcast(A) \
-{ \
- crit_enter((A)->lock); \
- while ((A)->waiters != 0) { \
- condvar_notify((A)->cond); \
- (A)->waiters -= 1; \
- } \
- crit_exit((A)->lock); \
-}
-
-#define usr_cond_wait(A,B) \
- (crit_enter((A)->lock), \
- crit_exit(*(B)), \
- (A)->waiters += 1, \
- condvar_wait((A)->cond), \
- crit_exit((A)->lock), \
- crit_enter(*(B)), 0)
-
-#define usr_thread_create(A,B,C) \
- ((*(A)=systhread_start(SYSTHREAD_DEFAULT_PRIORITY, \
- 0,B,C))==SYS_THREAD_ERROR)
-#define usr_thread_detach(A) 0
-#define usr_keycreate(A,B) (*(A)=systhread_newkey(),0)
-#define usr_setspecific(A,B) (systhread_setdata(A,B),0)
-#define usr_getspecific(A,B) (*(B)=systhread_getdata(A),0)
-#define usr_thread_self() systhread_current()
-#ifdef AFS_USR_SUN5_ENV
-#define usr_thread_sleep(A) \
- poll(0, 0, (A)->tv_sec*1000+(A)->tv_nsec/1000000)
-#else /* AFS_USR_SUN5_ENV */
-#define usr_thread_sleep(A) \
- systhread_sleep((A)->tv_sec*1000+(A)->tv_nsec/1000000)
-#endif /* AFS_USR_SUN5_ENV */
-
-#define uprintf printf
-
-#define usr_getpid() (int)(usr_thread_self())
-
-#define ISAFS_GLOCK() (usr_thread_self() == afs_global_owner)
-
-#else /* NETSCAPE_NSAPI */
-
-/*
- * Mutex and condition variable used to implement sleep
- */
-extern pthread_mutex_t usr_sleep_mutex;
-extern pthread_cond_t usr_sleep_cond;
-
-#define usr_cond_t pthread_cond_t
-#define usr_mutex_t pthread_mutex_t
-#define usr_thread_t pthread_t
-#define usr_key_t pthread_key_t
-
-#define usr_mutex_init(A) assert(pthread_mutex_init(A,NULL) == 0)
-#define usr_mutex_destroy(A) assert(pthread_mutex_destroy(A) == 0)
-#define usr_mutex_lock(A) assert(pthread_mutex_lock(A) == 0)
-#define usr_mutex_trylock(A) ((pthread_mutex_trylock(A)==0)?1:0)
-#define usr_mutex_unlock(A) assert(pthread_mutex_unlock(A) == 0)
-#define usr_cond_init(A) assert(pthread_cond_init(A,NULL) == 0)
-#define usr_cond_destroy(A) assert(pthread_cond_destroy(A) == 0)
-#define usr_cond_signal(A) assert(pthread_cond_signal(A) == 0)
-#define usr_cond_broadcast(A) assert(pthread_cond_broadcast(A) == 0)
-#define usr_cond_wait(A,B) pthread_cond_wait(A,B)
-#define usr_cond_timedwait(A,B,C) pthread_cond_timedwait(A,B,C)
-
-#define usr_thread_create(A,B,C) \
- do { \
- pthread_attr_t attr; \
- assert(pthread_attr_init(&attr) == 0); \
- assert(pthread_attr_setstacksize(&attr, 124288) == 0); \
- assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); \
- assert(pthread_create((A), &attr, (B), (void *)(C)) == 0); \
- assert(pthread_attr_destroy(&attr) == 0); \
- } while(0)
-#define usr_thread_detach(A) pthread_detach(A)
-#define usr_keycreate(A,B) assert(pthread_key_create(A,B) == 0)
-#define usr_setspecific(A,B) pthread_setspecific(A,B)
-#define usr_getspecific(A,B) (*(B)=pthread_getspecific(A),0)
-#define usr_thread_self() pthread_self()
-#define usr_thread_sleep(A) \
-{ \
- struct timespec _sleep_ts; \
- struct timeval _sleep_tv; \
- gettimeofday(&_sleep_tv, NULL); \
- _sleep_ts = *(A); \
- _sleep_ts.tv_sec += _sleep_tv.tv_sec; \
- _sleep_ts.tv_nsec += _sleep_tv.tv_usec * 1000; \
- if (_sleep_ts.tv_nsec >= 1000000000) { \
- _sleep_ts.tv_sec += 1; \
- _sleep_ts.tv_nsec -= 1000000000; \
- } \
- assert(pthread_mutex_lock(&usr_sleep_mutex) == 0); \
- pthread_cond_timedwait(&usr_sleep_cond, &usr_sleep_mutex, &_sleep_ts); \
- assert(pthread_mutex_unlock(&usr_sleep_mutex) == 0); \
-}
-
-#define uprintf printf
-
-#define usr_getpid() (int)(usr_thread_self())
-#ifdef ISAFS_GLOCK
-#undef ISAFS_GLOCK
-#endif
-#define ISAFS_GLOCK() (usr_thread_self() == afs_global_owner)
-
-#endif /* NETSCAPE_NSAPI */
-
-#define copyin(A,B,C) (memcpy((void *)B,(void *)A,C), 0)
-#define copyout(A,B,C) (memcpy((void *)B,(void *)A,C), 0)
-#define copyinstr(A,B,C,D) (strncpy(B,A,C),(*D)=strlen(B), 0)
-#define copyoutstr(A,B,C,D) (strncpy(B,A,C),(*D)=strlen(B), 0)
-
-#define vattr_null(A) usr_vattr_null(A)
-
-#define VN_HOLD(vp) \
-{ \
- (vp)->v_count++; \
-}
-
-#define VN_RELE(vp) \
-do { \
- AFS_ASSERT_GLOCK(); \
- usr_assert((vp)->v_count > 0); \
- if (--((vp)->v_count) == 0) \
- afs_inactive(vp, u.u_cred); \
-} while(0)
-
-struct usr_statfs {
- unsigned long f_type;
- unsigned long f_bsize;
- unsigned long f_frsize;
- unsigned long f_ffree;
- unsigned long f_favail;
- struct {
- unsigned long val[2];
- } f_fsid;
- char f_basetype[FSTYPSZ];
- unsigned long f_flag;
- unsigned long f_namemax;
- unsigned long f_blocks;
- unsigned long f_bfree;
- unsigned long f_bavail;
- unsigned long f_files;
-};
-
-struct usr_vattr {
- long va_mask;
- usr_vtype_t va_type;
- unsigned short va_mode;
- long va_uid;
- long va_gid;
- unsigned long va_fsid;
- unsigned long va_nodeid;
- unsigned long va_nlink;
- unsigned long va_size;
- struct timeval va_atime;
- struct timeval va_mtime;
- struct timeval va_ctime;
- unsigned long va_rdev;
- unsigned long va_blocksize;
- unsigned long va_blocks;
- unsigned long va_vcode;
-};
-
-#ifdef VSUID
-#undef VSUID
-#endif
-#ifdef VSGID
-#undef VSGID
-#endif
-#ifdef VSVTX
-#undef VSVTX
-#endif
-#ifdef VREAD
-#undef VREAD
-#endif
-#ifdef VWRITE
-#undef VWRITE
-#endif
-#ifdef VEXEC
-#undef VEXEC
-#endif
-
-#define VSUID 04000
-#define VSGID 02000
-#define VSVTX 01000
-#define VREAD 00400
-#define VWRITE 00200
-#define VEXEC 00100
-
-
-struct usr_vnode {
- unsigned short v_flag;
- unsigned long v_count;
- struct usr_vnodeops *v_op;
- struct usr_vfs *v_vfsp;
- long v_type;
- unsigned long v_rdev;
- char *v_data;
-};
-
-struct usr_inode {
- daddr_t i_db[NDADDR];
- struct usr_vnode *i_devvp;
- unsigned long i_dev;
- long i_flag;
- struct usr_inode *i_freef;
- struct usr_inode **i_freeb;
- long i_gid;
- daddr_t i_ib[NIADDR];
- unsigned short i_mode;
- short i_nlink;
- unsigned long i_number;
- long i_size;
- long i_uid;
- struct usr_vnode i_vnode;
- struct {
- unsigned long ic_spare[4];
- } i_ic;
-};
-extern struct usr_inode *iget();
-
-struct usr_fileops {
- int (*vno_rw) (void);
- int (*vno_ioctl) (void);
- int (*vno_select) (void);
- int (*vno_closex) (void);
-};
-
-struct usr_file {
- unsigned short f_flag;
- offset_t f_offset;
- struct usr_ucred *f_cred;
- struct usr_fileops *f_ops;
- char *f_data;
- long f_type;
-};
-extern struct usr_file *falloc();
-extern struct usr_file *getf(int);
-
-#ifdef fid_len
-#undef fid_len
-#endif
-#ifdef fid_data
-#undef fid_data
-#endif
-
-struct usr_fid {
- unsigned short fid_len;
- unsigned short fid_reserved;
- char fid_data[MAXFIDSZ];
-};
-
-struct usr_flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- long l_sysid;
- pid_t l_pid;
-};
-
-extern struct usr_ucred *usr_crget(void);
-extern struct usr_ucred *usr_crcopy(struct usr_ucred *);
-extern int usr_crhold(struct usr_ucred *);
-extern int usr_crfree(struct usr_ucred *);
-extern struct usr_ucred *afs_global_ucredp;
-
-struct usr_proc {
- unsigned long p_flag;
- pid_t p_pid;
- pid_t p_ppid;
- struct usr_ucred *p_ucred;
- char p_cursig;
-};
-
-struct usr_a {
- int fd;
- int syscall;
- int parm1;
- int parm2;
- int parm3;
- int parm4;
- int parm5;
- int parm6;
-};
-
-#ifdef uio_offset
-#undef uio_offset
-#endif
-
-struct usr_uio {
- struct iovec *uio_iov;
- int uio_iovcnt;
- long uio_offset;
- int uio_segflg;
- short uio_fmode;
- int uio_resid;
-};
-
-#ifdef b_blkno
-#undef b_blkno
-#endif
-#ifdef b_vp
-#undef b_vp
-#endif
-
-struct usr_buf {
- int b_flags;
- short b_dev;
- unsigned b_bcount;
- struct {
- char *b_addr;
- struct usr_fs *b_fs;
- } b_un;
- long b_blkno;
- unsigned int b_resid;
- struct usr_vnode *b_vp;
-};
-
-struct usr_socket {
- int sock;
- short port;
-};
-
-#define NDIRSIZ_LEN(len) \
-((sizeof (struct usr_dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
-
-struct usr_vnodeops {
- int (*vn_open) (char *path, int flags, int mode);
- int (*vn_close) (int fd);
- int (*vn_rdwr) ();
- int (*vn_ioctl) (void);
- int (*vn_select) (void);
- int (*vn_getattr) ();
- int (*vn_setattr) ();
- int (*vn_access) ();
- int (*vn_lookup) ();
- int (*vn_create) ();
- int (*vn_remove) ();
- int (*vn_link) ();
- int (*vn_rename) ();
- int (*vn_mkdir) ();
- int (*vn_rmdir) ();
- int (*vn_readdir) ();
- int (*vn_symlink) ();
- int (*vn_readlink) ();
- int (*vn_fsync) ();
- int (*vn_inactive) ();
- int (*vn_bmap) ();
- int (*vn_strategy) ();
- int (*vn_bread) ();
- int (*vn_brelse) ();
- int (*vn_lockctl) ();
- int (*vn_fid) ();
-};
-
-struct usr_fs {
- int dummy;
-};
-
-struct usr_mount {
- char m_flags;
- unsigned long m_dev;
- struct usr_inode *m_inodp;
- struct usr_buf *m_bufp;
- struct usr_vnode *m_mount;
-};
-extern struct usr_mount *getmp(unsigned long);
-
-typedef long usr_whymountroot_t;
-
-struct usr_vfsops {
- int (*vfs_mount) ();
- int (*vfs_unmount) ();
- int (*vfs_root) ();
- int (*vfs_statfs) ();
- int (*vfs_mountroot) ();
- int (*vfs_swapvp) ();
-};
-
-struct usr_vfs {
- struct usr_vnode *vfs_vnodecovered;
- struct {
- unsigned long val[2];
- } vfs_fsid;
- char *vfs_data;
- unsigned long vfs_bsize;
- struct usr_mount *vfs_mount;
- struct usr_vfsops *vfs_op;
-};
-
-struct usr_sysent {
- char sy_narg;
- int (*sy_call) ();
-};
-extern struct usr_sysent usr_sysent[];
-
-struct usr_ifnet {
- struct usr_ifnet *if_next;
- short if_flags;
- u_int if_mtu;
- u_int if_metric;
- struct usr_ifaddr *if_addrlist;
-};
-extern struct usr_ifnet *usr_ifnet;
-
-struct usr_ifaddr {
- struct usr_ifaddr *ifa_next;
- struct usr_ifnet *ifa_ifp;
- struct sockaddr ifa_addr;
-};
-
-#ifdef ia_ifp
-#undef ia_ifp
-#endif
-#ifdef ia_addr
-#undef ia_addr
-#endif
-
-struct usr_in_ifaddr {
- struct usr_in_ifaddr *ia_next;
- struct usr_ifnet *ia_ifp;
- struct sockaddr_in ia_addr;
- unsigned long ia_net;
- unsigned long ia_netmask;
- unsigned long ia_subnet;
- unsigned long ia_subnetmask;
- struct in_addr ia_netbroadcast;
-};
-extern struct usr_in_ifaddr *usr_in_ifaddr;
-
-extern usr_key_t afs_global_u_key; /* for per thread authentication */
-
-#if defined(AFS_USR_OSF_ENV)
-extern char V;
-#else
-extern long V;
-#endif
-
-#endif /* UKERNEL */
-
-struct min_direct {
-#if defined(AFS_OFS_ENV) || defined(AFS_USR_OSF_ENV)
- unsigned int d_fileno;
-#else /* AFS_OFS_ENV || AFS_USR_OSF_ENV */
- unsigned long d_fileno;
-#endif /* AFS_OFS_ENV || AFS_USR_OSF_ENV */
- unsigned short d_reclen;
- unsigned short d_namlen;
-};
-
-#ifndef NGROUPS
-#define NGROUPS NGROUPS_MAX
-#endif
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-#ifdef cr_gid
-#undef cr_gid
-#endif
-
-struct usr_ucred {
- unsigned long cr_ref;
- long cr_uid;
- long cr_gid;
- long cr_ruid;
- long cr_rgid;
- long cr_suid;
- long cr_sgid;
- long cr_ngroups;
- gid_t cr_groups[NGROUPS];
-};
-
-#ifdef u_rval1
-#undef u_rval1
-#endif
-
-struct usr_user {
- int u_error;
- int u_prio;
- char *u_ap;
- int u_rval1;
- long u_viceid;
- unsigned long u_expiration;
- struct usr_proc *u_procp;
- struct usr_ucred *u_cred;
- struct {
- int r_val1;
- } u_r;
-};
-#define u_rval1 u_r.r_val1
-#define u (*(get_user_struct()))
-
-extern struct usr_user *get_user_struct(void);
-
-#define USR_DIRSIZE 2048
-
-struct usr_dirent {
- unsigned long d_ino;
- unsigned long d_off;
- unsigned short d_reclen;
- char d_name[MAXNAMLEN + 1];
-};
-
-typedef struct {
- int dd_fd;
- int dd_loc;
- int dd_size;
- int dd_reserved;
- char *dd_buf;
-} usr_DIR;
-
-extern unsigned short usr_rx_port;
-
-#define AFS_LOOKUP_NOEVAL 1
-
-#endif /* __AFS_SYSINCLUDESH__ so idempotent */
+++ /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
- */
-
-/*
- * afs_vnop_access.c - access vop ccess mode bit support for vnode operations.
- *
- * Implements:
- * afs_GetAccessBits
- * afs_AccessOK
- * afs_access
- *
- * Local:
- * fileModeMap (table)
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.10 2003/07/15 23:14:29 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-#ifndef ANONYMOUSID
-#define ANONYMOUSID 32766 /* make sure this is same as in ptserver.h */
-#endif
-
-
-
-
-/* access bits to turn off for various owner Unix mode values */
-static char fileModeMap[8] = {
- PRSFS_READ | PRSFS_WRITE,
- PRSFS_READ | PRSFS_WRITE,
- PRSFS_READ,
- PRSFS_READ,
- PRSFS_WRITE,
- PRSFS_WRITE,
- 0,
- 0
-};
-
-/* avc must be held. Returns bit map of mode bits. Ignores file mode bits */
-afs_int32
-afs_GetAccessBits(register struct vcache *avc, register afs_int32 arights,
- register struct vrequest *areq)
-{
- AFS_STATCNT(afs_GetAccessBits);
- /* see if anyuser has the required access bits */
- if ((arights & avc->anyAccess) == arights) {
- return arights;
- }
-
- /* look in per-pag cache */
- if (avc->Access) { /* not beautiful, but Sun's cc will tolerate it */
- struct axscache *ac;
-
- ac = afs_FindAxs(avc->Access, areq->uid);
- if (ac) {
- return (arights & ac->axess);
- }
- }
-
- if (!(avc->states & CForeign)) {
- /* If there aren't any bits cached for this user (but the vnode
- * _is_ cached, obviously), make sure this user has valid tokens
- * before bothering with the RPC. */
- struct unixuser *tu;
- extern struct unixuser *afs_FindUser();
- tu = afs_FindUser(areq->uid, avc->fid.Cell, READ_LOCK);
- if (!tu) {
- return (arights & avc->anyAccess);
- }
- if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
- || (tu->states & UTokensBad)) {
- afs_PutUser(tu, READ_LOCK);
- return (arights & avc->anyAccess);
- } else {
- afs_PutUser(tu, READ_LOCK);
- }
- }
-
- { /* Ok, user has valid tokens, go ask the server. */
- struct AFSFetchStatus OutStatus;
- afs_int32 code;
-
- code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
- return (code ? 0 : OutStatus.CallerAccess & arights);
- }
-}
-
-
-/* the new access ok function. AVC must be held but not locked. if avc is a
- * file, its parent need not be held, and should not be locked. */
-
-int
-afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
- afs_int32 check_mode_bits)
-{
- register struct vcache *tvc;
- struct VenusFid dirFid;
- register afs_int32 mask;
- afs_int32 dirBits;
- register afs_int32 fileBits;
-
- AFS_STATCNT(afs_AccessOK);
-
- if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
- /* rights are just those from acl */
- return (arights == afs_GetAccessBits(avc, arights, areq));
- } else {
- /* some rights come from dir and some from file. Specifically, you
- * have "a" rights to a file if you are its owner, which comes
- * back as "a" rights to the file. You have other rights just
- * from dir, but all are restricted by the file mode bit. Now,
- * if you have I and A rights to a file, we throw in R and W
- * rights for free. These rights will then be restricted by
- * the access mask. */
- dirBits = 0;
- if (avc->parentVnode) {
- dirFid.Cell = avc->fid.Cell;
- dirFid.Fid.Volume = avc->fid.Fid.Volume;
- dirFid.Fid.Vnode = avc->parentVnode;
- dirFid.Fid.Unique = avc->parentUnique;
- /* Avoid this GetVCache call */
- tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
- if (tvc) {
- dirBits = afs_GetAccessBits(tvc, arights, areq);
- afs_PutVCache(tvc);
- }
- } else
- dirBits = 0xffffffff; /* assume OK; this is a race condition */
- if (arights & PRSFS_ADMINISTER)
- fileBits = afs_GetAccessBits(avc, arights, areq);
- else
- fileBits = 0; /* don't make call if results don't matter */
-
- /* compute basic rights in fileBits, taking A from file bits */
- fileBits =
- (fileBits & PRSFS_ADMINISTER) | (dirBits & ~PRSFS_ADMINISTER);
-
- /* for files, throw in R and W if have I and A (owner). This makes
- * insert-only dirs work properly */
- if (vType(avc) != VDIR
- && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
- (PRSFS_ADMINISTER | PRSFS_INSERT))
- fileBits |= (PRSFS_READ | PRSFS_WRITE);
-
- if (check_mode_bits & CHECK_MODE_BITS) {
- /* owner mode bits are further restrictions on the access mode
- * The mode bits are mapped to protection bits through the
- * fileModeMap. If CMB_ALLOW_EXEC_AS_READ is set, it's from the
- * NFS translator and we don't know if it's a read or execute
- * on the NFS client, but both need to read the data.
- */
- mask = (avc->m.Mode & 0700) >> 6; /* file restrictions to use */
- fileBits &= ~fileModeMap[mask];
- if (check_mode_bits & CMB_ALLOW_EXEC_AS_READ) {
- if (avc->m.Mode & 0100)
- fileBits |= PRSFS_READ;
- }
- }
- return ((fileBits & arights) == arights); /* true if all rights bits are on */
- }
-}
-
-
-#if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
-int
-afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
- struct AFS_UCRED *acred)
-#else
-int
-afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
- struct AFS_UCRED *acred)
-#endif
-{
- register afs_int32 code;
- struct vrequest treq;
- struct afs_fakestat_state fakestate;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_access);
- afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- afs_InitFakeStat(&fakestate);
- if ((code = afs_InitReq(&treq, acred)))
- return code;
-
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- return code;
- }
-
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 16);
- return code;
- }
-
- /* if we're looking for write access and we have a read-only file system, report it */
- if ((amode & VWRITE) && (avc->states & CRO)) {
- afs_PutFakeStat(&fakestate);
- return EROFS;
- }
- code = 1; /* Default from here on in is access ok. */
- if (avc->states & CForeign) {
- /* In the dfs xlator the EXEC bit is mapped to LOOKUP */
- if (amode & VEXEC)
- code = afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- if (code && (amode & VWRITE)) {
- code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
- if (code && (vType(avc) == VDIR)) {
- if (code)
- code =
- afs_AccessOK(avc, PRSFS_INSERT, &treq,
- CHECK_MODE_BITS);
- if (!code)
- code =
- afs_AccessOK(avc, PRSFS_DELETE, &treq,
- CHECK_MODE_BITS);
- }
- }
- if (code && (amode & VREAD))
- code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
- } else {
- if (vType(avc) == VDIR) {
- if (amode & VEXEC)
- code =
- afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- if (code && (amode & VWRITE)) {
- code =
- afs_AccessOK(avc, PRSFS_INSERT, &treq, CHECK_MODE_BITS);
- if (!code)
- code =
- afs_AccessOK(avc, PRSFS_DELETE, &treq,
- CHECK_MODE_BITS);
- }
- if (code && (amode & VREAD))
- code =
- afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- } else {
- if (amode & VEXEC) {
- code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
- if (code) {
-#ifdef AFS_OSF_ENV
- /*
- * The nfs server in read operations for non-owner of a file
- * will also check the access with the VEXEC (along with VREAD)
- * because for them exec is the same as read over the net because of
- * demand loading. But this means if the mode bit is '-rw' the call
- * will fail below; so for this particular case where both modes are
- * specified (only in rfs_read so far) and from the xlator requests
- * we return succes.
- */
- if (!((amode & VREAD) && AFS_NFSXLATORREQ(acred)))
-#endif
- if ((avc->m.Mode & 0100) == 0)
- code = 0;
- } else if (avc->m.Mode & 0100)
- code = 1;
- }
- if (code && (amode & VWRITE)) {
- code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
-
- /* The above call fails when the NFS translator tries to copy
- ** a file with r--r--r-- permissions into a directory which
- ** has system:anyuser acl. This is because the destination file
- ** file is first created with r--r--r-- permissions through an
- ** unauthenticated connectin. hence, the above afs_AccessOK
- ** call returns failure. hence, we retry without any file
- ** mode bit checking */
- if (!code && AFS_NFSXLATORREQ(acred)
- && avc->m.Owner == ANONYMOUSID)
- code =
- afs_AccessOK(avc, PRSFS_WRITE, &treq,
- DONT_CHECK_MODE_BITS);
- }
- if (code && (amode & VREAD))
- code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
- }
- }
- afs_PutFakeStat(&fakestate);
- if (code) {
- return 0; /* if access is ok */
- } else {
- code = afs_CheckCode(EACCES, &treq, 17); /* failure code */
- return code;
- }
-}
-
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
-/*
- * afs_getRights
- * This function is just an interface to afs_GetAccessBits
- */
-int
-afs_getRights(OSI_VC_DECL(avc), register afs_int32 arights,
- struct AFS_UCRED *acred)
-{
- register afs_int32 code;
- struct vrequest treq;
- OSI_VC_CONVERT(avc)
-
- if (code = afs_InitReq(&treq, acred))
- return code;
-
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 16);
- return code;
- }
-
- return afs_GetAccessBits(avc, arights, &treq);
-}
-#endif /* defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) */
+++ /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
- *
- * Portions Copyright (c) 2003 Apple Computer, Inc.
- */
-
-/*
- * afs_vnop_attrs.c - setattr and getattr vnodeops
- *
- * Implements:
- * afs_CopyOutAttrs
- * afs_getattr
- * afs_VAttrToAS
- * afs_setattr
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27 2003/10/24 06:26:04 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-extern afs_rwlock_t afs_xcbhash;
-struct afs_exporter *afs_nfsexporter;
-extern struct vcache *afs_globalVp;
-#if defined(AFS_HPUX110_ENV)
-extern struct vfs *afs_globalVFS;
-#endif
-
-/* copy out attributes from cache entry */
-int
-afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
-{
- register struct volume *tvp;
- register struct cell *tcell;
- int fakedir = 0;
-
- AFS_STATCNT(afs_CopyOutAttrs);
- if (afs_fakestat_enable && avc->mvstat == 1)
- fakedir = 1;
-#if defined(AFS_MACH_ENV )
- attrs->va_mode =
- fakedir ? VDIR | 0755 : vType(avc) | (avc->m.Mode & ~VFMT);
-#else /* AFS_MACH_ENV */
- attrs->va_type = fakedir ? VDIR : vType(avc);
-#if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
- attrs->va_mode = fakedir ? 0755 : (mode_t) (avc->m.Mode & 0xffff);
-#else
- attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
-#endif
-#endif /* AFS_MACH_ENV */
-
- if (avc->m.Mode & (VSUID | VSGID)) {
- /* setuid or setgid, make sure we're allowed to run them from this cell */
- tcell = afs_GetCell(avc->fid.Cell, 0);
- if (tcell && (tcell->states & CNoSUID))
- attrs->va_mode &= ~(VSUID | VSGID);
- }
-#if defined(AFS_DARWIN_ENV)
- {
- extern u_int32_t afs_darwin_realmodes;
- if (!afs_darwin_realmodes) {
- /* Mac OS X uses the mode bits to determine whether a file or
- * directory is accessible, and believes them, even though under
- * AFS they're almost assuredly wrong, especially if the local uid
- * does not match the AFS ID. So we set the mode bits
- * conservatively.
- */
- if (S_ISDIR(attrs->va_mode)) {
- /* all access bits need to be set for directories, since even
- * a mode 0 directory can still be used normally.
- */
- attrs->va_mode |= ACCESSPERMS;
- } else {
- /* for other files, replicate the user bits to group and other */
- mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
- attrs->va_mode |= ubits | (ubits << 3);
- }
- }
- }
-#endif /* AFS_DARWIN_ENV */
- attrs->va_uid = fakedir ? 0 : avc->m.Owner;
- attrs->va_gid = fakedir ? 0 : avc->m.Group; /* yeah! */
-#if defined(AFS_SUN56_ENV)
- attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
-#else
-#ifdef AFS_SUN5_ENV
- /* XXX We try making this match the vfs's dev field XXX */
- attrs->va_fsid = 1;
-#else
-#ifdef AFS_OSF_ENV
- attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0];
-#else
-#ifdef AFS_DARWIN70_ENV
- attrs->va_fsid = avc->v.v_mount->mnt_stat.f_fsid.val[0];
-#else /* ! AFS_DARWIN70_ENV */
- attrs->va_fsid = 1;
-#endif /* AFS_DARWIN70_ENV */
-#endif
-#endif
-#endif /* AFS_SUN56_ENV */
- if (avc->mvstat == 2) {
- tvp = afs_GetVolume(&avc->fid, 0, READ_LOCK);
- /* The mount point's vnode. */
- if (tvp) {
- attrs->va_nodeid =
- tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
- if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
- attrs->va_nodeid = 2;
- afs_PutVolume(tvp, READ_LOCK);
- } else
- attrs->va_nodeid = 2;
- } else
- attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
- attrs->va_nodeid &= 0x7fffffff; /* Saber C hates negative inode #s! */
- attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
- attrs->va_size = fakedir ? 4096 : avc->m.Length;
- attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
- fakedir ? 0 : (int)avc->m.Date;
- /* set microseconds to be dataversion # so that we approximate NFS-style
- * use of mtime as a dataversion #. We take it mod 512K because
- * microseconds *must* be less than a million, and 512K is the biggest
- * power of 2 less than such. DataVersions are typically pretty small
- * anyway, so the difference between 512K and 1000000 shouldn't matter
- * much, and "&" is a lot faster than "%".
- */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka
- * dataversion) in va_gen */
-
- attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
- attrs->va_ctime.tv_nsec = 0;
- attrs->va_gen = hgetlo(avc->m.DataVersion);
-#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV)
- attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
- attrs->va_ctime.tv_nsec =
- (hgetlo(avc->m.DataVersion) & 0x7ffff) * 1000;
-#else
- attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
- attrs->va_ctime.tv_usec = (hgetlo(avc->m.DataVersion) & 0x7ffff);
-#endif
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV)
- attrs->va_flags = 0;
-#endif
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
- attrs->va_blksize = PAGESIZE; /* XXX Was 8192 XXX */
-#else
- attrs->va_blocksize = PAGESIZE; /* XXX Was 8192 XXX */
-#endif
-#ifdef AFS_DEC_ENV
- /* Have to use real device #s in Ultrix, since that's how FS type is
- * encoded. If rdev doesn't match Ultrix equivalent of statfs's rdev, then
- * "df ." doesn't work.
- */
- if (afs_globalVFS && afs_globalVFS->vfs_data)
- attrs->va_rdev = ((struct mount *)(afs_globalVFS->vfs_data))->m_dev;
- else
- attrs->va_rdev = 1; /* better than nothing */
-#else
- attrs->va_rdev = 1;
-#endif
-#if defined(AFS_HPUX110_ENV)
- if (afs_globalVFS)
- attrs->va_fstype = afs_globalVFS->vfs_mtype;
-#endif
-
- /*
- * Below return 0 (and not 1) blocks if the file is zero length. This conforms
- * better with the other filesystems that do return 0.
- */
-#if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#if !defined(AFS_HPUX_ENV)
-#ifdef AFS_SUN5_ENV
- attrs->va_nblocks =
- (attrs->va_size ? ((attrs->va_size + 1023) >> 10) << 1 : 0);
-#elif defined(AFS_SGI_ENV)
- attrs->va_blocks = BTOBB(attrs->va_size);
-#else
- attrs->va_blocks =
- (attrs->va_size ? ((attrs->va_size + 1023) >> 10) << 1 : 0);
-#endif
-#else /* !defined(AFS_HPUX_ENV) */
- attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023) >> 10) : 0);
-#endif /* !defined(AFS_HPUX_ENV) */
-#else /* ! AFS_OSF_ENV && !AFS_DARWIN_ENV && !AFS_XBSD_ENV */
- attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
-#ifdef va_bytes_rsv
- attrs->va_bytes_rsv = -1;
-#endif
-#endif /* ! AFS_OSF_ENV && !AFS_DARWIN_ENV && !AFS_XBSD_ENV */
-
-#ifdef AFS_LINUX22_ENV
- /* And linux has its own stash as well. */
- vattr2inode(AFSTOV(avc), attrs);
-#endif
-#ifdef notdef
-#ifdef AFS_AIX51_ENV
- afs_Trace2(afs_iclSetp, CM_TRACE_STATACLX, ICL_TYPE_POINTER,
- attrs->va_acl, ICL_TYPE_INT32, attrs->va_aclsiz);
- if (attrs->va_acl && attrs->va_aclsiz >= 12) {
- struct acl *ap;
-
- ap = (struct acl *)attrs->va_acl;
- ap->acl_len = 8;
- ap->acl_mode = ACL_MODE;
- ap->acl_rsvd = 0;
- ap->u_access = 7;
- }
- /* temporary fix ? */
- attrs->va_aclsiz = 1;
-#endif
-#endif
- return 0;
-}
-
-
-
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-int
-afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, int flags,
- struct AFS_UCRED *acred)
-#else
-int
-afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, struct AFS_UCRED *acred)
-#endif
-{
- afs_int32 code;
- struct vrequest treq;
- extern struct unixuser *afs_FindUser();
- struct unixuser *au;
- int inited = 0;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_getattr);
- afs_Trace2(afs_iclSetp, CM_TRACE_GETATTR, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
-
- if (afs_fakestat_enable && avc->mvstat == 1) {
- struct afs_fakestat_state fakestat;
-
- code = afs_InitReq(&treq, acred);
- if (code)
- return code;
- afs_InitFakeStat(&fakestat);
- code = afs_TryEvalFakeStat(&avc, &fakestat, &treq);
- if (code) {
- afs_PutFakeStat(&fakestat);
- return code;
- }
-
- code = afs_CopyOutAttrs(avc, attrs);
- afs_PutFakeStat(&fakestat);
- return code;
- }
-#if defined(AFS_SUN5_ENV)
- if (flags & ATTR_HINT) {
- code = afs_CopyOutAttrs(avc, attrs);
- return code;
- }
-#endif
-#if defined(AFS_DARWIN_ENV)
- if (avc->states & CUBCinit) {
- code = afs_CopyOutAttrs(avc, attrs);
- return code;
- }
-#endif
-
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&avc->pvnLock, avc);
-#endif
-
- if (afs_shuttingdown)
- return EIO;
-
- if (!(avc->states & CStatd)) {
- if (!(code = afs_InitReq(&treq, acred))) {
- code = afs_VerifyVCache2(avc, &treq);
- inited = 1;
- }
- } else
- code = 0;
-
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- if (code == 0)
- osi_FlushPages(avc, acred);
- afs_BozonUnlock(&avc->pvnLock, avc);
-#endif
-
-
- if (code == 0) {
- osi_FlushText(avc); /* only needed to flush text if text locked last time */
- code = afs_CopyOutAttrs(avc, attrs);
-
- if (afs_nfsexporter) {
- if (!inited) {
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- inited = 1;
- }
- if (AFS_NFSXLATORREQ(acred)) {
- if ((vType(avc) != VDIR)
- && !afs_AccessOK(avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS |
- CMB_ALLOW_EXEC_AS_READ)) {
- return EACCES;
- }
- if (avc->mvstat == 2) {
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- attrs->va_mtime.tv_nsec += ((++avc->xlatordv) * 1000);
-#else
- attrs->va_mtime.tv_usec += ++avc->xlatordv;
-#endif
- }
- }
- if ((au = afs_FindUser(treq.uid, -1, READ_LOCK))) {
- register struct afs_exporter *exporter = au->exporter;
-
- if (exporter && !(afs_nfsexporter->exp_states & EXP_UNIXMODE)) {
- unsigned int ubits;
- /*
- * If the remote user wishes to enforce default Unix mode semantics,
- * like in the nfs exporter case, we OR in the user bits
- * into the group and other bits. We need to do this
- * because there is no RFS_ACCESS call and thus nfs
- * clients implement nfs_access by interpreting the
- * mode bits in the traditional way, which of course
- * loses with afs.
- */
- ubits = (attrs->va_mode & 0700) >> 6;
- attrs->va_mode = attrs->va_mode | ubits | (ubits << 3);
- /* If it's the root of AFS, replace the inode number with the
- * inode number of the mounted on directory; otherwise this
- * confuses getwd()... */
-#ifdef AFS_LINUX22_ENV
- if (avc == afs_globalVp) {
- struct inode *ip = avc->v.i_sb->s_root->d_inode;
- attrs->va_nodeid = ip->i_ino;
- }
-#else
- if (AFSTOV(avc)->v_flag & VROOT) {
- struct vnode *vp = AFSTOV(avc);
-
- vp = vp->v_vfsp->vfs_vnodecovered;
- if (vp) { /* Ignore weird failures */
-#ifdef AFS_SGI62_ENV
- attrs->va_nodeid = VnodeToIno(vp);
-#else
- struct inode *ip;
-
- ip = (struct inode *)VTOI(vp);
- if (ip) /* Ignore weird failures */
- attrs->va_nodeid = ip->i_number;
-#endif
- }
- }
-#endif /* AFS_LINUX22_ENV */
- }
- afs_PutUser(au, READ_LOCK);
- }
- }
- }
- if (!code)
- return 0;
- code = afs_CheckCode(code, &treq, 14);
- return code;
-}
-
-/* convert a Unix request into a status store request */
-int
-afs_VAttrToAS(register struct vcache *avc, register struct vattr *av,
- register struct AFSStoreStatus *as)
-{
- register int mask;
- mask = 0;
- AFS_STATCNT(afs_VAttrToAS);
-#if defined(AFS_AIX_ENV)
-/* Boy, was this machine dependent bogosity hard to swallow????.... */
- if (av->va_mode != -1) {
-#else
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (av->va_mask & AT_MODE) {
-#else
- if (av->va_mode != ((unsigned short)-1)) {
-#endif
-#endif
- mask |= AFS_SETMODE;
- as->UnixModeBits = av->va_mode & 0xffff;
- if (avc->states & CForeign) {
- ObtainWriteLock(&avc->lock, 127);
- afs_FreeAllAxs(&(avc->Access));
- ReleaseWriteLock(&avc->lock);
- }
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (av->va_mask & AT_GID) {
-#else
-#if (defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV))
-#if defined(AFS_HPUX102_ENV)
- if (av->va_gid != GID_NO_CHANGE) {
-#else
- if (av->va_gid != ((unsigned short)-1)) {
-#endif
-#else
- if (av->va_gid != -1) {
-#endif
-#endif /* AFS_SUN5_ENV */
- mask |= AFS_SETGROUP;
- as->Group = av->va_gid;
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (av->va_mask & AT_UID) {
-#else
-#if (defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV))
-#if defined(AFS_HPUX102_ENV)
- if (av->va_uid != UID_NO_CHANGE) {
-#else
- if (av->va_uid != ((unsigned short)-1)) {
-#endif
-#else
- if (av->va_uid != -1) {
-#endif
-#endif /* AFS_SUN5_ENV */
- mask |= AFS_SETOWNER;
- as->Owner = av->va_uid;
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (av->va_mask & AT_MTIME) {
-#else
- if (av->va_mtime.tv_sec != -1) {
-#endif
- mask |= AFS_SETMODTIME;
-#ifndef AFS_SGI_ENV
-#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if (av->va_mtime.tv_nsec == -1)
-#else
- if (av->va_mtime.tv_usec == -1)
-#endif
- as->ClientModTime = osi_Time(); /* special Sys V compat hack for Suns */
- else
-#endif
- as->ClientModTime = av->va_mtime.tv_sec;
- }
- as->Mask = mask;
- return 0;
-}
-
-/* We don't set CDirty bit in avc->states because setattr calls WriteVCache
- * synchronously, therefore, it's not needed.
- */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-int
-afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs, int flags,
- struct AFS_UCRED *acred)
-#else
-int
-afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
- struct AFS_UCRED *acred)
-#endif
-{
- struct vrequest treq;
- struct AFSStoreStatus astat;
- register afs_int32 code;
- struct afs_fakestat_state fakestate;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_setattr);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- afs_Trace4(afs_iclSetp, CM_TRACE_SETATTR, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, attrs->va_mask, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(attrs->va_size), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
-#else
- afs_Trace4(afs_iclSetp, CM_TRACE_SETATTR, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, attrs->va_mode, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(attrs->va_size), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
-#endif
- if ((code = afs_InitReq(&treq, acred)))
- return code;
-
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code)
- goto done;
-
- if (avc->states & CRO) {
- code = EROFS;
- goto done;
- }
-#if defined(AFS_SGI_ENV)
- /* ignore ATTR_LAZY calls - they are really only for keeping
- * the access/mtime of mmaped files up to date
- */
- if (flags & ATTR_LAZY)
- goto done;
-#endif
-#ifndef AFS_DEC_ENV
- /* if file size has changed, we need write access, otherwise (e.g.
- * chmod) give it a shot; if it fails, we'll discard the status
- * info.
- *
- * Note that Ultrix actually defines ftruncate of a file you have open to
- * be O.K., and does the proper access checks itself in the truncate
- * path (unlike BSD or SUNOS), so we skip this check for Ultrix.
- *
- */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (attrs->va_mask & AT_SIZE) {
-#else
-#ifdef AFS_OSF_ENV
- if (attrs->va_size != VNOVAL) {
-#else
-#ifdef AFS_AIX41_ENV
- if (attrs->va_size != -1) {
-#else
- if (attrs->va_size != ~0) {
-#endif
-#endif
-#endif
- if (!afs_AccessOK(avc, PRSFS_WRITE, &treq, DONT_CHECK_MODE_BITS)) {
- code = EACCES;
- goto done;
- }
- }
-#endif
-
- afs_VAttrToAS(avc, attrs, &astat); /* interpret request */
- code = 0;
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&avc->pvnLock, avc);
-#endif
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if (AFS_NFSXLATORREQ(acred)) {
- avc->execsOrWriters++;
- }
-#endif
-
-#if defined(AFS_SGI_ENV)
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX22_ENV)
- if (attrs->va_mask & AT_SIZE) {
-#else
-#if defined(AFS_OSF_ENV)
- if (attrs->va_size != VNOVAL) {
-#else /* AFS_OSF_ENV */
- if (attrs->va_size != -1) {
-#endif
-#endif
- afs_size_t tsize = attrs->va_size;
- ObtainWriteLock(&avc->lock, 128);
- avc->states |= CDirty;
- code = afs_TruncateAllSegments(avc, tsize, &treq, acred);
- /* if date not explicitly set by this call, set it ourselves, since we
- * changed the data */
- if (!(astat.Mask & AFS_SETMODTIME)) {
- astat.Mask |= AFS_SETMODTIME;
- astat.ClientModTime = osi_Time();
- }
- if (code == 0) {
- if (((avc->execsOrWriters <= 0) && (avc->states & CCreating) == 0)
- || (avc->execsOrWriters == 1 && AFS_NFSXLATORREQ(acred))) {
- code = afs_StoreAllSegments(avc, &treq, AFS_ASYNC);
- if (!code)
- avc->states &= ~CDirty;
- }
- } else
- avc->states &= ~CDirty;
-
- ReleaseWriteLock(&avc->lock);
- hzero(avc->flushDV);
- osi_FlushText(avc); /* do this after releasing all locks */
-#ifdef AFS_DEC_ENV
- /* in case we changed the size here, propagate it to gp->g_size */
- afs_gfshack((struct gnode *)avc);
-#endif
- }
- if (code == 0) {
- ObtainSharedLock(&avc->lock, 16); /* lock entry */
- code = afs_WriteVCache(avc, &astat, &treq); /* send request */
- ReleaseSharedLock(&avc->lock); /* release lock */
- }
- if (code) {
- ObtainWriteLock(&afs_xcbhash, 487);
- afs_DequeueCallback(avc);
- avc->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- /* error? erase any changes we made to vcache entry */
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if (AFS_NFSXLATORREQ(acred)) {
- avc->execsOrWriters--;
- }
-#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&avc->pvnLock, avc);
-#endif
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
- done:
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 15);
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_create
- * afs_LocalHero
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_create.c,v 1.16 2003/07/15 23:14:30 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-/* question: does afs_create need to set CDirty in the adp or the avc?
- * I think we can get away without it, but I'm not sure. Note that
- * afs_setattr is called in here for truncation.
- */
-#ifdef AFS_OSF_ENV
-int
-afs_create(struct nameidata *ndp, struct vattr *attrs)
-#else /* AFS_OSF_ENV */
-#ifdef AFS_SGI64_ENV
-int
-afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, int flags,
- int amode, struct vcache **avcp, struct AFS_UCRED *acred)
-#else /* AFS_SGI64_ENV */
-int
-afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
- enum vcexcl aexcl, int amode, struct vcache **avcp,
- struct AFS_UCRED *acred)
-#endif /* AFS_SGI64_ENV */
-#endif /* AFS_OSF_ENV */
-{
-#ifdef AFS_OSF_ENV
- register struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- enum vcexcl aexcl = NONEXCL; /* XXX - create called properly */
- int amode = 0; /* XXX - checked in higher level */
- struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
- struct ucred *acred = ndp->ni_cred;
-#endif
-
- afs_int32 origCBs, origZaps, finalZaps;
- struct vrequest treq;
- register afs_int32 code;
- register struct conn *tc;
- struct VenusFid newFid;
- struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
- struct AFSVolSync tsync;
- struct AFSCallBack CallBack;
- afs_int32 now;
- struct dcache *tdc;
- afs_size_t offset, len;
- struct server *hostp = 0;
- struct vcache *tvc;
- struct volume *volp = 0;
- struct afs_fakestat_state fakestate;
- XSTATS_DECLS OSI_VC_CONVERT(adp)
-
-
- AFS_STATCNT(afs_create);
- if ((code = afs_InitReq(&treq, acred)))
- goto done2;
-
- afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode);
-
- afs_InitFakeStat(&fakestate);
-
-#ifdef AFS_SGI65_ENV
- /* If avcp is passed not null, it's the old reference to this file.
- * We can use this to avoid create races. For now, just decrement
- * the reference count on it.
- */
- if (*avcp) {
- AFS_RELE(AFSTOV(*avcp));
- *avcp = NULL;
- }
-#endif
-
- if (strlen(aname) > AFSNAMEMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
-
- if (!afs_ENameOK(aname)) {
- code = EINVAL;
- goto done;
- }
- switch (attrs->va_type) {
- case VBLK:
- case VCHR:
-#if !defined(AFS_SUN5_ENV)
- case VSOCK:
-#endif
- case VFIFO:
- /* We don't support special devices or FIFOs */
- code = EINVAL;
- goto done;
- default:
- ;
- }
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (code)
- goto done;
- tagain:
- code = afs_VerifyVCache(adp, &treq);
- if (code)
- goto done;
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
- code = EROFS;
- goto done;
- }
-
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
- ObtainWriteLock(&adp->lock, 135);
- if (tdc)
- ObtainSharedLock(&tdc->lock, 630);
-
- /*
- * Make sure that the data in the cache is current. We may have
- * received a callback while we were waiting for the write lock.
- */
- if (!(adp->states & CStatd)
- || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
- ReleaseWriteLock(&adp->lock);
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- goto tagain;
- }
- if (tdc) {
- /* see if file already exists. If it does, we only set
- * the size attributes (to handle O_TRUNC) */
- code = afs_dir_Lookup(&tdc->f.inode, aname, &newFid.Fid); /* use dnlc first xxx */
- if (code == 0) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseWriteLock(&adp->lock);
-#ifdef AFS_SGI64_ENV
- if (flags & VEXCL) {
-#else
- if (aexcl != NONEXCL) {
-#endif
- code = EEXIST; /* file exists in excl mode open */
- goto done;
- }
- /* found the file, so use it */
- newFid.Cell = adp->fid.Cell;
- newFid.Fid.Volume = adp->fid.Fid.Volume;
- tvc = NULL;
- if (newFid.Fid.Unique == 0) {
- tvc = afs_LookupVCache(&newFid, &treq, NULL, adp, aname);
- }
- if (!tvc) /* lookup failed or wasn't called */
- tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
-
- if (tvc) {
- /* if the thing exists, we need the right access to open it.
- * we must check that here, since no other checks are
- * made by the open system call */
- len = attrs->va_size; /* only do the truncate */
- /*
- * We used to check always for READ access before; the
- * problem is that we will fail if the existing file
- * has mode -w-w-w, which is wrong.
- */
- if ((amode & VREAD)
- && !afs_AccessOK(tvc, PRSFS_READ, &treq, CHECK_MODE_BITS)) {
- afs_PutVCache(tvc);
- code = EACCES;
- goto done;
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if ((amode & VWRITE) || (attrs->va_mask & AT_SIZE))
-#else
- if ((amode & VWRITE) || len != 0xffffffff)
-#endif
- {
- /* needed for write access check */
- tvc->parentVnode = adp->fid.Fid.Vnode;
- tvc->parentUnique = adp->fid.Fid.Unique;
- /* need write mode for these guys */
- if (!afs_AccessOK
- (tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
- afs_PutVCache(tvc);
- code = EACCES;
- goto done;
- }
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if (attrs->va_mask & AT_SIZE)
-#else
- if (len != 0xffffffff)
-#endif
- {
- if (vType(tvc) != VREG) {
- afs_PutVCache(tvc);
- code = EISDIR;
- goto done;
- }
- /* do a truncate */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- attrs->va_mask = AT_SIZE;
-#else
- VATTR_NULL(attrs);
-#endif
- attrs->va_size = len;
- ObtainWriteLock(&tvc->lock, 136);
- tvc->states |= CCreating;
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-#if defined(AFS_SGI64_ENV)
- code =
- afs_setattr(VNODE_TO_FIRST_BHV((vnode_t *) tvc),
- attrs, 0, acred);
-#else
- code = afs_setattr(tvc, attrs, 0, acred);
-#endif /* AFS_SGI64_ENV */
-#else /* SUN5 || SGI */
- code = afs_setattr(tvc, attrs, acred);
-#endif /* SUN5 || SGI */
- ObtainWriteLock(&tvc->lock, 137);
- tvc->states &= ~CCreating;
- ReleaseWriteLock(&tvc->lock);
- if (code) {
- afs_PutVCache(tvc);
- goto done;
- }
- }
- *avcp = tvc;
- } else
- code = ENOENT; /* shouldn't get here */
- /* make sure vrefCount bumped only if code == 0 */
- goto done;
- }
- }
-
- /* if we create the file, we don't do any access checks, since
- * that's how O_CREAT is supposed to work */
- if (adp->states & CForeign) {
- origCBs = afs_allCBs;
- origZaps = afs_allZaps;
- } else {
- origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
- origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
- }
- InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
- InStatus.ClientModTime = osi_Time();
- InStatus.Group = (afs_int32) acred->cr_gid;
- if (AFS_NFSXLATORREQ(acred)) {
- /*
- * XXX The following is mainly used to fix a bug in the HP-UX
- * nfs client where they create files with mode of 0 without
- * doing any setattr later on to fix it. * XXX
- */
-#if defined(AFS_AIX_ENV)
- if (attrs->va_mode != -1) {
-#else
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if (attrs->va_mask & AT_MODE) {
-#else
- if (attrs->va_mode != ((unsigned short)-1)) {
-#endif
-#endif
- if (!attrs->va_mode)
- attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
- }
- }
- InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- hostp = tc->srvr->server; /* remember for callback processing */
- now = osi_Time();
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_CreateFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
- aname, &InStatus, (struct AFSFid *)
- &newFid.Fid, &OutFidStatus, &OutDirStatus,
- &CallBack, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- CallBack.ExpirationTime += now;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_CREATEFILE,
- SHARED_LOCK, NULL));
-
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
- if (code == EEXIST && aexcl == NONEXCL) {
- /* This lookup was handled in the common vn_open code in the
- * vnode layer */
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- ReleaseWriteLock(&adp->lock);
- goto done;
- }
-#else /* AFS_OSF_ENV */
-#ifdef AFS_SGI64_ENV
- if (code == EEXIST && !(flags & VEXCL)) {
-#else /* AFS_SGI64_ENV */
- if (code == EEXIST && aexcl == NONEXCL) {
-#endif /* AFS_SGI64_ENV */
- /* if we get an EEXIST in nonexcl mode, just do a lookup */
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- ReleaseWriteLock(&adp->lock);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-#if defined(AFS_SGI64_ENV)
- code =
- afs_lookup(VNODE_TO_FIRST_BHV((vnode_t *) adp), aname, avcp, NULL,
- 0, NULL, acred);
-#else
- code = afs_lookup(adp, aname, avcp, NULL, 0, NULL, acred);
-#endif /* AFS_SGI64_ENV */
-#else /* SUN5 || SGI */
- code = afs_lookup(adp, aname, avcp, acred);
-#endif /* SUN5 || SGI */
- goto done;
- }
-#endif /* AFS_OSF_ENV */
- if (code) {
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 488);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- goto done;
- }
- /* otherwise, we should see if we can make the change to the dir locally */
- if (tdc)
- UpgradeSToWLock(&tdc->lock, 631);
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
- if (code) {
- ZapDCE(tdc);
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- newFid.Cell = adp->fid.Cell;
- newFid.Fid.Volume = adp->fid.Fid.Volume;
- ReleaseWriteLock(&adp->lock);
- volp = afs_FindVolume(&newFid, READ_LOCK);
-
- /* New tricky optimistic callback handling algorithm for file creation works
- * as follows. We create the file essentially with no locks set at all. File
- * server may thus handle operations from others cache managers as well as from
- * this very own cache manager that reference the file in question before
- * we managed to create the cache entry. However, if anyone else changes
- * any of the status information for a file, we'll see afs_evenCBs increase
- * (files always have even fids). If someone on this workstation manages
- * to do something to the file, they'll end up having to create a cache
- * entry for the new file. Either we'll find it once we've got the afs_xvcache
- * lock set, or it was also *deleted* the vnode before we got there, in which case
- * we will find evenZaps has changed, too. Thus, we only assume we have the right
- * status information if no callbacks or vnode removals have occurred to even
- * numbered files from the time the call started until the time that we got the xvcache
- * lock set. Of course, this also assumes that any call that modifies a file first
- * gets a write lock on the file's vnode, but if that weren't true, the whole cache manager
- * would fail, since no call would be able to update the local vnode status after modifying
- * a file on a file server. */
- ObtainWriteLock(&afs_xvcache, 138);
- if (adp->states & CForeign)
- finalZaps = afs_allZaps; /* do this before calling newvcache */
- else
- finalZaps = afs_evenZaps; /* do this before calling newvcache */
- /* don't need to call RemoveVCB, since only path leaving a callback is the
- * one where we pass through afs_NewVCache. Can't have queued a VCB unless
- * we created and freed an entry between file creation time and here, and the
- * freeing of the vnode will change evenZaps. Don't need to update the VLRU
- * queue, since the find will only succeed in the event of a create race, and
- * then the vcache will be at the front of the VLRU queue anyway... */
- if (!(tvc = afs_FindVCache(&newFid, 0, DO_STATS))) {
- tvc = afs_NewVCache(&newFid, hostp);
- if (tvc) {
- int finalCBs;
- ObtainWriteLock(&tvc->lock, 139);
-
- ObtainWriteLock(&afs_xcbhash, 489);
- finalCBs = afs_evenCBs;
- /* add the callback in */
- if (adp->states & CForeign) {
- tvc->states |= CForeign;
- finalCBs = afs_allCBs;
- }
- if (origCBs == finalCBs && origZaps == finalZaps) {
- tvc->states |= CStatd; /* we've fake entire thing, so don't stat */
- tvc->states &= ~CBulkFetching;
- tvc->cbExpires = CallBack.ExpirationTime;
- afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
- } else {
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CUnique);
- tvc->callback = 0;
- if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- }
- ReleaseWriteLock(&afs_xcbhash);
- afs_ProcessFS(tvc, &OutFidStatus, &treq);
- ReleaseWriteLock(&tvc->lock);
- *avcp = tvc;
- code = 0;
- } else
- code = ENOENT;
- } else {
- /* otherwise cache entry already exists, someone else must
- * have created it. Comments used to say: "don't need write
- * lock to *clear* these flags" but we should do it anyway.
- * Code used to clear stat bit and callback, but I don't see
- * the point -- we didn't have a create race, somebody else just
- * snuck into NewVCache before we got here, probably a racing
- * lookup.
- */
- *avcp = tvc;
- code = 0;
- }
- ReleaseWriteLock(&afs_xvcache);
-
- done:
- if (volp)
- afs_PutVolume(volp, READ_LOCK);
-
- if (code == 0) {
- afs_AddMarinerName(aname, *avcp);
- /* return the new status in vattr */
- afs_CopyOutAttrs(*avcp, attrs);
- }
-#ifdef AFS_OSF_ENV
- if (!code && !strcmp(aname, "core"))
- tvc->states |= CCore1;
-#endif
-
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 20);
-
- done2:
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
-#endif /* AFS_OSF_ENV */
-
- return code;
-}
-
-
-/*
- * Check to see if we can track the change locally: requires that
- * we have sufficiently recent info in data cache. If so, we
- * know the new DataVersion number, and place it correctly in both the
- * data and stat cache entries. This routine returns 1 if we should
- * do the operation locally, and 0 otherwise.
- *
- * This routine must be called with the stat cache entry write-locked,
- * and dcache entry write-locked.
- */
-int
-afs_LocalHero(register struct vcache *avc, register struct dcache *adc,
- register AFSFetchStatus * astat, register int aincr)
-{
- register afs_int32 ok;
- afs_hyper_t avers;
-
- AFS_STATCNT(afs_LocalHero);
- hset64(avers, astat->dataVersionHigh, astat->DataVersion);
- /* this *is* the version number, no matter what */
- if (adc) {
- ok = (hsame(avc->m.DataVersion, adc->f.versionNo) && avc->callback
- && (avc->states & CStatd) && avc->cbExpires >= osi_Time());
- } else {
- ok = 0;
- }
-#if defined(AFS_SGI_ENV)
- osi_Assert(avc->v.v_type == VDIR);
-#endif
- /* The bulk status code used the length as a sequence number. */
- /* Don't update the vcache entry unless the stats are current. */
- if (avc->states & CStatd) {
- hset(avc->m.DataVersion, avers);
-#ifdef AFS_64BIT_CLIENT
- FillInt64(avc->m.Length, astat->Length_hi, astat->Length);
-#else /* AFS_64BIT_ENV */
- avc->m.Length = astat->Length;
-#endif /* AFS_64BIT_ENV */
- avc->m.Date = astat->ClientModTime;
- }
- if (ok) {
- /* we've been tracking things correctly */
- adc->dflags |= DFEntryMod;
- adc->f.versionNo = avers;
- return 1;
- } else {
- if (adc) {
- ZapDCE(adc);
- DZap(&adc->f.inode);
- }
- if (avc->states & CStatd) {
- osi_dnlc_purgedp(avc);
- }
- 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
- */
-
-/*
- * afs_vnop_dirops.c - make and remove directories
- *
- * Implements:
- *
- * afs_mkdir
- * afs_rmdir
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_dirops.c,v 1.14 2003/08/29 22:00:04 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-extern afs_rwlock_t afs_xvcache;
-extern afs_rwlock_t afs_xcbhash;
-
-/* don't set CDirty in here because RPC is called synchronously */
-
-int
-#ifdef AFS_OSF_ENV
-afs_mkdir(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs;
-{
- register struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- register struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
-afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
- OSI_VC_DECL(adp);
- register struct vcache **avcp;
- char *aname;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
-#endif
- struct vrequest treq;
- register afs_int32 code;
- register struct conn *tc;
- struct VenusFid newFid;
- register struct dcache *tdc;
- afs_size_t offset, len;
- register struct vcache *tvc;
- struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- afs_int32 now;
- struct afs_fakestat_state fakestate;
- XSTATS_DECLS OSI_VC_CONVERT(adp)
-
- AFS_STATCNT(afs_mkdir);
- afs_Trace2(afs_iclSetp, CM_TRACE_MKDIR, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, aname);
-
- if ((code = afs_InitReq(&treq, acred)))
- goto done2;
- afs_InitFakeStat(&fakestate);
-
- if (strlen(aname) > AFSNAMEMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
-
- if (!afs_ENameOK(aname)) {
- code = EINVAL;
- goto done;
- }
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (code)
- goto done;
- code = afs_VerifyVCache(adp, &treq);
- if (code)
- goto done;
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
- code = EROFS;
- goto done;
- }
-
- InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
- InStatus.ClientModTime = osi_Time();
- InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
- InStatus.Group = (afs_int32) acred->cr_gid;
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
- ObtainWriteLock(&adp->lock, 153);
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
- now = osi_Time();
- RX_AFS_GUNLOCK();
- code =
- RXAFS_MakeDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
- &InStatus, (struct AFSFid *)&newFid.Fid,
- &OutFidStatus, &OutDirStatus, &CallBack,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- CallBack.ExpirationTime += now;
- /* DON'T forget to Set the callback value... */
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_MAKEDIR,
- SHARED_LOCK, NULL));
-
- if (code) {
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 490);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- if (tdc)
- afs_PutDCache(tdc);
- goto done;
- }
- /* otherwise, we should see if we can make the change to the dir locally */
- if (tdc)
- ObtainWriteLock(&tdc->lock, 632);
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
- if (code) {
- ZapDCE(tdc); /* surprise error -- use invalid value */
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- adp->m.LinkCount = OutDirStatus.LinkCount;
- newFid.Cell = adp->fid.Cell;
- newFid.Fid.Volume = adp->fid.Fid.Volume;
- ReleaseWriteLock(&adp->lock);
- /* now we're done with parent dir, create the real dir's cache entry */
- tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
- if (tvc) {
- code = 0;
- *avcp = tvc;
- } else
- code = ENOENT;
- done:
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 26);
- done2:
-#ifdef AFS_OSF_ENV
- AFS_RELE(ndp->ni_dvp);
-#endif /* AFS_OSF_ENV */
- return code;
-}
-
-
-int
-#ifdef AFS_OSF_ENV
-afs_rmdir(ndp)
- struct nameidata *ndp;
-{
- register struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
-/* don't set CDirty in here because RPC is called synchronously */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_rmdir(OSI_VC_ARG(adp), aname, cdirp, acred)
- struct vnode *cdirp;
-#else
-afs_rmdir(adp, aname, acred)
-#endif
- OSI_VC_DECL(adp);
- char *aname;
- struct AFS_UCRED *acred;
-{
-#endif
- struct vrequest treq;
- register struct dcache *tdc;
- register struct vcache *tvc = NULL;
- register afs_int32 code;
- register struct conn *tc;
- afs_size_t offset, len;
- struct AFSFetchStatus OutDirStatus;
- struct AFSVolSync tsync;
- struct afs_fakestat_state fakestate;
- XSTATS_DECLS OSI_VC_CONVERT(adp)
-
- AFS_STATCNT(afs_rmdir);
-
- afs_Trace2(afs_iclSetp, CM_TRACE_RMDIR, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, aname);
-
- if ((code = afs_InitReq(&treq, acred)))
- goto done2;
- afs_InitFakeStat(&fakestate);
-
- if (strlen(aname) > AFSNAMEMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
-
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (code)
- goto done;
-
- code = afs_VerifyVCache(adp, &treq);
- if (code)
- goto done;
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
- code = EROFS;
- goto done;
- }
-
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
- ObtainWriteLock(&adp->lock, 154);
- if (tdc)
- ObtainSharedLock(&tdc->lock, 633);
- if (tdc && (adp->states & CForeign)) {
- struct VenusFid unlinkFid;
-
- unlinkFid.Fid.Vnode = 0;
- code = afs_dir_Lookup(&tdc->f.inode, aname, &unlinkFid.Fid);
- if (code == 0) {
- afs_int32 cached = 0;
-
- unlinkFid.Cell = adp->fid.Cell;
- unlinkFid.Fid.Volume = adp->fid.Fid.Volume;
- if (unlinkFid.Fid.Unique == 0) {
- tvc =
- afs_LookupVCache(&unlinkFid, &treq, &cached, adp, aname);
- } else {
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&unlinkFid, 0, 1 /* do xstats */ );
- ReleaseReadLock(&afs_xvcache);
- }
- }
- }
-
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_RemoveDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
- &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_REMOVEDIR,
- SHARED_LOCK, NULL));
-
- if (code) {
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 491);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- goto done;
- }
- /* here if rpc worked; update the in-core link count */
- adp->m.LinkCount = OutDirStatus.LinkCount;
- if (tdc)
- UpgradeSToWLock(&tdc->lock, 634);
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Delete(&tdc->f.inode, aname);
- if (code) {
- ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc); /* drop ref count */
- }
-
-
- if (tvc) {
- osi_dnlc_purgedp(tvc); /* get rid of any entries for this directory */
- afs_symhint_inval(tvc);
- } else
- osi_dnlc_remove(adp, aname, 0);
-
- if (tvc) {
- ObtainWriteLock(&tvc->lock, 155);
- tvc->states &= ~CUnique; /* For the dfs xlator */
- ReleaseWriteLock(&tvc->lock);
- afs_PutVCache(tvc);
- }
- ReleaseWriteLock(&adp->lock);
- /* don't worry about link count since dirs can not be hardlinked */
- code = 0;
-
- done:
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 27);
- done2:
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(ndp->ni_vp);
-#endif /* AFS_OSF_ENV */
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_fid
- *
- * afs_vptofh (DUX) is now in DUX/osi_vfsops.c
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_fid.c,v 1.11 2003/07/15 23:14:30 shadow Exp $");
-
-#if !defined(AFS_DUX40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_OBSD_ENV)
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-
-int afs_fid_vnodeoverflow = 0, afs_fid_uniqueoverflow = 0;
-
-/*
- * afs_fid
- *
- * afs_fid 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.
- */
-
-#ifdef AFS_AIX41_ENV
-int afs_iauth_initd = 0;
-#define USE_SMALLFID(C) (afs_iauth_initd && AFS_NFSXLATORREQ(C))
-#endif
-
-
-extern int afs_NFSRootOnly; /* 1 => only allow NFS mounts of /afs. */
-
-int
-#if !defined(AFS_DEC_ENV) && !defined(AFS_ATHENA_ENV)
-#ifdef AFS_AIX41_ENV
-afs_fid(OSI_VC_ARG(avc), fidpp, credp)
- struct ucred *credp;
-#else
-afs_fid(OSI_VC_ARG(avc), fidpp)
-#endif /* AFS_AIX41_ENV */
-OSI_VC_DECL(avc);
-#if defined(AFS_AIX_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN54_ENV)
- struct fid *fidpp;
-#else
- struct fid **fidpp;
-#endif
-{
- struct SmallFid Sfid;
- long addr[2];
- register struct cell *tcell;
- extern struct vcache *afs_globalVp;
- int SizeOfSmallFid = SIZEOF_SMALLFID;
- int rootvp = 0;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_fid);
-
- if (afs_shuttingdown)
- return EIO;
-
- if (afs_NFSRootOnly && (avc == afs_globalVp))
- rootvp = 1;
- if (!afs_NFSRootOnly || rootvp
-#ifdef AFS_AIX41_ENV
- || USE_SMALLFID(credp)
-#endif
- ) {
- tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
- Sfid.Volume = avc->fid.Fid.Volume;
- Sfid.Vnode = 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 {
-#if defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64))
- addr[1] = (long)AFS_XLATOR_MAGIC << 48;
-#else /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
- addr[1] = AFS_XLATOR_MAGIC;
- SizeOfSmallFid = sizeof(addr);
-#endif /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
- addr[0] = (long)avc;
-#ifndef AFS_AIX41_ENV
- /* No post processing, so don't hold ref count. */
- VN_HOLD(AFSTOV(avc));
-#endif
- }
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN54_ENV)
- /* Use the fid pointer passed to us. */
- fidpp->fid_len = SizeOfSmallFid;
-
- if (afs_NFSRootOnly) {
- if (rootvp
-#ifdef AFS_AIX41_ENV
- || USE_SMALLFID(credp)
-#endif
- ) {
- memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
- } else {
- memcpy(fidpp->fid_data, (caddr_t) addr, SizeOfSmallFid);
- }
- } else {
- memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
- }
-#else
- /* malloc a fid pointer ourselves. */
- *fidpp = (struct fid *)AFS_KALLOC(SizeOfSmallFid + 2);
- (*fidpp)->fid_len = SizeOfSmallFid;
- if (afs_NFSRootOnly) {
- if (rootvp) {
- memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
- } else {
- memcpy((*fidpp)->fid_data, (char *)addr, SizeOfSmallFid);
- }
- } else {
- memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
- }
-#endif
- return (0);
-}
-#endif
-
-
-#endif /* !AFS_DUX40_ENV && !AFS_LINUX20_ENV */
+++ /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
- */
-
-/*
- * Implements:
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_flock.c,v 1.24 2003/07/15 23:14:30 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-/* Static prototypes */
-static int HandleGetLock(register struct vcache *avc,
- register struct AFS_FLOCK *af,
- register struct vrequest *areq, int clid);
-static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
-static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
- register struct SimpleLocks *alp, int onlymine,
- int clid);
-static void DoLockWarning(void);
-
-/* int clid; * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
-void
-lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
-{
-#if defined(AFS_SUN5_ENV)
- register proc_t *procp = ttoproc(curthread);
-#else
-#if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#ifdef AFS_SGI_ENV
- struct proc *procp = OSI_GET_CURRENT_PROCP();
-#else
- struct proc *procp = u.u_procp;
-#endif /* AFS_SGI_ENV */
-#endif
-#endif
-#if defined(AFS_SGI65_ENV)
- flid_t flid;
- get_current_flid(&flid);
-#endif
-
- if (slp) {
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX41_ENV
- slp->sysid = 0;
- slp->pid = getpid();
-#else
- slp->sysid = u.u_sysid;
- slp->pid = u.u_epid;
-#endif
-#else
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN53_ENV
- slp->sysid = 0;
- slp->pid = procp->p_pid;
-#else
- slp->sysid = procp->p_sysid;
- slp->pid = procp->p_epid;
-#endif
-#else
-#if defined(AFS_SGI_ENV)
-#ifdef AFS_SGI65_ENV
- slp->sysid = flid.fl_sysid;
-#else
- slp->sysid = OSI_GET_CURRENT_SYSID();
-#endif
- slp->pid = clid;
-#else
-#if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- slp->pid = clid;
-#else
-#if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
- slp->pid = getpid();
-#else
- slp->pid = u.u_procp->p_pid;
-#endif
-#endif
-#endif /* AFS_AIX_ENV */
-#endif /* AFS_AIX32_ENV */
-#endif
- } else {
-#if defined(AFS_AIX32_ENV)
-#ifdef AFS_AIX41_ENV
- flock->l_sysid = 0;
- flock->l_pid = getpid();
-#else
- flock->l_sysid = u.u_sysid;
- flock->l_pid = u.u_epid;
-#endif
-#else
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN53_ENV
- flock->l_sysid = 0;
- flock->l_pid = procp->p_pid;
-#else
- flock->l_sysid = procp->p_sysid;
- flock->l_pid = procp->p_epid;
-#endif
-#else
-#if defined(AFS_SGI_ENV)
-#ifdef AFS_SGI65_ENV
- flock->l_sysid = flid.fl_sysid;
-#else
- flock->l_sysid = OSI_GET_CURRENT_SYSID();
-#endif
- flock->l_pid = clid;
-#else
-#if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- flock->l_pid = clid;
-#else
-#if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
- flock->l_pid = getpid();
-#else
- flock->l_pid = u.u_procp->p_pid;
-#endif
-#endif
-#endif
-#endif /* AFS_AIX_ENV */
-#endif /* AFS_AIX32_ENV */
- }
-}
-
-/* return 1 (true) if specified flock does not match alp (if
- * specified), or any of the slp structs (if alp == 0)
- */
-/* I'm not sure that the comparsion of flock->pid to p_ppid
- * is correct. Should that be a comparision of alp (or slp) ->pid
- * to p_ppid? Especially in the context of the lower loop, where
- * the repeated comparison doesn't make much sense...
- */
-/* onlymine - don't match any locks which are held by my parent */
-/* clid - only irix 6.5 */
-
-static int
-lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
- register struct SimpleLocks *alp, int onlymine, int clid)
-{
- register struct SimpleLocks *slp;
-#if defined(AFS_SUN5_ENV)
- register proc_t *procp = ttoproc(curthread);
-#else
-#if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#ifdef AFS_SGI64_ENV
- struct proc *procp = curprocp;
-#else /* AFS_SGI64_ENV */
- struct proc *procp = u.u_procp;
-#endif /* AFS_SGI64_ENV */
-#endif
-#endif
-
- if (alp) {
-#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- if (flock1->l_sysid != alp->sysid) {
- return 1;
- }
-#endif
- if ((flock1->l_pid == alp->pid) ||
-#if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
- (!onlymine && (flock1->l_pid == getppid()))
-#else
-#if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- /* XXX check this. used to be *only* irix for some reason. */
- (!onlymine && (flock1->l_pid == clid))
-#else
- (!onlymine && (flock1->l_pid == procp->p_ppid))
-#endif
-#endif
- ) {
- return 0;
- }
- return 1;
- }
-
- for (slp = vp->slocks; slp; slp = slp->next) {
-#if defined(AFS_HAVE_FLOCK_SYSID)
- if (flock1->l_sysid != slp->sysid) {
- continue;
- }
-#endif
- if (flock1->l_pid == slp->pid) {
- return 0;
- }
- }
- return (1); /* failure */
-}
-
-
-/* we don't send multiple read flocks to the server, but rather just count
- them up ourselves. Of course, multiple write locks are incompatible.
-
- Note that we should always try to release a lock, even if we have
- a network problem sending the release command through, since often
- a lock is released on a close call, when the user can't retry anyway.
-
- After we remove it from our structure, the lock will no longer be
- kept alive, and the server should time it out within a few minutes.
-
- 94.04.13 add "force" parameter. If a child explicitly unlocks a
- file, I guess we'll permit it. however, we don't want simple,
- innocent closes by children to unlock files in the parent process.
-*/
-/* clid - nonzero on sgi sunos osf1 only */
-int
-HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
- pid_t clid, int onlymine)
-{
- struct conn *tc;
- struct SimpleLocks *slp, *tlp, **slpp;
- afs_int32 code;
- struct AFSVolSync tsync;
- afs_int32 lockType;
- struct AFS_FLOCK flock;
- XSTATS_DECLS AFS_STATCNT(HandleFlock);
- code = 0; /* default when we don't make any network calls */
- lockIdSet(&flock, NULL, clid);
-
-#if defined(AFS_SGI_ENV)
- osi_Assert(valusema(&avc->vc_rwlock) <= 0);
- osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
-#endif
- ObtainWriteLock(&avc->lock, 118);
- if (acom & LOCK_UN) {
-
-/* defect 3083 */
-
-#ifdef AFS_AIX_ENV
- /* If the lock is held exclusive, then only the owning process
- * or a child can unlock it. Use pid and ppid because they are
- * unique identifiers.
- */
- if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
-#ifdef AFS_AIX41_ENV
- if (onlymine || (getppid() != avc->ownslock)) {
-#else
- if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
-#endif
- ReleaseWriteLock(&avc->lock);
- return 0;
- }
- }
-#endif
- if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
- ReleaseWriteLock(&avc->lock);
- return 0;
- }
-#ifdef AFS_AIX_ENV
- avc->ownslock = 0;
-#endif
- if (avc->flockCount == 0) {
- ReleaseWriteLock(&avc->lock);
- return 0 /*ENOTTY*/;
- /* no lock held */
- }
- /* unlock the lock */
- if (avc->flockCount > 0) {
- slpp = &avc->slocks;
- for (slp = *slpp; slp;) {
- if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
- avc->flockCount--;
- tlp = *slpp = slp->next;
- osi_FreeSmallSpace(slp);
- slp = tlp;
- } else {
- slpp = &slp->next;
- slp = *slpp;
- }
- }
- } else if (avc->flockCount == -1) {
- afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
- avc->flockCount = 0;
- /* And remove the (only) exclusive lock entry from the list... */
- osi_FreeSmallSpace(avc->slocks);
- avc->slocks = 0;
- }
- if (avc->flockCount == 0) {
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
- RX_AFS_GUNLOCK();
- code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
- &avc->fid.Fid, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
- }
- } else {
- while (1) { /* set a new lock */
- /*
- * Upgrading from shared locks to Exclusive and vice versa
- * is a bit tricky and we don't really support it yet. But
- * we try to support the common used one which is upgrade
- * a shared lock to an exclusive for the same process...
- */
- if ((avc->flockCount > 0 && (acom & LOCK_EX))
- || (avc->flockCount == -1 && (acom & LOCK_SH))) {
- /*
- * Upgrading from shared locks to an exclusive one:
- * For now if all the shared locks belong to the
- * same process then we unlock them on the server
- * and proceed with the upgrade. Unless we change the
- * server's locking interface impl we prohibit from
- * unlocking other processes's shared locks...
- * Upgrading from an exclusive lock to a shared one:
- * Again only allowed to be done by the same process.
- */
- slpp = &avc->slocks;
- for (slp = *slpp; slp;) {
- if (!lockIdcmp2
- (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
- if (acom & LOCK_EX)
- avc->flockCount--;
- else
- avc->flockCount = 0;
- tlp = *slpp = slp->next;
- osi_FreeSmallSpace(slp);
- slp = tlp;
- } else {
- code = EWOULDBLOCK;
- slpp = &slp->next;
- slp = *slpp;
- }
- }
- if (!code && avc->flockCount == 0) {
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME
- (AFS_STATS_FS_RPCIDX_RELEASELOCK);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_ReleaseLock(tc->id,
- (struct AFSFid *)&avc->fid.
- Fid, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
- NULL));
- }
- } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
- if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- code = EWOULDBLOCK;
- } else
- code = 0;
- }
- if (code == 0) {
- /* compatible here, decide if needs to go to file server. If
- * we've already got the file locked (and thus read-locked, since
- * we've already checked for compatibility), we shouldn't send
- * the call through to the server again */
- if (avc->flockCount == 0) {
- /* we're the first on our block, send the call through */
- lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
- RX_AFS_GUNLOCK();
- code = RXAFS_SetLock(tc->id, (struct AFSFid *)
- &avc->fid.Fid, lockType,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
- NULL));
- } else
- code = 0; /* otherwise, pretend things worked */
- }
- if (code == 0) {
- slp = (struct SimpleLocks *)
- osi_AllocSmallSpace(sizeof(struct SimpleLocks));
- if (acom & LOCK_EX) {
-
-/* defect 3083 */
-
-#ifdef AFS_AIX_ENV
- /* Record unique id of process owning exclusive lock. */
- avc->ownslock = getpid();
-#endif
-
- slp->type = LockWrite;
- slp->next = NULL;
- avc->slocks = slp;
- avc->flockCount = -1;
- } else {
- slp->type = LockRead;
- slp->next = avc->slocks;
- avc->slocks = slp;
- avc->flockCount++;
- }
-
- lockIdSet(&flock, slp, clid);
- break;
- }
- /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
- if (((code == EWOULDBLOCK) || (code == EAGAIN))
- && !(acom & LOCK_NB)) {
- /* sleep for a second, allowing interrupts */
- ReleaseWriteLock(&avc->lock);
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
- code = afs_osi_Wait(1000, NULL, 1);
-#if defined(AFS_SGI_ENV)
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
- ObtainWriteLock(&avc->lock, 120);
- if (code) {
- code = EINTR; /* return this if ^C typed */
- break;
- }
- } else
- break;
- } /* while loop */
- }
- ReleaseWriteLock(&avc->lock);
- code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
- return code;
-}
-
-
-/* warn a user that a lock has been ignored */
-afs_int32 lastWarnTime = 0; /* this is used elsewhere */
-static void
-DoLockWarning(void)
-{
- register afs_int32 now;
- now = osi_Time();
-
- AFS_STATCNT(DoLockWarning);
- /* check if we've already warned someone recently */
- if (now < lastWarnTime + 120)
- return;
-
- /* otherwise, it is time to nag the user */
- lastWarnTime = now;
- afs_warn
- ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
-}
-
-
-#ifdef AFS_OSF_ENV
-afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
- struct AFS_UCRED * acred, pid_t clid, off_t offset)
-#elif defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
- struct AFS_UCRED * acred, pid_t clid)
-#else
-u_int clid = 0;
-afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
- struct AFS_UCRED * acred)
-#endif
-{
- struct vrequest treq;
- afs_int32 code;
-#ifdef AFS_OSF_ENV
- int acmd = 0;
-#endif
- struct afs_fakestat_state fakestate;
-
- AFS_STATCNT(afs_lockctl);
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- return code;
- }
-#ifdef AFS_OSF_ENV
- if (flag & VNOFLCK) {
- afs_PutFakeStat(&fakestate);
- return 0;
- }
- if (flag & CLNFLCK) {
- acmd = LOCK_UN;
- } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
- acmd = F_GETLK;
- } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
- acmd = F_SETLK;
- }
-#endif
-#if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
- if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
-#else
- if (acmd == F_GETLK) {
-#endif
- if (af->l_type == F_UNLCK) {
- afs_PutFakeStat(&fakestate);
- return 0;
- }
-#ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
- code = HandleGetLock(avc, af, &treq, clid);
-#endif
- code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
- afs_PutFakeStat(&fakestate);
- return code;
- } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
-#if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
- || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
-#else
- ) {
-#endif
- /* this next check is safer when left out, but more applications work
- * with it in. However, they fail in race conditions. The question is
- * what to do for people who don't have source to their application;
- * this way at least, they can get work done */
-#ifdef AFS_LINUX24_ENV
- if (af->l_len == OFFSET_MAX)
- af->l_len = 0; /* since some systems indicate it as EOF */
-#else
- if (af->l_len == 0x7fffffff)
- af->l_len = 0; /* since some systems indicate it as EOF */
-#ifdef AFS_LINUX_64BIT_KERNEL
- if (af->l_len == LONG_MAX)
- af->l_len = 0; /* since some systems indicate it as EOF */
-#endif
-#endif
- /* next line makes byte range locks always succeed,
- * even when they should block */
- if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
- DoLockWarning();
- afs_PutFakeStat(&fakestate);
- return 0;
- }
- /* otherwise we can turn this into a whole-file flock */
- if (af->l_type == F_RDLCK)
- code = LOCK_SH;
- else if (af->l_type == F_WRLCK)
- code = LOCK_EX;
- else if (af->l_type == F_UNLCK)
- code = LOCK_UN;
- else {
- afs_PutFakeStat(&fakestate);
- return EINVAL; /* unknown lock type */
- }
- if (((acmd == F_SETLK)
-#if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
- || (acmd == F_RSETLK)
-#endif
- ) && code != LOCK_UN)
- code |= LOCK_NB; /* non-blocking, s.v.p. */
-#if (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_OSF_ENV)
- code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
-#elif defined(AFS_SGI_ENV)
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
- code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#else
- code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
-#endif
- code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
- afs_PutFakeStat(&fakestate);
- return code;
- }
- afs_PutFakeStat(&fakestate);
- return EINVAL;
-}
-
-
-/*
- * Get a description of the first lock which would
- * block the lock specified. If the specified lock
- * would succeed, fill in the lock structure with 'F_UNLCK'.
- *
- * To do that, we have to ask the server for the lock
- * count if:
- * 1. The file is not locked by this machine.
- * 2. Asking for write lock, and only the current
- * PID has the file read locked.
- */
-#ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
-static int
-HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
- register struct vrequest *areq, int clid)
-{
- register afs_int32 code;
- struct AFS_FLOCK flock;
-
- lockIdSet(&flock, NULL, clid);
-
- ObtainWriteLock(&avc->lock, 122);
- if (avc->flockCount == 0) {
- /*
- * We don't know ourselves, so ask the server. Unfortunately, we
- * don't know the pid. Not even the server knows the pid. Besides,
- * the process with the lock is on another machine
- */
- code = GetFlockCount(avc, areq);
- if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
- af->l_type = F_UNLCK;
- goto unlck_leave;
- }
- if (code > 0)
- af->l_type = F_RDLCK;
- else
- af->l_type = F_WRLCK;
-
- af->l_pid = 0;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- goto done;
- }
-
- if (af->l_type == F_RDLCK) {
- /*
- * We want a read lock. If there are only
- * read locks, or we are the one with the
- * write lock, say it is unlocked.
- */
- if (avc->flockCount > 0 || /* only read locks */
- !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- af->l_type = F_UNLCK;
- goto unlck_leave;
- }
-
- /* one write lock, but who? */
- af->l_type = F_WRLCK; /* not us, so lock would block */
- if (avc->slocks) { /* we know who, so tell */
- af->l_pid = avc->slocks->pid;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = avc->slocks->sysid;
-#endif
- } else {
- af->l_pid = 0; /* XXX can't happen?? */
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- }
- goto done;
- }
-
- /*
- * Ok, we want a write lock. If there is a write lock
- * already, and it is not this process, we fail.
- */
- if (avc->flockCount < 0) {
- if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- af->l_type = F_WRLCK;
- if (avc->slocks) {
- af->l_pid = avc->slocks->pid;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = avc->slocks->sysid;
-#endif
- } else {
- af->l_pid = 0; /* XXX can't happen?? */
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- }
- goto done;
- }
- /* we are the one with the write lock */
- af->l_type = F_UNLCK;
- goto unlck_leave;
- }
-
- /*
- * Want a write lock, and we know there are read locks.
- * If there is more than one, or it isn't us, we cannot lock.
- */
- if ((avc->flockCount > 1)
- || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- struct SimpleLocks *slp;
-
- af->l_type = F_RDLCK;
- af->l_pid = 0;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- /* find a pid that isn't our own */
- for (slp = avc->slocks; slp; slp = slp->next) {
- if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
- af->l_pid = slp->pid;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = avc->slocks->sysid;
-#endif
- break;
- }
- }
- goto done;
- }
-
- /*
- * Ok, we want a write lock. If there is a write lock
- * already, and it is not this process, we fail.
- */
- if (avc->flockCount < 0) {
- if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- af->l_type = F_WRLCK;
- if (avc->slocks) {
- af->l_pid = avc->slocks->pid;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = avc->slocks->sysid;
-#endif
- } else {
- af->l_pid = 0; /* XXX can't happen?? */
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- }
- goto done;
- }
- /* we are the one with the write lock */
- af->l_type = F_UNLCK;
- goto unlck_leave;
- }
-
- /*
- * Want a write lock, and we know there are read locks.
- * If there is more than one, or it isn't us, we cannot lock.
- */
- if ((avc->flockCount > 1)
- || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
- struct SimpleLocks *slp;
- af->l_type = F_RDLCK;
- af->l_pid = 0;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
- /* find a pid that isn't our own */
- for (slp = avc->slocks; slp; slp = slp->next) {
- if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
- af->l_pid = slp->pid;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = avc->slocks->sysid;
-#endif
- break;
- }
- }
- goto done;
- }
-
- /*
- * Want a write lock, and there is just one read lock, and it
- * is this process with a read lock. Ask the server if there
- * are any more processes with the file locked.
- */
- code = GetFlockCount(avc, areq);
- if (code == 0 || code == 1) {
- af->l_type = F_UNLCK;
- goto unlck_leave;
- }
- if (code > 0)
- af->l_type = F_RDLCK;
- else
- af->l_type = F_WRLCK;
- af->l_pid = 0;
-#if defined(AFS_HAVE_FLOCK_SYSID)
- af->l_sysid = 0;
-#endif
-
- done:
- af->l_whence = 0;
- af->l_start = 0;
- af->l_len = 0; /* to end of file */
-
- unlck_leave:
- ReleaseWriteLock(&avc->lock);
- return 0;
-}
-
-/* Get the 'flock' count from the server. This comes back in a 'spare'
- * field from a GetStatus RPC. If we have any problems with the RPC,
- * we lie and say the file is unlocked. If we ask any 'old' fileservers,
- * the spare field will be a zero, saying the file is unlocked. This is
- * OK, as a further 'lock' request will do the right thing.
- */
-static int
-GetFlockCount(struct vcache *avc, struct vrequest *areq)
-{
- register struct conn *tc;
- register afs_int32 code;
- struct AFSFetchStatus OutStatus;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- int temp;
- XSTATS_DECLS temp = areq->flags & O_NONBLOCK;
- areq->flags |= O_NONBLOCK;
-
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->fid.Fid,
- &OutStatus, &CallBack, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
- SHARED_LOCK, NULL));
-
- if (temp)
- areq->flags &= ~O_NONBLOCK;
-
- if (code) {
- return (0); /* failed, say it is 'unlocked' */
- } else {
- return ((int)OutStatus.lockCount);
- }
-}
-#endif
-
-
-#if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-/* Flock not support on System V systems */
-#ifdef AFS_OSF_ENV
-extern struct fileops afs_fileops;
-
-int
-afs_xflock(struct proc *p, void *args, int *retval)
-#else /* AFS_OSF_ENV */
-int
-afs_xflock(void)
-#endif
-{
- int code = 0;
- struct a {
- int fd;
- int com;
- } *uap;
- struct file *fd;
- struct vrequest treq;
- struct vcache *tvc;
- int flockDone;
- struct afs_fakestat_state fakestate;
-
- afs_InitFakeStat(&fakestate);
- AFS_STATCNT(afs_xflock);
- flockDone = 0;
-#ifdef AFS_OSF_ENV
- uap = (struct a *)args;
- getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
-#else /* AFS_OSF_ENV */
- uap = (struct a *)u.u_ap;
- fd = getf(uap->fd);
-#endif
- if (!fd) {
- afs_PutFakeStat(&fakestate);
- return;
- }
-
- if (flockDone = afs_InitReq(&treq, u.u_cred)) {
- afs_PutFakeStat(&fakestate);
- return flockDone;
- }
- /* first determine whether this is any sort of vnode */
- if (fd->f_type == DTYPE_VNODE) {
- /* good, this is a vnode; next see if it is an AFS vnode */
- tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
- if (IsAfsVnode(AFSTOV(tvc))) {
- /* This is an AFS vnode, so do the work */
-#ifdef AFS_DEC_ENV
- /* find real vcache entry; shouldn't be null if gnode ref count
- * is greater than 0.
- */
- tvc = VTOAFS(afs_gntovn) (tvc);
- if (!tvc) {
- u.u_error = ENOENT;
- afs_PutFakeStat(&fakestate);
- return;
- }
-#endif
- code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- return code;
- }
- if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
- /* First, if fd already has lock, release it for relock path */
-#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
- HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
- 0 /*!onlymine */ );
-#else
- HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
-#endif
- fd->f_flag &= ~(FEXLOCK | FSHLOCK);
- }
- /* now try the requested operation */
-
-#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
- code =
- HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
- 0 /*!onlymine */ );
-#else
- code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
-#endif
-#ifndef AFS_OSF_ENV
- u.u_error = code;
-#endif
-
- if (uap->com & LOCK_UN) {
- /* gave up lock */
- fd->f_flag &= ~(FEXLOCK | FSHLOCK);
- } else {
-#ifdef AFS_OSF_ENV
- if (!code) {
-#else /* AFS_OSF_ENV */
- if (!u.u_error) {
-#endif
- if (uap->com & LOCK_SH)
- fd->f_flag |= FSHLOCK;
- else if (uap->com & LOCK_EX)
- fd->f_flag |= FEXLOCK;
- }
- }
- flockDone = 1;
- fd->f_ops = &afs_fileops;
- }
- }
-#ifdef AFS_OSF_ENV
- if (!flockDone)
- code = flock(p, args, retval);
-#ifdef AFS_OSF30_ENV
- FP_UNREF_ALWAYS(fd);
-#else
- FP_UNREF(fd);
-#endif
- afs_PutFakeStat(&fakestate);
- return code;
-#else /* AFS_OSF_ENV */
- if (!flockDone)
-#ifdef DYNEL
- (*afs_longcall_procs.LC_flock) ();
-#else
- flock();
-#endif
- afs_PutFakeStat(&fakestate);
- return;
-#endif
-}
-#endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */
+++ /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
- */
-
-/*
- * Implements:
- * afs_link
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_link.c,v 1.15 2003/08/29 22:00:04 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-extern afs_rwlock_t afs_xcbhash;
-
-/* Note that we don't set CDirty here, this is OK because the link
- * RPC is called synchronously. */
-
-int
-#ifdef AFS_OSF_ENV
-afs_link(avc, ndp)
- struct vcache *avc;
- struct nameidata *ndp;
-{
- struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_link(OSI_VC_ARG(adp), avc, aname, acred)
-#else
-afs_link(avc, OSI_VC_ARG(adp), aname, acred)
-#endif
- OSI_VC_DECL(adp);
- struct vcache *avc;
- char *aname;
- struct AFS_UCRED *acred;
-{
-#endif
- struct vrequest treq;
- register struct dcache *tdc;
- register afs_int32 code;
- register struct conn *tc;
- afs_size_t offset, len;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
- struct AFSVolSync tsync;
- struct afs_fakestat_state vfakestate, dfakestate;
- XSTATS_DECLS OSI_VC_CONVERT(adp)
-
- AFS_STATCNT(afs_link);
- afs_Trace3(afs_iclSetp, CM_TRACE_LINK, ICL_TYPE_POINTER, adp,
- ICL_TYPE_POINTER, avc, ICL_TYPE_STRING, aname);
- /* create a hard link; new entry is aname in dir adp */
- if ((code = afs_InitReq(&treq, acred)))
- goto done2;
-
- afs_InitFakeStat(&vfakestate);
- afs_InitFakeStat(&dfakestate);
- code = afs_EvalFakeStat(&avc, &vfakestate, &treq);
- if (code)
- goto done;
- code = afs_EvalFakeStat(&adp, &dfakestate, &treq);
- if (code)
- goto done;
-
- if (avc->fid.Cell != adp->fid.Cell
- || avc->fid.Fid.Volume != adp->fid.Fid.Volume) {
- code = EXDEV;
- goto done;
- }
- if (strlen(aname) > AFSNAMEMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
- code = afs_VerifyVCache(adp, &treq);
- if (code)
- goto done;
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
- code = EROFS;
- goto done;
- }
-
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
- ObtainWriteLock(&adp->lock, 145);
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_LINK);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_Link(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
- (struct AFSFid *)&avc->fid.Fid, &OutFidStatus,
- &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
-
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_LINK,
- SHARED_LOCK, NULL));
-
- if (code) {
- if (tdc)
- afs_PutDCache(tdc);
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 492);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- goto done;
- }
- if (tdc)
- ObtainWriteLock(&tdc->lock, 635);
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Create(&tdc->f.inode, aname, &avc->fid.Fid);
- if (code) {
- ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc); /* drop ref count */
- }
- ReleaseWriteLock(&adp->lock);
- ObtainWriteLock(&avc->lock, 146); /* correct link count */
-
- /* we could lock both dir and file; since we get the new fid
- * status back, you'd think we could put it in the cache status
- * entry at that point. Note that if we don't lock the file over
- * the rpc call, we have no guarantee that the status info
- * returned in ustat is the most recent to store in the file's
- * cache entry */
-
- ObtainWriteLock(&afs_xcbhash, 493);
- afs_DequeueCallback(avc);
- avc->states &= ~CStatd; /* don't really know new link count */
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- ReleaseWriteLock(&avc->lock);
- code = 0;
- done:
- code = afs_CheckCode(code, &treq, 24);
- afs_PutFakeStat(&vfakestate);
- afs_PutFakeStat(&dfakestate);
- done2:
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
-#endif /* AFS_OSF_ENV */
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_lookup
- * EvalMountPoint
- * afs_DoBulkStat
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_lookup.c,v 1.50 2004/03/17 06:43:36 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/exporter.h"
-#include "afs/afs_osidnlc.h"
-
-
-extern struct DirEntry *afs_dir_GetBlob();
-
-#ifdef AFS_LINUX22_ENV
-extern struct inode_operations afs_symlink_iops, afs_dir_iops;
-#endif
-
-
-afs_int32 afs_bkvolpref = 0;
-afs_int32 afs_bulkStatsDone;
-static int bulkStatCounter = 0; /* counter for bulk stat seq. numbers */
-int afs_fakestat_enable = 0; /* 1: fakestat-all, 2: fakestat-crosscell */
-
-
-/* this would be faster if it did comparison as int32word, but would be
- * dependant on byte-order and alignment, and I haven't figured out
- * what "@sys" is in binary... */
-#define AFS_EQ_ATSYS(name) (((name)[0]=='@')&&((name)[1]=='s')&&((name)[2]=='y')&&((name)[3]=='s')&&(!(name)[4]))
-
-/* call under write lock, evaluate mvid field from a mt pt.
- * avc is the vnode of the mount point object; must be write-locked.
- * advc is the vnode of the containing directory (optional; if NULL and
- * EvalMountPoint succeeds, caller must initialize *avolpp->dotdot)
- * avolpp is where we return a pointer to the volume named by the mount pt, if success
- * areq is the identity of the caller.
- *
- * NOTE: this function returns a held volume structure in *volpp if it returns 0!
- */
-int
-EvalMountPoint(register struct vcache *avc, struct vcache *advc,
- struct volume **avolpp, register struct vrequest *areq)
-{
- afs_int32 code;
- struct volume *tvp = 0;
- struct VenusFid tfid;
- struct cell *tcell;
- char *cpos, *volnamep;
- char type, *buf;
- afs_int32 prefetch; /* 1=>None 2=>RO 3=>BK */
- afs_int32 mtptCell, assocCell, hac = 0;
- afs_int32 samecell, roname, len;
-
- AFS_STATCNT(EvalMountPoint);
-#ifdef notdef
- if (avc->mvid && (avc->states & CMValid))
- return 0; /* done while racing */
-#endif
- *avolpp = NULL;
- code = afs_HandleLink(avc, areq);
- if (code)
- return code;
-
- /* Determine which cell and volume the mointpoint goes to */
- type = avc->linkData[0]; /* '#'=>Regular '%'=>RW */
- cpos = afs_strchr(&avc->linkData[1], ':'); /* if cell name present */
- if (cpos) {
- volnamep = cpos + 1;
- *cpos = 0;
- tcell = afs_GetCellByName(&avc->linkData[1], READ_LOCK);
- *cpos = ':';
- } else {
- volnamep = &avc->linkData[1];
- tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
- }
- if (!tcell)
- return ENODEV;
-
- mtptCell = tcell->cellNum; /* The cell for the mountpoint */
- if (tcell->lcellp) {
- hac = 1; /* has associated cell */
- assocCell = tcell->lcellp->cellNum; /* The associated cell */
- }
- afs_PutCell(tcell, READ_LOCK);
-
- /* Is volume name a "<n>.backup" or "<n>.readonly" name */
- len = strlen(volnamep);
- roname = ((len > 9) && (strcmp(&volnamep[len - 9], ".readonly") == 0))
- || ((len > 7) && (strcmp(&volnamep[len - 7], ".backup") == 0));
-
- /* When we cross mountpoint, do we stay in the same cell */
- samecell = (avc->fid.Cell == mtptCell) || (hac
- && (avc->fid.Cell ==
- assocCell));
-
- /* Decide whether to prefetch the BK, or RO. Also means we want the BK or
- * RO.
- * If this is a regular mountpoint with a RW volume name
- * - If BK preference is enabled AND we remain within the same cell AND
- * start from a BK volume, then we will want to prefetch the BK volume.
- * - If we cross a cell boundary OR start from a RO volume, then we will
- * want to prefetch the RO volume.
- */
- if ((type == '#') && !roname) {
- if (afs_bkvolpref && samecell && (avc->states & CBackup))
- prefetch = 3; /* Prefetch the BK */
- else if (!samecell || (avc->states & CRO))
- prefetch = 2; /* Prefetch the RO */
- else
- prefetch = 1; /* Do not prefetch */
- } else {
- prefetch = 1; /* Do not prefetch */
- }
-
- /* Get the volume struct. Unless this volume name has ".readonly" or
- * ".backup" in it, this will get the volume struct for the RW volume.
- * The RO volume will be prefetched if requested (but not returned).
- */
- tvp = afs_GetVolumeByName(volnamep, mtptCell, prefetch, areq, WRITE_LOCK);
-
- /* If no volume was found in this cell, try the associated linked cell */
- if (!tvp && hac && areq->volumeError) {
- tvp =
- afs_GetVolumeByName(volnamep, assocCell, prefetch, areq,
- WRITE_LOCK);
- }
-
- /* Still not found. If we are looking for the RO, then perhaps the RW
- * doesn't exist? Try adding ".readonly" to volname and look for that.
- * Don't know why we do this. Would have still found it in above call - jpm.
- */
- if (!tvp && (prefetch == 2) && len < AFS_SMALLOCSIZ - 10) {
- buf = (char *)osi_AllocSmallSpace(len + 10);
-
- strcpy(buf, volnamep);
- afs_strcat(buf, ".readonly");
-
- tvp = afs_GetVolumeByName(buf, mtptCell, 1, areq, WRITE_LOCK);
-
- /* Try the associated linked cell if failed */
- if (!tvp && hac && areq->volumeError) {
- tvp = afs_GetVolumeByName(buf, assocCell, 1, areq, WRITE_LOCK);
- }
- osi_FreeSmallSpace(buf);
- }
-
- if (!tvp)
- return ENODEV; /* Couldn't find the volume */
-
- /* Don't cross mountpoint from a BK to a BK volume */
- if ((avc->states & CBackup) && (tvp->states & VBackup)) {
- afs_PutVolume(tvp, WRITE_LOCK);
- return ENODEV;
- }
-
- /* If we want (prefetched) the BK and it exists, then drop the RW volume
- * and get the BK.
- * Otherwise, if we want (prefetched0 the RO and it exists, then drop the
- * RW volume and get the RO.
- * Otherwise, go with the RW.
- */
- if ((prefetch == 3) && tvp->backVol) {
- tfid.Fid.Volume = tvp->backVol; /* remember BK volume */
- tfid.Cell = tvp->cell;
- afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */
- tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK); /* get the new one */
- if (!tvp)
- return ENODEV; /* oops, can't do it */
- } else if ((prefetch >= 2) && tvp->roVol) {
- tfid.Fid.Volume = tvp->roVol; /* remember RO volume */
- tfid.Cell = tvp->cell;
- afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */
- tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK); /* get the new one */
- if (!tvp)
- return ENODEV; /* oops, can't do it */
- }
-
- if (avc->mvid == 0)
- avc->mvid =
- (struct VenusFid *)osi_AllocSmallSpace(sizeof(struct VenusFid));
- avc->mvid->Cell = tvp->cell;
- avc->mvid->Fid.Volume = tvp->volume;
- avc->mvid->Fid.Vnode = 1;
- avc->mvid->Fid.Unique = 1;
- avc->states |= CMValid;
-
- /* Used to: if the mount point is stored within a backup volume,
- * then we should only update the parent pointer information if
- * there's none already set, so as to avoid updating a volume's ..
- * info with something in an OldFiles directory.
- *
- * Next two lines used to be under this if:
- *
- * if (!(avc->states & CBackup) || tvp->dotdot.Fid.Volume == 0)
- *
- * Now: update mount point back pointer on every call, so that we handle
- * multiple mount points better. This way, when du tries to go back
- * via chddir(".."), it will end up exactly where it started, yet
- * cd'ing via a new path to a volume will reset the ".." pointer
- * to the new path.
- */
- tvp->mtpoint = avc->fid; /* setup back pointer to mtpoint */
- if (advc)
- tvp->dotdot = advc->fid;
-
- *avolpp = tvp;
- return 0;
-}
-
-/*
- * afs_InitFakeStat
- *
- * Must be called on an afs_fakestat_state object before calling
- * afs_EvalFakeStat or afs_PutFakeStat. Calling afs_PutFakeStat
- * without calling afs_EvalFakeStat is legal, as long as this
- * function is called.
- */
-void
-afs_InitFakeStat(struct afs_fakestat_state *state)
-{
- if (!afs_fakestat_enable)
- return;
-
- state->valid = 1;
- state->did_eval = 0;
- state->need_release = 0;
-}
-
-/*
- * afs_EvalFakeStat_int
- *
- * The actual implementation of afs_EvalFakeStat and afs_TryEvalFakeStat,
- * which is called by those wrapper functions.
- *
- * Only issues RPCs if canblock is non-zero.
- */
-int
-afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
- struct vrequest *areq, int canblock)
-{
- struct vcache *tvc, *root_vp;
- struct volume *tvolp = NULL;
- int code = 0;
-
- if (!afs_fakestat_enable)
- return 0;
-
- osi_Assert(state->valid == 1);
- osi_Assert(state->did_eval == 0);
- state->did_eval = 1;
-
- tvc = *avcp;
- if (tvc->mvstat != 1)
- return 0;
-
- /* Is the call to VerifyVCache really necessary? */
- code = afs_VerifyVCache(tvc, areq);
- if (code)
- goto done;
- if (canblock) {
- ObtainWriteLock(&tvc->lock, 599);
- code = EvalMountPoint(tvc, NULL, &tvolp, areq);
- ReleaseWriteLock(&tvc->lock);
- if (code)
- goto done;
- if (tvolp) {
- tvolp->dotdot = tvc->fid;
- tvolp->dotdot.Fid.Vnode = tvc->parentVnode;
- tvolp->dotdot.Fid.Unique = tvc->parentUnique;
- }
- }
- if (tvc->mvid && (tvc->states & CMValid)) {
- if (!canblock) {
- afs_int32 retry;
-
- do {
- retry = 0;
- ObtainWriteLock(&afs_xvcache, 597);
- root_vp = afs_FindVCache(tvc->mvid, &retry, 0);
- if (root_vp && retry) {
- ReleaseWriteLock(&afs_xvcache);
- afs_PutVCache(root_vp);
- }
- } while (root_vp && retry);
- ReleaseWriteLock(&afs_xvcache);
- } else {
- root_vp = afs_GetVCache(tvc->mvid, areq, NULL, NULL);
- }
- if (!root_vp) {
- code = canblock ? ENOENT : 0;
- goto done;
- }
- if (tvolp) {
- /* Is this always kosher? Perhaps we should instead use
- * NBObtainWriteLock to avoid potential deadlock.
- */
- ObtainWriteLock(&root_vp->lock, 598);
- if (!root_vp->mvid)
- root_vp->mvid = osi_AllocSmallSpace(sizeof(struct VenusFid));
- *root_vp->mvid = tvolp->dotdot;
- ReleaseWriteLock(&root_vp->lock);
- }
- state->need_release = 1;
- state->root_vp = root_vp;
- *avcp = root_vp;
- code = 0;
- } else {
- code = canblock ? ENOENT : 0;
- }
-
- done:
- if (tvolp)
- afs_PutVolume(tvolp, WRITE_LOCK);
- return code;
-}
-
-/*
- * afs_EvalFakeStat
- *
- * Automatically does the equivalent of EvalMountPoint for vcache entries
- * which are mount points. Remembers enough state to properly release
- * the volume root vcache when afs_PutFakeStat() is called.
- *
- * State variable must be initialized by afs_InitFakeState() beforehand.
- *
- * Returns 0 when everything succeeds and *avcp points to the vcache entry
- * that should be used for the real vnode operation. Returns non-zero if
- * something goes wrong and the error code should be returned to the user.
- */
-int
-afs_EvalFakeStat(struct vcache **avcp, struct afs_fakestat_state *state,
- struct vrequest *areq)
-{
- return afs_EvalFakeStat_int(avcp, state, areq, 1);
-}
-
-/*
- * afs_TryEvalFakeStat
- *
- * Same as afs_EvalFakeStat, but tries not to talk to remote servers
- * and only evaluate the mount point if all the data is already in
- * local caches.
- *
- * Returns 0 if everything succeeds and *avcp points to a valid
- * vcache entry (possibly evaluated).
- */
-int
-afs_TryEvalFakeStat(struct vcache **avcp, struct afs_fakestat_state *state,
- struct vrequest *areq)
-{
- return afs_EvalFakeStat_int(avcp, state, areq, 0);
-}
-
-/*
- * afs_PutFakeStat
- *
- * Perform any necessary cleanup at the end of a vnode op, given that
- * afs_InitFakeStat was previously called with this state.
- */
-void
-afs_PutFakeStat(struct afs_fakestat_state *state)
-{
- if (!afs_fakestat_enable)
- return;
-
- osi_Assert(state->valid == 1);
- if (state->need_release)
- afs_PutVCache(state->root_vp);
- state->valid = 0;
-}
-
-int
-afs_ENameOK(register char *aname)
-{
- register int tlen;
-
- AFS_STATCNT(ENameOK);
- tlen = strlen(aname);
- if (tlen >= 4 && strcmp(aname + tlen - 4, "@sys") == 0)
- return 0;
- return 1;
-}
-
-static int
-afs_getsysname(register struct vrequest *areq, register struct vcache *adp,
- register char *bufp, int *num, char **sysnamelist[])
-{
- register struct unixuser *au;
- register afs_int32 error;
-
- AFS_STATCNT(getsysname);
-
- *sysnamelist = afs_sysnamelist;
-
- if (!afs_nfsexporter)
- strcpy(bufp, (*sysnamelist)[0]);
- else {
- au = afs_GetUser(areq->uid, adp->fid.Cell, 0);
- if (au->exporter) {
- error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
- if (error) {
- strcpy(bufp, "@sys");
- afs_PutUser(au, 0);
- return -1;
- } else {
- strcpy(bufp, (*sysnamelist)[0]);
- }
- } else
- strcpy(bufp, afs_sysname);
- afs_PutUser(au, 0);
- }
- return 0;
-}
-
-void
-Check_AtSys(register struct vcache *avc, char *aname,
- struct sysname_info *state, struct vrequest *areq)
-{
- int num = 0;
- char **sysnamelist[MAXSYSNAME];
-
- if (AFS_EQ_ATSYS(aname)) {
- state->offset = 0;
- state->name = (char *)osi_AllocLargeSpace(AFS_SMALLOCSIZ);
- state->allocked = 1;
- state->index = afs_getsysname(areq, avc, state->name, &num, sysnamelist);
- } else {
- state->offset = -1;
- state->allocked = 0;
- state->index = 0;
- state->name = aname;
- }
-}
-
-int
-Next_AtSys(register struct vcache *avc, struct vrequest *areq,
- struct sysname_info *state)
-{
- int num = afs_sysnamecount;
- char **sysnamelist[MAXSYSNAME];
-
- if (state->index == -1)
- return 0; /* No list */
-
- /* Check for the initial state of aname != "@sys" in Check_AtSys*/
- if (state->offset == -1 && state->allocked == 0) {
- register char *tname;
-
- /* Check for .*@sys */
- for (tname=state->name; *tname; tname++)
- /*Move to the end of the string*/;
-
- if ((tname > state->name + 4) && (AFS_EQ_ATSYS(tname-4))) {
- state->offset = (tname - 4) - state->name;
- tname = (char *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- strncpy(tname, state->name, state->offset);
- state->name = tname;
- state->allocked = 1;
- num = 0;
- state->index = afs_getsysname(areq, avc, state->name+state->offset,
- &num, sysnamelist);
- return 1;
- } else
- return 0; /* .*@sys doesn't match either */
- } else {
- register struct unixuser *au;
- register afs_int32 error;
-
- *sysnamelist = afs_sysnamelist;
-
- if (afs_nfsexporter) {
- au = afs_GetUser(areq->uid, avc->fid.Cell, 0);
- if (au->exporter) {
- error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
- if (error) {
- return 0;
- }
- }
- afs_PutUser(au, 0);
- }
- if (++(state->index) >= num || !(*sysnamelist)[state->index])
- return 0; /* end of list */
- }
- strcpy(state->name+state->offset, (*sysnamelist)[state->index]);
- return 1;
-}
-
-#if (defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV))
-extern int BlobScan(ino64_t * afile, afs_int32 ablob);
-#else
-#if defined(AFS_HPUX1123_ENV)
-/* DEE should use the new afs_inode_t for all */
-extern int BlobScan(ino_t *afile, afs_int32 ablob);
-#else
-#if defined AFS_LINUX_64BIT_KERNEL
-extern int BlobScan(long *afile, afs_int32 ablob);
-#else
-extern int BlobScan(afs_int32 * afile, afs_int32 ablob);
-#endif
-#endif
-#endif
-
-
-/* called with an unlocked directory and directory cookie. Areqp
- * describes who is making the call.
- * Scans the next N (about 30, typically) directory entries, and does
- * a bulk stat call to stat them all.
- *
- * Must be very careful when merging in RPC responses, since we dont
- * want to overwrite newer info that was added by a file system mutating
- * call that ran concurrently with our bulk stat call.
- *
- * We do that, as described below, by not merging in our info (always
- * safe to skip the merge) if the status info is valid in the vcache entry.
- *
- * If adapt ever implements the bulk stat RPC, then this code will need to
- * ensure that vcaches created for failed RPC's to older servers have the
- * CForeign bit set.
- */
-static struct vcache *BStvc = NULL;
-
-int
-afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
-{
- int nentries; /* # of entries to prefetch */
- int nskip; /* # of slots in the LRU queue to skip */
- struct vcache *lruvcp; /* vcache ptr of our goal pos in LRU queue */
- struct dcache *dcp; /* chunk containing the dir block */
- char *statMemp; /* status memory block */
- char *cbfMemp; /* callback and fid memory block */
- afs_size_t temp; /* temp for holding chunk length, &c. */
- struct AFSFid *fidsp; /* file IDs were collecting */
- struct AFSCallBack *cbsp; /* call back pointers */
- struct AFSCallBack *tcbp; /* temp callback ptr */
- struct AFSFetchStatus *statsp; /* file status info */
- struct AFSVolSync volSync; /* vol sync return info */
- struct vcache *tvcp; /* temp vcp */
- struct afs_q *tq; /* temp queue variable */
- AFSCBFids fidParm; /* file ID parm for bulk stat */
- AFSBulkStats statParm; /* stat info parm for bulk stat */
- int fidIndex; /* which file were stating */
- struct conn *tcp; /* conn for call */
- AFSCBs cbParm; /* callback parm for bulk stat */
- struct server *hostp = 0; /* host we got callback from */
- long startTime; /* time we started the call,
- * for callback expiration base
- */
- afs_size_t statSeqNo; /* Valued of file size to detect races */
- int code; /* error code */
- long newIndex; /* new index in the dir */
- struct DirEntry *dirEntryp; /* dir entry we are examining */
- int i;
- struct VenusFid afid; /* file ID we are using now */
- struct VenusFid tfid; /* another temp. file ID */
- afs_int32 retry; /* handle low-level SGI MP race conditions */
- long volStates; /* flags from vol structure */
- struct volume *volp = 0; /* volume ptr */
- struct VenusFid dotdot;
- int flagIndex; /* First file with bulk fetch flag set */
- int inlinebulk = 0; /* Did we use InlineBulk RPC or not? */
- XSTATS_DECLS
- /* first compute some basic parameters. We dont want to prefetch more
- * than a fraction of the cache in any given call, and we want to preserve
- * a portion of the LRU queue in any event, so as to avoid thrashing
- * the entire stat cache (we will at least leave some of it alone).
- * presently dont stat more than 1/8 the cache in any one call. */
- nentries = afs_cacheStats / 8;
-
- /* dont bother prefetching more than one calls worth of info */
- if (nentries > AFSCBMAX)
- nentries = AFSCBMAX;
-
- /* heuristic to make sure that things fit in 4K. This means that
- * we shouldnt make it any bigger than 47 entries. I am typically
- * going to keep it a little lower, since we don't want to load
- * too much of the stat cache.
- */
- if (nentries > 30)
- nentries = 30;
-
- /* now, to reduce the stack size, well allocate two 4K blocks,
- * one for fids and callbacks, and one for stat info. Well set
- * up our pointers to the memory from there, too.
- */
- statMemp = osi_AllocLargeSpace(nentries * sizeof(AFSFetchStatus));
- statsp = (struct AFSFetchStatus *)statMemp;
- cbfMemp =
- osi_AllocLargeSpace(nentries *
- (sizeof(AFSCallBack) + sizeof(AFSFid)));
- fidsp = (AFSFid *) cbfMemp;
- cbsp = (AFSCallBack *) (cbfMemp + nentries * sizeof(AFSFid));
-
- /* next, we must iterate over the directory, starting from the specified
- * cookie offset (dirCookie), and counting out nentries file entries.
- * We skip files that already have stat cache entries, since we
- * dont want to bulk stat files that are already in the cache.
- */
- tagain:
- code = afs_VerifyVCache(adp, areqp);
- if (code)
- goto done;
-
- dcp = afs_GetDCache(adp, (afs_size_t) 0, areqp, &temp, &temp, 1);
- if (!dcp) {
- code = ENOENT;
- goto done;
- }
-
- /* lock the directory cache entry */
- ObtainReadLock(&adp->lock);
- ObtainReadLock(&dcp->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((adp->states & CStatd)
- && (dcp->dflags & DFFetching)
- && hsame(adp->m.DataVersion, dcp->f.versionNo)) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, dcp,
- ICL_TYPE_INT32, dcp->dflags);
- ReleaseReadLock(&dcp->lock);
- ReleaseReadLock(&adp->lock);
- afs_osi_Sleep(&dcp->validPos);
- ObtainReadLock(&adp->lock);
- ObtainReadLock(&dcp->lock);
- }
- if (!(adp->states & CStatd)
- || !hsame(adp->m.DataVersion, dcp->f.versionNo)) {
- ReleaseReadLock(&dcp->lock);
- ReleaseReadLock(&adp->lock);
- afs_PutDCache(dcp);
- goto tagain;
- }
-
- /* Generate a sequence number so we can tell whether we should
- * store the attributes when processing the response. This number is
- * stored in the file size when we set the CBulkFetching bit. If the
- * CBulkFetching is still set and this value hasn't changed, then
- * we know we were the last to set CBulkFetching bit for this file,
- * and it is safe to set the status information for this file.
- */
- statSeqNo = bulkStatCounter++;
-
- /* now we have dir data in the cache, so scan the dir page */
- fidIndex = 0;
- flagIndex = 0;
- while (1) { /* Should probably have some constant bound */
- /* look for first safe entry to examine in the directory. BlobScan
- * looks for a the 1st allocated dir after the dirCookie slot.
- */
- newIndex = BlobScan(&dcp->f.inode, (dirCookie >> 5));
- if (newIndex == 0)
- break;
-
- /* remember the updated directory cookie */
- dirCookie = newIndex << 5;
-
- /* get a ptr to the dir entry */
- dirEntryp =
- (struct DirEntry *)afs_dir_GetBlob(&dcp->f.inode, newIndex);
- if (!dirEntryp)
- break;
-
- /* dont copy more than we have room for */
- if (fidIndex >= nentries) {
- DRelease((struct buffer *)dirEntryp, 0);
- break;
- }
-
- /* now, if the dir entry looks good, copy it out to our list. Vnode
- * 0 means deleted, although it should also be free were it deleted.
- */
- if (dirEntryp->fid.vnode != 0) {
- /* dont copy entries we have in our cache. This check will
- * also make us skip "." and probably "..", unless it has
- * disappeared from the cache since we did our namei call.
- */
- tfid.Cell = adp->fid.Cell;
- tfid.Fid.Volume = adp->fid.Fid.Volume;
- tfid.Fid.Vnode = ntohl(dirEntryp->fid.vnode);
- tfid.Fid.Unique = ntohl(dirEntryp->fid.vunique);
- do {
- retry = 0;
- ObtainWriteLock(&afs_xvcache, 130);
- tvcp = afs_FindVCache(&tfid, &retry, 0 /* no stats | LRU */ );
- if (tvcp && retry) {
- ReleaseWriteLock(&afs_xvcache);
- afs_PutVCache(tvcp);
- }
- } while (tvcp && retry);
- if (!tvcp) { /* otherwise, create manually */
- tvcp = afs_NewVCache(&tfid, hostp);
- ObtainWriteLock(&tvcp->lock, 505);
- ReleaseWriteLock(&afs_xvcache);
- afs_RemoveVCB(&tfid);
- ReleaseWriteLock(&tvcp->lock);
- } else {
- ReleaseWriteLock(&afs_xvcache);
- }
- if (!tvcp)
- goto done; /* can't happen at present, more's the pity */
-
- /* WARNING: afs_DoBulkStat uses the Length field to store a
- * sequence number for each bulk status request. Under no
- * circumstances should afs_DoBulkStat store a sequence number
- * if the new length will be ignored when afs_ProcessFS is
- * called with new stats. */
-#ifdef AFS_SGI_ENV
- if (!(tvcp->states & (CStatd | CBulkFetching))
- && (tvcp->execsOrWriters <= 0)
- && !afs_DirtyPages(tvcp)
- && !AFS_VN_MAPPED((vnode_t *) tvcp))
-#else
- if (!(tvcp->states & (CStatd | CBulkFetching))
- && (tvcp->execsOrWriters <= 0)
- && !afs_DirtyPages(tvcp))
-#endif
-
- {
- /* this entry doesnt exist in the cache, and is not
- * already being fetched by someone else, so add it to the
- * list of file IDs to obtain.
- *
- * We detect a callback breaking race condition by checking the
- * CBulkFetching state bit and the value in the file size.
- * It is safe to set the status only if the CBulkFetching
- * flag is still set and the value in the file size does
- * not change.
- *
- * Don't fetch status for dirty files. We need to
- * preserve the value of the file size. We could
- * flush the pages, but it wouldn't be worthwhile.
- */
- memcpy((char *)(fidsp + fidIndex), (char *)&tfid.Fid,
- sizeof(*fidsp));
- tvcp->states |= CBulkFetching;
- tvcp->m.Length = statSeqNo;
- fidIndex++;
- }
- afs_PutVCache(tvcp);
- }
-
- /* if dir vnode has non-zero entry */
- /* move to the next dir entry by adding in the # of entries
- * used by this dir entry.
- */
- temp = afs_dir_NameBlobs(dirEntryp->name) << 5;
- DRelease((struct buffer *)dirEntryp, 0);
- if (temp <= 0)
- break;
- dirCookie += temp;
- } /* while loop over all dir entries */
-
- /* now release the dir lock and prepare to make the bulk RPC */
- ReleaseReadLock(&dcp->lock);
- ReleaseReadLock(&adp->lock);
-
- /* release the chunk */
- afs_PutDCache(dcp);
-
- /* dont make a null call */
- if (fidIndex == 0)
- goto done;
-
- do {
- /* setup the RPC parm structures */
- fidParm.AFSCBFids_len = fidIndex;
- fidParm.AFSCBFids_val = fidsp;
- statParm.AFSBulkStats_len = fidIndex;
- statParm.AFSBulkStats_val = statsp;
- cbParm.AFSCBs_len = fidIndex;
- cbParm.AFSCBs_val = cbsp;
-
- /* start the timer; callback expirations are relative to this */
- startTime = osi_Time();
-
- tcp = afs_Conn(&adp->fid, areqp, SHARED_LOCK);
- if (tcp) {
- hostp = tcp->srvr->server;
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS);
- RX_AFS_GUNLOCK();
-
- if (!(tcp->srvr->server->flags & SNO_INLINEBULK)) {
- code =
- RXAFS_InlineBulkStatus(tcp->id, &fidParm, &statParm,
- &cbParm, &volSync);
- if (code == RXGEN_OPCODE) {
- tcp->srvr->server->flags |= SNO_INLINEBULK;
- inlinebulk = 0;
- code =
- RXAFS_BulkStatus(tcp->id, &fidParm, &statParm,
- &cbParm, &volSync);
- } else
- inlinebulk = 1;
- } else {
- inlinebulk = 0;
- code =
- RXAFS_BulkStatus(tcp->id, &fidParm, &statParm, &cbParm,
- &volSync);
- }
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tcp, code, &adp->fid, areqp, AFS_STATS_FS_RPCIDX_BULKSTATUS,
- SHARED_LOCK, NULL));
-
- /* now, if we didnt get the info, bail out. */
- if (code)
- goto done;
-
- /* we need vol flags to create the entries properly */
- dotdot.Fid.Volume = 0;
- volp = afs_GetVolume(&adp->fid, areqp, READ_LOCK);
- if (volp) {
- volStates = volp->states;
- if (volp->dotdot.Fid.Volume != 0)
- dotdot = volp->dotdot;
- } else
- volStates = 0;
-
- /* find the place to merge the info into We do this by skipping
- * nskip entries in the LRU queue. The more we skip, the more
- * we preserve, since the head of the VLRU queue is the most recently
- * referenced file.
- */
- reskip:
- nskip = afs_cacheStats / 2; /* preserved fraction of the cache */
- ObtainReadLock(&afs_xvcache);
- if (QEmpty(&VLRU)) {
- /* actually a serious error, probably should panic. Probably will
- * panic soon, oh well. */
- ReleaseReadLock(&afs_xvcache);
- afs_warnuser("afs_DoBulkStat: VLRU empty!");
- goto done;
- }
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("Bulkstat VLRU inconsistent");
- }
- for (tq = VLRU.next; tq != &VLRU; tq = QNext(tq)) {
- if (--nskip <= 0)
- break;
- else if (QNext(QPrev(tq)) != tq) {
- BStvc = QTOV(tq);
- refpanic("BulkStat VLRU inconsistent");
- }
- }
- if (tq != &VLRU)
- lruvcp = QTOV(tq);
- else
- lruvcp = QTOV(VLRU.next);
-
- /* now we have to hold this entry, so that it does not get moved
- * into the free list while we're running. It could still get
- * moved within the lru queue, but hopefully that will be rare; it
- * doesn't hurt nearly as much.
- */
- retry = 0;
- osi_vnhold(lruvcp, &retry);
- ReleaseReadLock(&afs_xvcache); /* could be read lock */
- if (retry)
- goto reskip;
-
- /* otherwise, merge in the info. We have to be quite careful here,
- * since we need to ensure that we don't merge old info over newer
- * stuff in a stat cache entry. We're very conservative here: we don't
- * do the merge at all unless we ourselves create the stat cache
- * entry. That's pretty safe, and should work pretty well, since we
- * typically expect to do the stat cache creation ourselves.
- *
- * We also have to take into account racing token revocations.
- */
- for (i = 0; i < fidIndex; i++) {
- if ((&statsp[i])->errorCode)
- continue;
- afid.Cell = adp->fid.Cell;
- afid.Fid.Volume = adp->fid.Fid.Volume;
- afid.Fid.Vnode = fidsp[i].Vnode;
- afid.Fid.Unique = fidsp[i].Unique;
- do {
- retry = 0;
- ObtainReadLock(&afs_xvcache);
- tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */ );
- ReleaseReadLock(&afs_xvcache);
- } while (tvcp && retry);
-
- /* The entry may no longer exist */
- if (tvcp == NULL) {
- continue;
- }
-
- /* now we have the entry held, but we need to fill it in */
- ObtainWriteLock(&tvcp->lock, 131);
-
- /* if CBulkFetching is not set, or if the file size no longer
- * matches the value we placed there when we set the CBulkFetching
- * flag, then someone else has done something with this node,
- * and we may not have the latest status information for this
- * file. Leave the entry alone.
- */
- if (!(tvcp->states & CBulkFetching) || (tvcp->m.Length != statSeqNo)) {
- flagIndex++;
- ReleaseWriteLock(&tvcp->lock);
- afs_PutVCache(tvcp);
- continue;
- }
-
- /* now copy ".." entry back out of volume structure, if necessary */
- if (tvcp->mvstat == 2 && (dotdot.Fid.Volume != 0)) {
- if (!tvcp->mvid)
- tvcp->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- *tvcp->mvid = dotdot;
- }
-
- ObtainWriteLock(&afs_xvcache, 132);
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("Bulkstat VLRU inconsistent2");
- }
- if ((QNext(QPrev(&tvcp->vlruq)) != &tvcp->vlruq)
- || (QPrev(QNext(&tvcp->vlruq)) != &tvcp->vlruq)) {
- refpanic("Bulkstat VLRU inconsistent4");
- }
- if ((QNext(QPrev(&lruvcp->vlruq)) != &lruvcp->vlruq)
- || (QPrev(QNext(&lruvcp->vlruq)) != &lruvcp->vlruq)) {
- refpanic("Bulkstat VLRU inconsistent5");
- }
-
- if (tvcp != lruvcp) { /* if they are == don't move it, don't corrupt vlru */
- QRemove(&tvcp->vlruq);
- QAdd(&lruvcp->vlruq, &tvcp->vlruq);
- }
-
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("Bulkstat VLRU inconsistent3");
- }
- if ((QNext(QPrev(&tvcp->vlruq)) != &tvcp->vlruq)
- || (QPrev(QNext(&tvcp->vlruq)) != &tvcp->vlruq)) {
- refpanic("Bulkstat VLRU inconsistent5");
- }
- if ((QNext(QPrev(&lruvcp->vlruq)) != &lruvcp->vlruq)
- || (QPrev(QNext(&lruvcp->vlruq)) != &lruvcp->vlruq)) {
- refpanic("Bulkstat VLRU inconsistent6");
- }
- ReleaseWriteLock(&afs_xvcache);
-
- ObtainWriteLock(&afs_xcbhash, 494);
-
- /* We need to check the flags again. We may have missed
- * something while we were waiting for a lock.
- */
- if (!(tvcp->states & CBulkFetching) || (tvcp->m.Length != statSeqNo)) {
- flagIndex++;
- ReleaseWriteLock(&tvcp->lock);
- ReleaseWriteLock(&afs_xcbhash);
- afs_PutVCache(tvcp);
- continue;
- }
-
- /* now merge in the resulting status back into the vnode.
- * We only do this if the entry looks clear.
- */
- afs_ProcessFS(tvcp, &statsp[i], areqp);
-#ifdef AFS_LINUX22_ENV
- /* overwrite the ops if it's a directory or symlink. */
- if (vType(tvcp) == VDIR)
- tvcp->v.v_op = &afs_dir_iops;
- else if (vType(tvcp) == VLNK)
- tvcp->v.v_op = &afs_symlink_iops;
-#endif
-
- /* do some accounting for bulk stats: mark this entry as
- * loaded, so we can tell if we use it before it gets
- * recycled.
- */
- tvcp->states |= CBulkStat;
- tvcp->states &= ~CBulkFetching;
- flagIndex++;
- afs_bulkStatsDone++;
-
- /* merge in vol info */
- if (volStates & VRO)
- tvcp->states |= CRO;
- if (volStates & VBackup)
- tvcp->states |= CBackup;
- if (volStates & VForeign)
- tvcp->states |= CForeign;
-
- /* merge in the callback info */
- tvcp->states |= CTruth;
-
- /* get ptr to the callback we are interested in */
- tcbp = cbsp + i;
-
- if (tcbp->ExpirationTime != 0) {
- tvcp->cbExpires = tcbp->ExpirationTime + startTime;
- tvcp->callback = hostp;
- tvcp->states |= CStatd;
- afs_QueueCallback(tvcp, CBHash(tcbp->ExpirationTime), volp);
- } else if (tvcp->states & CRO) {
- /* ordinary callback on a read-only volume -- AFS 3.2 style */
- tvcp->cbExpires = 3600 + startTime;
- tvcp->callback = hostp;
- tvcp->states |= CStatd;
- afs_QueueCallback(tvcp, CBHash(3600), volp);
- } else {
- tvcp->callback = 0;
- tvcp->states &= ~(CStatd | CUnique);
- afs_DequeueCallback(tvcp);
- if ((tvcp->states & CForeign) || (vType(tvcp) == VDIR))
- osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
- }
- ReleaseWriteLock(&afs_xcbhash);
-
- ReleaseWriteLock(&tvcp->lock);
- /* finally, we're done with the entry */
- afs_PutVCache(tvcp);
- } /* for all files we got back */
-
- /* finally return the pointer into the LRU queue */
- afs_PutVCache(lruvcp);
-
- done:
- /* Be sure to turn off the CBulkFetching flags */
- for (i = flagIndex; i < fidIndex; i++) {
- afid.Cell = adp->fid.Cell;
- afid.Fid.Volume = adp->fid.Fid.Volume;
- afid.Fid.Vnode = fidsp[i].Vnode;
- afid.Fid.Unique = fidsp[i].Unique;
- do {
- retry = 0;
- ObtainReadLock(&afs_xvcache);
- tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */ );
- ReleaseReadLock(&afs_xvcache);
- } while (tvcp && retry);
- if (tvcp != NULL && (tvcp->states & CBulkFetching)
- && (tvcp->m.Length == statSeqNo)) {
- tvcp->states &= ~CBulkFetching;
- }
- if (tvcp != NULL) {
- afs_PutVCache(tvcp);
- }
- }
- if (volp)
- afs_PutVolume(volp, READ_LOCK);
-
- /* If we did the InlineBulk RPC pull out the return code */
- if (inlinebulk) {
- if ((&statsp[0])->errorCode) {
- afs_Analyze(tcp, (&statsp[0])->errorCode, &adp->fid, areqp,
- AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, NULL);
- code = (&statsp[0])->errorCode;
- }
- } else {
- code = 0;
- }
- osi_FreeLargeSpace(statMemp);
- osi_FreeLargeSpace(cbfMemp);
- return code;
-}
-
-/* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */
-static int AFSDOBULK = 1;
-
-int
-#ifdef AFS_OSF_ENV
-afs_lookup(adp, ndp)
- struct vcache *adp;
- struct nameidata *ndp;
-{
- char aname[MAXNAMLEN + 1]; /* XXX */
- struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
- struct ucred *acred = ndp->ni_cred;
- int wantparent = ndp->ni_nameiop & WANTPARENT;
- int opflag = ndp->ni_nameiop & OPFLAG;
-#else /* AFS_OSF_ENV */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_lookup(OSI_VC_ARG(adp), aname, avcp, pnp, flags, rdir, acred)
- struct pathname *pnp;
- int flags;
- struct vnode *rdir;
-#else
-#if defined(UKERNEL)
-afs_lookup(adp, aname, avcp, acred, flags)
- int flags;
-#else
-afs_lookup(adp, aname, avcp, acred)
-#endif /* UKERNEL */
-#endif /* SUN5 || SGI */
-OSI_VC_DECL(adp);
- struct vcache **avcp;
- char *aname;
- struct AFS_UCRED *acred;
-{
-#endif
- struct vrequest treq;
- char *tname = NULL;
- register struct vcache *tvc = 0;
- register afs_int32 code;
- register afs_int32 bulkcode = 0;
- int pass = 0, hit = 0;
- long dirCookie;
- extern afs_int32 afs_mariner; /*Writing activity to log? */
- OSI_VC_CONVERT(adp)
- afs_hyper_t versionNo;
- int no_read_access = 0;
- struct sysname_info sysState; /* used only for @sys checking */
- int dynrootRetry = 1;
- struct afs_fakestat_state fakestate;
- int tryEvalOnly = 0;
-
- AFS_STATCNT(afs_lookup);
- afs_InitFakeStat(&fakestate);
-
- if ((code = afs_InitReq(&treq, acred)))
- goto done;
-
-#ifdef AFS_OSF_ENV
- ndp->ni_dvp = AFSTOV(adp);
- memcpy(aname, ndp->ni_ptr, ndp->ni_namelen);
- aname[ndp->ni_namelen] = '\0';
-#endif /* AFS_OSF_ENV */
-
-#if defined(AFS_DARWIN_ENV)
- /* Workaround for MacOSX Finder, which tries to look for
- * .DS_Store and Contents under every directory.
- */
- if (afs_fakestat_enable && adp->mvstat == 1) {
- if (strcmp(aname, ".DS_Store") == 0)
- tryEvalOnly = 1;
- if (strcmp(aname, "Contents") == 0)
- tryEvalOnly = 1;
- }
-#endif
-
- if (tryEvalOnly)
- code = afs_TryEvalFakeStat(&adp, &fakestate, &treq);
- else
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (tryEvalOnly && adp->mvstat == 1)
- code = ENOENT;
- if (code)
- goto done;
-
- *avcp = NULL; /* Since some callers don't initialize it */
-
- /* come back to here if we encounter a non-existent object in a read-only
- * volume's directory */
-
- redo:
- *avcp = NULL; /* Since some callers don't initialize it */
- bulkcode = 0;
-
- if (!(adp->states & CStatd)) {
- if ((code = afs_VerifyVCache2(adp, &treq))) {
- goto done;
- }
- } else
- code = 0;
-
- /* watch for ".." in a volume root */
- if (adp->mvstat == 2 && aname[0] == '.' && aname[1] == '.' && !aname[2]) {
- /* looking up ".." in root via special hacks */
- if (adp->mvid == (struct VenusFid *)0 || adp->mvid->Fid.Volume == 0) {
-#ifdef AFS_OSF_ENV
- extern struct vcache *afs_globalVp;
- if (adp == afs_globalVp) {
- struct vnode *rvp = AFSTOV(adp);
-/*
- ndp->ni_vp = rvp->v_vfsp->vfs_vnodecovered;
- ndp->ni_dvp = ndp->ni_vp;
- VN_HOLD(*avcp);
-*/
- code = ENODEV;
- goto done;
- }
-#endif
- code = ENODEV;
- goto done;
- }
- /* otherwise we have the fid here, so we use it */
- tvc = afs_GetVCache(adp->mvid, &treq, NULL, NULL);
- afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code);
- *avcp = tvc;
- code = (tvc ? 0 : ENOENT);
- hit = 1;
- if (tvc && !VREFCOUNT(tvc)) {
- osi_Panic("TT1");
- }
- if (code) {
- /*printf("LOOKUP GETVCDOTDOT -> %d\n", code); */
- }
- goto done;
- }
-
- /* now check the access */
- if (treq.uid != adp->last_looker) {
- if (!afs_AccessOK(adp, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS)) {
- *avcp = NULL;
- code = EACCES;
- goto done;
- } else
- adp->last_looker = treq.uid;
- }
-
- /* Check for read access as well. We need read access in order to
- * stat files, but not to stat subdirectories. */
- if (!afs_AccessOK(adp, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS))
- no_read_access = 1;
-
- /* special case lookup of ".". Can we check for it sooner in this code,
- * for instance, way up before "redo:" ??
- * I'm not fiddling with the LRUQ here, either, perhaps I should, or else
- * invent a lightweight version of GetVCache.
- */
- if (aname[0] == '.' && !aname[1]) { /* special case */
- ObtainReadLock(&afs_xvcache);
- osi_vnhold(adp, 0);
- ReleaseReadLock(&afs_xvcache);
- code = 0;
- *avcp = tvc = adp;
- hit = 1;
- if (adp && !VREFCOUNT(adp)) {
- osi_Panic("TT2");
- }
- goto done;
- }
-
- Check_AtSys(adp, aname, &sysState, &treq);
- tname = sysState.name;
-
- /* 1st Check_AtSys and lookup by tname is required here, for now,
- * because the dnlc is *not* told to remove entries for the parent
- * dir of file/dir op that afs_LocalHero likes, but dnlc is informed
- * if the cached entry for the parent dir is invalidated for a
- * non-local change.
- * Otherwise, we'd be able to do a dnlc lookup on an entry ending
- * w/@sys and know the dnlc was consistent with reality. */
- tvc = osi_dnlc_lookup(adp, tname, WRITE_LOCK);
- *avcp = tvc; /* maybe wasn't initialized, but it is now */
- if (tvc) {
- if (no_read_access && vType(tvc) != VDIR && vType(tvc) != VLNK) {
- /* need read access on dir to stat non-directory / non-link */
- afs_PutVCache(tvc);
- *avcp = NULL;
- code = EACCES;
- goto done;
- }
-#ifdef AFS_LINUX22_ENV
- if (tvc->mvstat == 2) { /* we don't trust the dnlc for root vcaches */
- AFS_RELE(tvc);
- *avcp = 0;
- } else {
- code = 0;
- hit = 1;
- goto done;
- }
-#else /* non - LINUX */
- code = 0;
- hit = 1;
- goto done;
-#endif /* linux22 */
- }
-
- { /* sub-block just to reduce stack usage */
- register struct dcache *tdc;
- afs_size_t dirOffset, dirLen;
- ino_t theDir;
- struct VenusFid tfid;
-
- /* now we have to lookup the next fid */
- tdc =
- afs_GetDCache(adp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
- if (!tdc) {
- *avcp = NULL; /* redundant, but harmless */
- code = EIO;
- goto done;
- }
-
- /* now we will just call dir package with appropriate inode.
- * Dirs are always fetched in their entirety for now */
- ObtainReadLock(&adp->lock);
- ObtainReadLock(&tdc->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((adp->states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(adp->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&adp->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&adp->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(adp->states & CStatd)
- || !hsame(adp->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&adp->lock);
- afs_PutDCache(tdc);
- if (tname && tname != aname)
- osi_FreeLargeSpace(tname);
- goto redo;
- }
-
- /* Save the version number for when we call osi_dnlc_enter */
- hset(versionNo, tdc->f.versionNo);
-
- /*
- * check for, and handle "@sys" if it's there. We should be able
- * to avoid the alloc and the strcpy with a little work, but it's
- * not pressing. If there aren't any remote users (ie, via the
- * NFS translator), we have a slightly easier job.
- * the faster way to do this is to check for *aname == '@' and if
- * it's there, check for @sys, otherwise, assume there's no @sys
- * then, if the lookup fails, check for .*@sys...
- */
- /* above now implemented by Check_AtSys and Next_AtSys */
-
- /* lookup the name in the appropriate dir, and return a cache entry
- * on the resulting fid */
- theDir = tdc->f.inode;
- code =
- afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
- &dirCookie);
-
- /* If the first lookup doesn't succeed, maybe it's got @sys in the name */
- while (code == ENOENT && Next_AtSys(adp, &treq, &sysState))
- code =
- afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
- &dirCookie);
- tname = sysState.name;
-
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
-
- if (code == ENOENT && afs_IsDynroot(adp) && dynrootRetry) {
- ReleaseReadLock(&adp->lock);
- dynrootRetry = 0;
- if (tname[0] == '.')
- afs_LookupAFSDB(tname + 1);
- else
- afs_LookupAFSDB(tname);
- if (tname && tname != aname)
- osi_FreeLargeSpace(tname);
- goto redo;
- } else {
- ReleaseReadLock(&adp->lock);
- }
-
- /* new fid has same cell and volume */
- tfid.Cell = adp->fid.Cell;
- tfid.Fid.Volume = adp->fid.Fid.Volume;
- afs_Trace4(afs_iclSetp, CM_TRACE_LOOKUP, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, tname, ICL_TYPE_FID, &tfid,
- ICL_TYPE_INT32, code);
-
- if (code) {
- if (code != ENOENT) {
- printf("LOOKUP dirLookupOff -> %d\n", code);
- }
- goto done;
- }
-
- /* prefetch some entries, if the dir is currently open. The variable
- * dirCookie tells us where to start prefetching from.
- */
- if (AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign)
- && !afs_IsDynroot(adp)) {
- afs_int32 retry;
- /* if the entry is not in the cache, or is in the cache,
- * but hasn't been statd, then do a bulk stat operation.
- */
- do {
- retry = 0;
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&tfid, &retry, 0 /* !stats,!lru */ );
- ReleaseReadLock(&afs_xvcache);
- } while (tvc && retry);
-
- if (!tvc || !(tvc->states & CStatd))
- bulkcode = afs_DoBulkStat(adp, dirCookie, &treq);
- else
- bulkcode = 0;
-
- /* if the vcache isn't usable, release it */
- if (tvc && !(tvc->states & CStatd)) {
- afs_PutVCache(tvc);
- tvc = NULL;
- }
- } else {
- tvc = NULL;
- bulkcode = 0;
- }
-
- /* now get the status info, if we don't already have it */
- /* This is kind of weird, but we might wind up accidentally calling
- * RXAFS_Lookup because we happened upon a file which legitimately
- * has a 0 uniquifier. That is the result of allowing unique to wrap
- * to 0. This was fixed in AFS 3.4. For CForeign, Unique == 0 means that
- * the file has not yet been looked up.
- */
- if (!tvc) {
- afs_int32 cached = 0;
- if (!tfid.Fid.Unique && (adp->states & CForeign)) {
- tvc = afs_LookupVCache(&tfid, &treq, &cached, adp, tname);
- }
- if (!tvc && !bulkcode) { /* lookup failed or wasn't called */
- tvc = afs_GetVCache(&tfid, &treq, &cached, NULL);
- }
- } /* if !tvc */
- } /* sub-block just to reduce stack usage */
-
- if (tvc) {
- int force_eval = afs_fakestat_enable ? 0 : 1;
-
- if (adp->states & CForeign)
- tvc->states |= CForeign;
- tvc->parentVnode = adp->fid.Fid.Vnode;
- tvc->parentUnique = adp->fid.Fid.Unique;
- tvc->states &= ~CBulkStat;
-
- if (afs_fakestat_enable == 2 && tvc->mvstat == 1) {
- ObtainSharedLock(&tvc->lock, 680);
- if (!tvc->linkData) {
- UpgradeSToWLock(&tvc->lock, 681);
- code = afs_HandleLink(tvc, &treq);
- ConvertWToRLock(&tvc->lock);
- } else {
- ConvertSToRLock(&tvc->lock);
- code = 0;
- }
- if (!code && !afs_strchr(tvc->linkData, ':'))
- force_eval = 1;
- ReleaseReadLock(&tvc->lock);
- }
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
- if (!(flags & AFS_LOOKUP_NOEVAL))
- /* don't eval mount points */
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
- if (tvc->mvstat == 1 && force_eval) {
- /* a mt point, possibly unevaluated */
- struct volume *tvolp;
-
- ObtainWriteLock(&tvc->lock, 133);
- code = EvalMountPoint(tvc, adp, &tvolp, &treq);
- ReleaseWriteLock(&tvc->lock);
-
- if (code) {
- afs_PutVCache(tvc);
- if (tvolp)
- afs_PutVolume(tvolp, WRITE_LOCK);
- goto done;
- }
-
- /* next, we want to continue using the target of the mt point */
- if (tvc->mvid && (tvc->states & CMValid)) {
- struct vcache *uvc;
- /* now lookup target, to set .. pointer */
- afs_Trace2(afs_iclSetp, CM_TRACE_LOOKUP1,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_FID,
- &tvc->fid);
- uvc = tvc; /* remember for later */
-
- if (tvolp && (tvolp->states & VForeign)) {
- /* XXXX tvolp has ref cnt on but not locked! XXX */
- tvc =
- afs_GetRootVCache(tvc->mvid, &treq, NULL, tvolp);
- } else {
- tvc = afs_GetVCache(tvc->mvid, &treq, NULL, NULL);
- }
- afs_PutVCache(uvc); /* we're done with it */
-
- if (!tvc) {
- code = ENOENT;
- if (tvolp) {
- afs_PutVolume(tvolp, WRITE_LOCK);
- }
- goto done;
- }
-
- /* now, if we came via a new mt pt (say because of a new
- * release of a R/O volume), we must reevaluate the ..
- * ptr to point back to the appropriate place */
- if (tvolp) {
- ObtainWriteLock(&tvc->lock, 134);
- if (tvc->mvid == NULL) {
- tvc->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- }
- /* setup backpointer */
- *tvc->mvid = tvolp->dotdot;
- ReleaseWriteLock(&tvc->lock);
- afs_PutVolume(tvolp, WRITE_LOCK);
- }
- } else {
- afs_PutVCache(tvc);
- code = ENOENT;
- if (tvolp)
- afs_PutVolume(tvolp, WRITE_LOCK);
- goto done;
- }
- }
- *avcp = tvc;
- if (tvc && !VREFCOUNT(tvc)) {
- osi_Panic("TT3");
- }
- code = 0;
- } else {
- /* if we get here, we found something in a directory that couldn't
- * be located (a Multics "connection failure"). If the volume is
- * read-only, we try flushing this entry from the cache and trying
- * again. */
- if (pass == 0) {
- struct volume *tv;
- tv = afs_GetVolume(&adp->fid, &treq, READ_LOCK);
- if (tv) {
- if (tv->states & VRO) {
- pass = 1; /* try this *once* */
- ObtainWriteLock(&afs_xcbhash, 495);
- afs_DequeueCallback(adp);
- /* re-stat to get later version */
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- afs_PutVolume(tv, READ_LOCK);
- goto redo;
- }
- afs_PutVolume(tv, READ_LOCK);
- }
- }
- code = ENOENT;
- }
-
- done:
- /* put the network buffer back, if need be */
- if (tname != aname && tname)
- osi_FreeLargeSpace(tname);
- if (code == 0) {
-#ifdef AFS_OSF_ENV
- /* Handle RENAME; only need to check rename "." */
- if (opflag == RENAME && wantparent && *ndp->ni_next == 0) {
- if (!FidCmp(&(tvc->fid), &(adp->fid))) {
- afs_PutVCache(*avcp);
- *avcp = NULL;
- afs_PutFakeStat(&fakestate);
- return afs_CheckCode(EISDIR, &treq, 18);
- }
- }
-#endif /* AFS_OSF_ENV */
-
- if (afs_mariner)
- afs_AddMarinerName(aname, tvc);
-
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
- if (!(flags & AFS_LOOKUP_NOEVAL))
- /* Here we don't enter the name into the DNLC because we want the
- * evaluated mount dir to be there (the vcache for the mounted volume)
- * rather than the vc of the mount point itself. we can still find the
- * mount point's vc in the vcache by its fid. */
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
- if (!hit) {
- osi_dnlc_enter(adp, aname, tvc, &versionNo);
- } else {
-#ifdef AFS_LINUX20_ENV
- /* So Linux inode cache is up to date. */
- code = afs_VerifyVCache(tvc, &treq);
-#else
- afs_PutFakeStat(&fakestate);
- return 0; /* can't have been any errors if hit and !code */
-#endif
- }
- }
- if (bulkcode)
- code = bulkcode;
- else
- code = afs_CheckCode(code, &treq, 19);
- if (code) {
- /* If there is an error, make sure *avcp is null.
- * Alphas panic otherwise - defect 10719.
- */
- *avcp = NULL;
- }
-
- afs_PutFakeStat(&fakestate);
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_open
- *
- */
-
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_open.c,v 1.10 2003/07/15 23:14:30 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-
-/* given a vnode ptr, open flags and credentials, open the file. No access
- * checks are done here, instead they're done by afs_create or afs_access,
- * both called by the vn_open call.
- */
-int
-#ifdef AFS_SGI64_ENV
-afs_open(bhv_desc_t * bhv, struct vcache **avcp, afs_int32 aflags,
- struct AFS_UCRED *acred)
-#else
-afs_open(struct vcache **avcp, afs_int32 aflags, struct AFS_UCRED *acred)
-#endif
-{
- register afs_int32 code;
- struct vrequest treq;
- struct vcache *tvc;
- int writing;
- struct afs_fakestat_state fakestate;
-
- AFS_STATCNT(afs_open);
- if ((code = afs_InitReq(&treq, acred)))
- return code;
-#ifdef AFS_SGI64_ENV
- /* avcpp can be, but is not necesarily, bhp's vnode. */
- tvc = VTOAFS(BHV_TO_VNODE(bhv));
-#else
- tvc = *avcp;
-#endif
- afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_INT32, aflags);
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
- if (code)
- goto done;
- code = afs_VerifyVCache(tvc, &treq);
- if (code)
- goto done;
- if (aflags & (FWRITE | FTRUNC))
- writing = 1;
- else
- writing = 0;
- if (vType(tvc) == VDIR) {
- /* directory */
- if (writing) {
- code = EISDIR;
- goto done;
- } else {
- if (!afs_AccessOK
- (tvc, ((tvc->states & CForeign) ? PRSFS_READ : PRSFS_LOOKUP),
- &treq, CHECK_MODE_BITS)) {
- code = EACCES;
- goto done;
- }
- }
- } else {
-#ifdef AFS_SUN5_ENV
- if (AFS_NFSXLATORREQ(acred) && (aflags & FREAD)) {
- if (!afs_AccessOK
- (tvc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- code = EACCES;
- goto done;
- }
- }
-#endif
-#ifdef AFS_AIX41_ENV
- if (aflags & FRSHARE) {
- /*
- * Hack for AIX 4.1:
- * Apparently it is possible for a file to get mapped without
- * either VNOP_MAP or VNOP_RDWR being called, if (1) it is a
- * sharable library, and (2) it has already been loaded. We must
- * ensure that the credp is up to date. We detect the situation
- * by checking for O_RSHARE at open time.
- */
- /*
- * We keep the caller's credentials since an async daemon will
- * handle the request at some point. We assume that the same
- * credentials will be used.
- */
- ObtainWriteLock(&tvc->lock, 140);
- if (!tvc->credp || (tvc->credp != acred)) {
- crhold(acred);
- if (tvc->credp) {
- struct ucred *crp = tvc->credp;
- tvc->credp = NULL;
- crfree(crp);
- }
- tvc->credp = acred;
- }
- ReleaseWriteLock(&tvc->lock);
- }
-#endif
- /* normal file or symlink */
- osi_FlushText(tvc); /* only needed to flush text if text locked last time */
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc);
-#endif
- osi_FlushPages(tvc, acred);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- }
- /* set date on file if open in O_TRUNC mode */
- if (aflags & FTRUNC) {
- /* this fixes touch */
- ObtainWriteLock(&tvc->lock, 123);
- tvc->m.Date = osi_Time();
- tvc->states |= CDirty;
- ReleaseWriteLock(&tvc->lock);
- }
- ObtainReadLock(&tvc->lock);
- if (writing)
- tvc->execsOrWriters++;
- tvc->opens++;
-#if defined(AFS_SGI_ENV)
- if (writing && tvc->cred == NULL) {
- crhold(acred);
- tvc->cred = acred;
- }
-#endif
- ReleaseReadLock(&tvc->lock);
- done:
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 4); /* avoid AIX -O bug */
-
- afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_INT32, 999999);
-
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_MemRead
- * afs_PrefetchChunk
- * afs_UFSRead
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_read.c,v 1.25 2003/08/27 21:43:19 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-extern char afs_zeros[AFS_ZEROS];
-
-afs_int32 maxIHint;
-afs_int32 nihints; /* # of above actually in-use */
-afs_int32 usedihint;
-
-
-/* Imported variables */
-extern afs_rwlock_t afs_xdcache;
-extern unsigned char *afs_indexFlags;
-extern afs_hyper_t *afs_indexTimes; /* Dcache entry Access times */
-extern afs_hyper_t afs_indexCounter; /* Fake time for marking index */
-
-
-/* Forward declarations */
-void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq);
-
-int
-afs_MemRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
- int noLock)
-{
- afs_size_t totalLength;
- afs_size_t transferLength;
- afs_size_t filePos;
- afs_size_t offset, len, tlen;
- afs_int32 trimlen;
- struct dcache *tdc = 0;
- afs_int32 error, trybusy = 1;
- struct uio tuio;
- struct iovec *tvec;
- afs_int32 code;
- struct vrequest treq;
-
- AFS_STATCNT(afs_MemRead);
- if (avc->vc_error)
- return EIO;
-
- /* check that we have the latest status info in the vnode cache */
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- if (!noLock) {
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 8); /* failed to get it */
- return code;
- }
- }
-#ifndef AFS_VM_RDWR_ENV
- if (AFS_NFSXLATORREQ(acred)) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- return afs_CheckCode(EACCES, &treq, 9);
- }
- }
-#endif
-
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
- afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
- totalLength, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- error = 0;
- transferLength = 0;
- if (!noLock)
- ObtainReadLock(&avc->lock);
-#if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
- if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
- hset(avc->flushDV, avc->m.DataVersion);
- }
-#endif
-
- /*
- * Locks held:
- * avc->lock(R)
- */
- while (totalLength > 0) {
- /* read all of the cached info */
- if (filePos >= avc->m.Length)
- break; /* all done */
- if (noLock) {
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- tdc = afs_FindDCache(avc, filePos);
- if (tdc) {
- ObtainReadLock(&tdc->lock);
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->f.chunkBytes - offset;
- }
- } else {
- /* a tricky question: does the presence of the DFFetching flag
- * mean that we're fetching the latest version of the file? No.
- * The server could update the file as soon as the fetch responsible
- * for the setting of the DFFetching flag completes.
- *
- * However, the presence of the DFFetching flag (visible under
- * a dcache read lock since it is set and cleared only under a
- * dcache write lock) means that we're fetching as good a version
- * as was known to this client at the time of the last call to
- * afs_VerifyVCache, since the latter updates the stat cache's
- * m.DataVersion field under a vcache write lock, and from the
- * time that the DFFetching flag goes on in afs_GetDCache (before
- * the fetch starts), to the time it goes off (after the fetch
- * completes), afs_GetDCache keeps at least a read lock on the
- * vcache entry.
- *
- * This means that if the DFFetching flag is set, we can use that
- * data for any reads that must come from the current version of
- * the file (current == m.DataVersion).
- *
- * Another way of looking at this same point is this: if we're
- * fetching some data and then try do an afs_VerifyVCache, the
- * VerifyVCache operation will not complete until after the
- * DFFetching flag is turned off and the dcache entry's f.versionNo
- * field is updated.
- *
- * Note, by the way, that if DFFetching is set,
- * m.DataVersion > f.versionNo (the latter is not updated until
- * after the fetch completes).
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc); /* before reusing tdc */
- }
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
- ObtainReadLock(&tdc->lock);
- /* now, first try to start transfer, if we'll need the data. If
- * data already coming, we don't need to do this, obviously. Type
- * 2 requests never return a null dcache entry, btw.
- */
- if (!(tdc->dflags & DFFetching)
- && !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- /* have cache entry, it is not coming in now,
- * and we'll need new data */
- tagain:
- if (trybusy && !afs_BBusy()) {
- struct brequest *bp;
- /* daemon is not busy */
- ObtainSharedLock(&tdc->mflock, 665);
- if (!(tdc->mflags & DFFetchReq)) {
- /* start the daemon (may already be running, however) */
- UpgradeSToWLock(&tdc->mflock, 666);
- tdc->mflags |= DFFetchReq;
- bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) filePos, (afs_size_t) 0,
- tdc);
- if (!bp) {
- tdc->mflags &= ~DFFetchReq;
- trybusy = 0; /* Avoid bkg daemon since they're too busy */
- ReleaseWriteLock(&tdc->mflock);
- goto tagain;
- }
- ConvertWToSLock(&tdc->mflock);
- /* don't use bp pointer! */
- }
- code = 0;
- ConvertSToRLock(&tdc->mflock);
- while (!code && tdc->mflags & DFFetchReq) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
- ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
- __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- /* don't need waiting flag on this one */
- ReleaseReadLock(&tdc->mflock);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- ObtainReadLock(&tdc->mflock);
- }
- ReleaseReadLock(&tdc->mflock);
- if (code) {
- error = code;
- break;
- }
- }
- }
- /* now data may have started flowing in (if DFFetching is on). If
- * data is now streaming in, then wait for some interesting stuff.
- */
- code = 0;
- while (!code && (tdc->dflags & DFFetching)
- && tdc->validPos <= filePos) {
- /* too early: wait for DFFetching flag to vanish,
- * or data to appear */
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
- tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (code) {
- error = code;
- break;
- }
- /* fetching flag gone, data is here, or we never tried
- * (BBusy for instance) */
- if (tdc->dflags & DFFetching) {
- /* still fetching, some new data is here:
- * compute length and offset */
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->validPos - filePos;
- } else {
- /* no longer fetching, verify data version
- * (avoid new GetDCache call) */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)
- && ((len = tdc->validPos - filePos) > 0)) {
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- } else {
- /* don't have current data, so get it below */
- afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
- ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
- ICL_TYPE_HYPER, &avc->m.DataVersion,
- ICL_TYPE_HYPER, &tdc->f.versionNo);
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = NULL;
- }
- }
-
- if (!tdc) {
- /* If we get, it was not possible to start the
- * background daemon. With flag == 1 afs_GetDCache
- * does the FetchData rpc synchronously.
- */
- ReleaseReadLock(&avc->lock);
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
- ObtainReadLock(&avc->lock);
- if (tdc)
- ObtainReadLock(&tdc->lock);
- }
- }
-
- afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
- if (!tdc) {
- error = EIO;
- break;
- }
-
- /*
- * Locks held:
- * avc->lock(R)
- * tdc->lock(R)
- */
-
- if (len > totalLength)
- len = totalLength; /* will read len bytes */
- if (len <= 0) { /* shouldn't get here if DFFetching is on */
- /* read past the end of a chunk, may not be at next chunk yet, and yet
- * also not at eof, so may have to supply fake zeros */
- len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
- if (len > totalLength)
- len = totalLength; /* and still within xfr request */
- tlen = avc->m.Length - offset; /* and still within file */
- if (len > tlen)
- len = tlen;
- if (len > AFS_ZEROS)
- len = sizeof(afs_zeros); /* and in 0 buffer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, &tuio, code);
- if (code) {
- error = code;
- break;
- }
- } else {
- /* get the data from the mem cache */
-
- /* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
-
- code = afs_MemReadUIO(tdc->f.inode, &tuio);
-
- if (code) {
- error = code;
- break;
- }
- }
- /* otherwise we've read some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
- trimlen = len;
- afsio_skip(auio, trimlen); /* update input uio structure */
- totalLength -= len;
- transferLength += len;
- filePos += len;
-
- if (len <= 0)
- break; /* surprise eof */
- } /* the whole while loop */
-
- /*
- * Locks held:
- * avc->lock(R)
- * tdc->lock(R) if tdc
- */
-
- /* if we make it here with tdc non-zero, then it is the last chunk we
- * dealt with, and we have to release it when we're done. We hold on
- * to it in case we need to do a prefetch.
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
-#if !defined(AFS_VM_RDWR_ENV)
- /* try to queue prefetch, if needed */
- if (!noLock) {
- afs_PrefetchChunk(avc, tdc, acred, &treq);
- }
-#endif
- afs_PutDCache(tdc);
- }
- if (!noLock)
- ReleaseReadLock(&avc->lock);
- osi_FreeSmallSpace(tvec);
- error = afs_CheckCode(error, &treq, 10);
- return error;
-}
-
-/* called with the dcache entry triggering the fetch, the vcache entry involved,
- * and a vrequest for the read call. Marks the dcache entry as having already
- * triggered a prefetch, starts the prefetch going and sets the DFFetchReq
- * flag in the prefetched block, so that the next call to read knows to wait
- * for the daemon to start doing things.
- *
- * This function must be called with the vnode at least read-locked, and
- * no locks on the dcache, because it plays around with dcache entries.
- */
-void
-afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq)
-{
- register struct dcache *tdc;
- afs_size_t offset;
- afs_size_t j1, j2; /* junk vbls for GetDCache to trash */
-
- offset = adc->f.chunk + 1; /* next chunk we'll need */
- offset = AFS_CHUNKTOBASE(offset); /* base of next chunk */
- ObtainReadLock(&adc->lock);
- ObtainSharedLock(&adc->mflock, 662);
- if (offset < avc->m.Length && !(adc->mflags & DFNextStarted)
- && !afs_BBusy()) {
- struct brequest *bp;
-
- UpgradeSToWLock(&adc->mflock, 663);
- adc->mflags |= DFNextStarted; /* we've tried to prefetch for this guy */
- ReleaseWriteLock(&adc->mflock);
- ReleaseReadLock(&adc->lock);
-
- tdc = afs_GetDCache(avc, offset, areq, &j1, &j2, 2); /* type 2 never returns 0 */
- ObtainSharedLock(&tdc->mflock, 651);
- if (!(tdc->mflags & DFFetchReq)) {
- /* ask the daemon to do the work */
- UpgradeSToWLock(&tdc->mflock, 652);
- tdc->mflags |= DFFetchReq; /* guaranteed to be cleared by BKG or GetDCache */
- /* last parm (1) tells bkg daemon to do an afs_PutDCache when it is done,
- * since we don't want to wait for it to finish before doing so ourselves.
- */
- bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) offset, (afs_size_t) 1, tdc);
- if (!bp) {
- /* Bkg table full; just abort non-important prefetching to avoid deadlocks */
- tdc->mflags &= ~DFFetchReq;
- ReleaseWriteLock(&tdc->mflock);
- afs_PutDCache(tdc);
-
- /*
- * DCLOCKXXX: This is a little sketchy, since someone else
- * could have already started a prefetch.. In practice,
- * this probably doesn't matter; at most it would cause an
- * extra slot in the BKG table to be used up when someone
- * prefetches this for the second time.
- */
- ObtainReadLock(&adc->lock);
- ObtainWriteLock(&adc->mflock, 664);
- adc->mflags &= ~DFNextStarted;
- ReleaseWriteLock(&adc->mflock);
- ReleaseReadLock(&adc->lock);
- } else {
- ReleaseWriteLock(&tdc->mflock);
- }
- } else {
- ReleaseSharedLock(&tdc->mflock);
- afs_PutDCache(tdc);
- }
- } else {
- ReleaseSharedLock(&adc->mflock);
- ReleaseReadLock(&adc->lock);
- }
-}
-
-int
-afs_UFSRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
- int noLock)
-{
- afs_size_t totalLength;
- afs_size_t transferLength;
- afs_size_t filePos;
- afs_size_t offset, len, tlen;
- afs_int32 trimlen;
- struct dcache *tdc = 0;
- afs_int32 error;
- struct uio tuio;
- struct iovec *tvec;
- struct osi_file *tfile;
- afs_int32 code;
- int trybusy = 1;
- struct vrequest treq;
-
- AFS_STATCNT(afs_UFSRead);
- if (avc && avc->vc_error)
- return EIO;
-
- /* check that we have the latest status info in the vnode cache */
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- if (!noLock) {
- if (!avc)
- osi_Panic("null avc in afs_UFSRead");
- else {
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 11); /* failed to get it */
- return code;
- }
- }
- }
-#ifndef AFS_VM_RDWR_ENV
- if (AFS_NFSXLATORREQ(acred)) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- return afs_CheckCode(EACCES, &treq, 12);
- }
- }
-#endif
-
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
- afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
- totalLength, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- error = 0;
- transferLength = 0;
- if (!noLock)
- ObtainReadLock(&avc->lock);
-#if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
- if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
- hset(avc->flushDV, avc->m.DataVersion);
- }
-#endif
-
- while (totalLength > 0) {
- /* read all of the cached info */
- if (filePos >= avc->m.Length)
- break; /* all done */
- if (noLock) {
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- tdc = afs_FindDCache(avc, filePos);
- if (tdc) {
- ObtainReadLock(&tdc->lock);
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->validPos - filePos;
- }
- } else {
- /* a tricky question: does the presence of the DFFetching flag
- * mean that we're fetching the latest version of the file? No.
- * The server could update the file as soon as the fetch responsible
- * for the setting of the DFFetching flag completes.
- *
- * However, the presence of the DFFetching flag (visible under
- * a dcache read lock since it is set and cleared only under a
- * dcache write lock) means that we're fetching as good a version
- * as was known to this client at the time of the last call to
- * afs_VerifyVCache, since the latter updates the stat cache's
- * m.DataVersion field under a vcache write lock, and from the
- * time that the DFFetching flag goes on in afs_GetDCache (before
- * the fetch starts), to the time it goes off (after the fetch
- * completes), afs_GetDCache keeps at least a read lock on the
- * vcache entry.
- *
- * This means that if the DFFetching flag is set, we can use that
- * data for any reads that must come from the current version of
- * the file (current == m.DataVersion).
- *
- * Another way of looking at this same point is this: if we're
- * fetching some data and then try do an afs_VerifyVCache, the
- * VerifyVCache operation will not complete until after the
- * DFFetching flag is turned off and the dcache entry's f.versionNo
- * field is updated.
- *
- * Note, by the way, that if DFFetching is set,
- * m.DataVersion > f.versionNo (the latter is not updated until
- * after the fetch completes).
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc); /* before reusing tdc */
- }
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
- ObtainReadLock(&tdc->lock);
- /* now, first try to start transfer, if we'll need the data. If
- * data already coming, we don't need to do this, obviously. Type
- * 2 requests never return a null dcache entry, btw. */
- if (!(tdc->dflags & DFFetching)
- && !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- /* have cache entry, it is not coming in now, and we'll need new data */
- tagain:
- if (trybusy && !afs_BBusy()) {
- struct brequest *bp;
- /* daemon is not busy */
- ObtainSharedLock(&tdc->mflock, 667);
- if (!(tdc->mflags & DFFetchReq)) {
- UpgradeSToWLock(&tdc->mflock, 668);
- tdc->mflags |= DFFetchReq;
- bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) filePos, (afs_size_t) 0,
- tdc);
- if (!bp) {
- /* Bkg table full; retry deadlocks */
- tdc->mflags &= ~DFFetchReq;
- trybusy = 0; /* Avoid bkg daemon since they're too busy */
- ReleaseWriteLock(&tdc->mflock);
- goto tagain;
- }
- ConvertWToSLock(&tdc->mflock);
- }
- code = 0;
- ConvertSToRLock(&tdc->mflock);
- while (!code && tdc->mflags & DFFetchReq) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
- ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
- __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- /* don't need waiting flag on this one */
- ReleaseReadLock(&tdc->mflock);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- ObtainReadLock(&tdc->mflock);
- }
- ReleaseReadLock(&tdc->mflock);
- if (code) {
- error = code;
- break;
- }
- }
- }
- /* now data may have started flowing in (if DFFetching is on). If
- * data is now streaming in, then wait for some interesting stuff.
- */
- code = 0;
- while (!code && (tdc->dflags & DFFetching)
- && tdc->validPos <= filePos) {
- /* too early: wait for DFFetching flag to vanish,
- * or data to appear */
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
- tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (code) {
- error = code;
- break;
- }
- /* fetching flag gone, data is here, or we never tried
- * (BBusy for instance) */
- if (tdc->dflags & DFFetching) {
- /* still fetching, some new data is here:
- * compute length and offset */
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->validPos - filePos;
- } else {
- /* no longer fetching, verify data version (avoid new
- * GetDCache call) */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)
- && ((len = tdc->validPos - filePos) > 0)) {
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- } else {
- /* don't have current data, so get it below */
- afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
- ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
- ICL_TYPE_HYPER, &avc->m.DataVersion,
- ICL_TYPE_HYPER, &tdc->f.versionNo);
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = NULL;
- }
- }
-
- if (!tdc) {
- /* If we get, it was not possible to start the
- * background daemon. With flag == 1 afs_GetDCache
- * does the FetchData rpc synchronously.
- */
- ReleaseReadLock(&avc->lock);
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
- ObtainReadLock(&avc->lock);
- if (tdc)
- ObtainReadLock(&tdc->lock);
- }
- }
-
- if (!tdc) {
- error = EIO;
- break;
- }
- len = tdc->validPos - filePos;
- afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
- if (len > totalLength)
- len = totalLength; /* will read len bytes */
- if (len <= 0) { /* shouldn't get here if DFFetching is on */
- afs_Trace4(afs_iclSetp, CM_TRACE_VNODEREAD2, ICL_TYPE_POINTER,
- tdc, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(tdc->validPos),
- ICL_TYPE_INT32, tdc->f.chunkBytes, ICL_TYPE_INT32,
- tdc->dflags);
- /* read past the end of a chunk, may not be at next chunk yet, and yet
- * also not at eof, so may have to supply fake zeros */
- len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
- if (len > totalLength)
- len = totalLength; /* and still within xfr request */
- tlen = avc->m.Length - offset; /* and still within file */
- if (len > tlen)
- len = tlen;
- if (len > AFS_ZEROS)
- len = sizeof(afs_zeros); /* and in 0 buffer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, &tuio, code);
- if (code) {
- error = code;
- break;
- }
- } else {
- /* get the data from the file */
-#ifdef IHINT
- if (tfile = tdc->ihint) {
- if (tdc->f.inode != tfile->inum) {
- afs_warn("afs_UFSRead: %x hint mismatch tdc %d inum %d\n",
- tdc, tdc->f.inode, tfile->inum);
- osi_UFSClose(tfile);
- tdc->ihint = tfile = 0;
- nihints--;
- }
- }
- if (tfile != 0) {
- usedihint++;
- } else
-#endif /* IHINT */
-
- tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
- /* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
-#if defined(AFS_AIX41_ENV)
- AFS_GUNLOCK();
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL,
- NULL, afs_osi_credp);
- AFS_GLOCK();
-#elif defined(AFS_AIX32_ENV)
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL);
- /* Flush all JFS pages now for big performance gain in big file cases
- * If we do something like this, must check to be sure that AFS file
- * isn't mmapped... see afs_gn_map() for why.
- */
-/*
- if (tfile->vnode->v_gnode && tfile->vnode->v_gnode->gn_seg) {
- many different ways to do similar things:
- so far, the best performing one is #2, but #1 might match it if we
- straighten out the confusion regarding which pages to flush. It
- really does matter.
- 1. vm_flushp(tfile->vnode->v_gnode->gn_seg, 0, len/PAGESIZE - 1);
- 2. vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
- (len + PAGESIZE-1)/PAGESIZE);
- 3. vms_inactive(tfile->vnode->v_gnode->gn_seg) Doesn't work correctly
- 4. vms_delete(tfile->vnode->v_gnode->gn_seg) probably also fails
- tfile->vnode->v_gnode->gn_seg = NULL;
- 5. deletep
- 6. ipgrlse
- 7. ifreeseg
- Unfortunately, this seems to cause frequent "cache corruption" episodes.
- vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
- (len + PAGESIZE-1)/PAGESIZE);
- }
-*/
-#elif defined(AFS_AIX_ENV)
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
- &tuio, NULL, NULL, -1);
-#elif defined(AFS_SUN5_ENV)
- AFS_GUNLOCK();
- VOP_RWLOCK(tfile->vnode, 0);
- code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_RWUNLOCK(tfile->vnode, 0);
- AFS_GLOCK();
-#elif defined(AFS_SGI_ENV)
- AFS_GUNLOCK();
- AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_VOP_READ(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp,
- code);
- AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_GLOCK();
-#elif defined(AFS_OSF_ENV)
- tuio.uio_rw = UIO_READ;
- AFS_GUNLOCK();
- VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, code);
- AFS_GLOCK();
-#elif defined(AFS_SUN_ENV)
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
-#elif defined(AFS_HPUX100_ENV)
- AFS_GUNLOCK();
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
- AFS_GLOCK();
-#elif defined(AFS_LINUX20_ENV)
- AFS_GUNLOCK();
- code = osi_file_uio_rdwr(tfile, &tuio, UIO_READ);
- AFS_GLOCK();
-#elif defined(AFS_DARWIN_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
- code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, current_proc());
- AFS_GLOCK();
-#elif defined(AFS_FBSD50_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
- code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, curthread);
- AFS_GLOCK();
-#elif defined(AFS_XBSD_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
- code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, curproc);
- AFS_GLOCK();
-#else
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
-#endif
-
-#ifdef IHINT
- if (!tdc->ihint && nihints < maxIHint) {
- tdc->ihint = tfile;
- nihints++;
- } else
-#endif /* IHINT */
- osi_UFSClose(tfile);
-
- if (code) {
- error = code;
- break;
- }
- }
- /* otherwise we've read some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
- trimlen = len;
- afsio_skip(auio, trimlen); /* update input uio structure */
- totalLength -= len;
- transferLength += len;
- filePos += len;
- if (len <= 0)
- break; /* surprise eof */
- }
-
- /* if we make it here with tdc non-zero, then it is the last chunk we
- * dealt with, and we have to release it when we're done. We hold on
- * to it in case we need to do a prefetch, obviously.
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
-#if !defined(AFS_VM_RDWR_ENV)
- /* try to queue prefetch, if needed */
- if (!noLock) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, acred, &treq);
- }
-#endif
- afs_PutDCache(tdc);
- }
- if (!noLock)
- ReleaseReadLock(&avc->lock);
-
- osi_FreeSmallSpace(tvec);
- error = afs_CheckCode(error, &treq, 13);
- return error;
-}
+++ /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
- */
-
-/*
- * afs_vnop_readdir.c - afs_readdir and bulk stat
- *
- * Implements:
- * BlobScan
- * afs_readdir_move
- * afs_bulkstat_send
- * afs_readdir/afs_readdir2(HP)
- * afs_readdir1 - HP and DUX NFS versions
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_readdir.c,v 1.23 2003/11/27 01:17:40 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-#if defined(AFS_HPUX1122_ENV)
-#define DIRPAD 7
-#else
-#define DIRPAD 3
-#endif
-/**
- * A few definitions. This is until we have a proper header file
- * which ahs prototypes for all functions
- */
-
-extern struct DirEntry *afs_dir_GetBlob();
-/*
- * AFS readdir vnodeop and bulk stat support.
- */
-
-/* Saber C hates negative inode #s. We're not going to talk about software
- * that could fail if it sees a negative inode #.
- */
-#define FIXUPSTUPIDINODE(a) ((a) &= 0x7fffffff)
-
-/* BlobScan is supposed to ensure that the blob reference refers to a valid
- directory entry. It consults the allocation map in the page header
- to determine whether a blob is actually in use or not.
-
- More formally, BlobScan is supposed to return a new blob number which is just like
- the input parameter, only it is advanced over header or free blobs.
-
- Note that BlobScan switches pages if necessary. BlobScan may return
- either 0 or an out-of-range blob number for end of file.
-
- BlobScan is used by the Linux port in a separate file, so it should not
- become static.
-*/
-#if defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)
-int
-BlobScan(ino64_t * afile, afs_int32 ablob)
-#else
-#if defined(AFS_HPUX1123_ENV)
-/*DEE should use afs_inode_t for all */
-int
-BlobScan(ino_t *afile, afs_int32 ablob)
-#else
-#ifdef AFS_LINUX_64BIT_KERNEL
-int
-BlobScan(long *afile, afs_int32 ablob)
-#else
-int
-BlobScan(afs_int32 * afile, afs_int32 ablob)
-#endif
-#endif
-#endif
-{
- register afs_int32 relativeBlob;
- afs_int32 pageBlob;
- register struct PageHeader *tpe;
- register afs_int32 i;
-
- AFS_STATCNT(BlobScan);
- /* advance ablob over free and header blobs */
- while (1) {
- pageBlob = ablob & ~(EPP - 1); /* base blob in same page */
- tpe = (struct PageHeader *)afs_dir_GetBlob(afile, pageBlob);
- if (!tpe)
- return 0; /* we've past the end */
- relativeBlob = ablob - pageBlob; /* relative to page's first blob */
- /* first watch for headers */
- if (pageBlob == 0) { /* first dir page has extra-big header */
- /* first page */
- if (relativeBlob < DHE + 1)
- relativeBlob = DHE + 1;
- } else { /* others have one header blob */
- if (relativeBlob == 0)
- relativeBlob = 1;
- }
- /* make sure blob is allocated */
- for (i = relativeBlob; i < EPP; i++) {
- if (tpe->freebitmap[i >> 3] & (1 << (i & 7)))
- break;
- }
- /* now relativeBlob is the page-relative first allocated blob,
- * or EPP (if there are none in this page). */
- DRelease((struct buffer *)tpe, 0);
- if (i != EPP)
- return i + pageBlob;
- ablob = pageBlob + EPP; /* go around again */
- }
- /* never get here */
-}
-
-#if !defined(AFS_LINUX20_ENV)
-/* Changes to afs_readdir which affect dcache or vcache handling or use of
- * bulk stat data should also be reflected in the Linux specific verison of
- * the readdir routine.
- */
-
-/*
- * The kernel don't like it so much to have large stuff on the stack.
- * Here we use a watered down version of the direct struct, since
- * its not too bright to double copy the strings anyway.
-*/
-#if !defined(UKERNEL)
-#if defined(AFS_SGI_ENV)
-/* Long form for 64 bit apps and kernel requests. */
-struct min_dirent { /* miniature dirent structure */
- /* If struct dirent changes, this must too */
- ino_t d_fileno; /* This is 32 bits for 3.5, 64 for 6.2+ */
- off64_t d_off;
- u_short d_reclen;
-};
-/* Short form for 32 bit apps. */
-struct irix5_min_dirent { /* miniature dirent structure */
- /* If struct dirent changes, this must too */
- afs_uint32 d_fileno;
- afs_int32 d_off;
- u_short d_reclen;
-};
-#ifdef AFS_SGI62_ENV
-#define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
-#define AFS_DIRENT64BASESIZE DIRENT64BASESIZE
-#else
-#define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
-#define AFS_DIRENT64BASESIZE DIRENTBASESIZE
-#endif /* AFS_SGI62_ENV */
-#else
-struct min_direct { /* miniature direct structure */
- /* If struct direct changes, this must too */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- afs_uint32 d_fileno;
- u_short d_reclen;
- u_char d_type;
- u_char d_namlen;
-#else
-#ifdef AFS_SUN5_ENV
- afs_uint32 d_fileno;
- afs_int32 d_off;
- u_short d_reclen;
-#else
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
- afs_int32 d_off;
- afs_uint32 d_fileno;
-#endif
-#if defined(AFS_HPUX100_ENV)
- unsigned long long d_off;
- afs_uint32 d_fileno;
-#endif
- u_short d_reclen;
- u_short d_namlen;
-#endif
-#endif
-};
-#endif /* AFS_SGI_ENV */
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-struct minnfs_direct {
- afs_int32 d_off; /* XXX */
- afs_uint32 d_fileno;
- u_short d_reclen;
- u_short d_namlen;
-};
-#define NDIRSIZ_LEN(len) ((sizeof (struct dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + DIRPAD) &~ DIRPAD))
-#endif
-#endif /* !defined(UKERNEL) */
-
-
-/*
- *------------------------------------------------------------------------------
- *
- * Keep a stack of about 256 fids for the bulk stat call.
- * Fill it during the readdir_move. Later empty it...
- */
-
-#define READDIR_STASH AFSCBMAX
-struct AFSFid afs_readdir_stash[READDIR_STASH];
-int afs_rd_stash_i = 0;
-
-/*
- *------------------------------------------------------------------------------
- *
- * afs_readdir_move.
- * mainly a kind of macro... makes getting the struct direct
- * out to the user space easy... could take more parameters,
- * but now just takes what it needs.
- *
- *
-*/
-
-#if defined(AFS_HPUX100_ENV)
-#define DIRSIZ_LEN(len) \
- ((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + DIRPAD) &~ DIRPAD))
-#else
-#if defined(AFS_SUN56_ENV)
-#define DIRSIZ_LEN(len) ((18 + (len) + 1 + 7) & ~7 )
-#else
-#ifdef AFS_SUN5_ENV
-#define DIRSIZ_LEN(len) ((10 + (len) + 1 + (NBPW-1)) & ~(NBPW-1))
-#else
-#ifdef AFS_DIRENT
-#define DIRSIZ_LEN(len) \
- ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
-#else
-#if defined(AFS_SGI_ENV)
-#ifndef AFS_SGI53_ENV
-/* SGI 5.3 and later use 32/64 bit versions of directory size. */
-#define DIRSIZ_LEN(len) DIRENTSIZE(len)
-#endif
-#else /* AFS_SGI_ENV */
-#define DIRSIZ_LEN(len) \
- ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
-#endif /* AFS_SGI_ENV */
-#endif /* AFS_DIRENT */
-#endif /* AFS_SUN5_ENV */
-#endif /* AFS_SUN56_ENV */
-#endif /* AFS_HPUX100_ENV */
-
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-int
-afs_readdir_type(avc, ade)
- struct DirEntry *ade;
- struct vcache *avc;
-{
- struct VenusFid tfid;
- struct vcache *tvc;
- int vtype;
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = avc->fid.Fid.Volume;
- tfid.Fid.Vnode = ntohl(ade->fid.vnode);
- tfid.Fid.Unique = ntohl(ade->fid.vunique);
- if ((avc->states & CForeign) == 0 && (ntohl(ade->fid.vnode) & 1)) {
- return DT_DIR;
- } else if ((tvc = afs_FindVCache(&tfid, 0, 0))) {
- if (tvc->mvstat) {
- afs_PutVCache(tvc);
- return DT_DIR;
- } else if (((tvc->states) & (CStatd | CTruth))) {
- /* CTruth will be set if the object has
- *ever* been statd */
- vtype = vType(tvc);
- afs_PutVCache(tvc);
- if (vtype == VDIR)
- return DT_DIR;
- else if (vtype == VREG)
- return DT_REG;
- /* Don't do this until we're sure it can't be a mtpt */
- /* else if (vtype == VLNK)
- * type=DT_LNK; */
- /* what other types does AFS support? */
- } else
- afs_PutVCache(tvc);
- }
- return DT_UNKNOWN;
-}
-#endif
-
-#ifdef AFS_AIX41_ENV
-#define AFS_MOVE_LOCK() AFS_GLOCK()
-#define AFS_MOVE_UNLOCK() AFS_GUNLOCK()
-#else
-#define AFS_MOVE_LOCK()
-#define AFS_MOVE_UNLOCK()
-#endif
-char bufofzeros[64]; /* gotta fill with something */
-
-int
-afs_readdir_move(de, vc, auio, slen, rlen, off)
- struct DirEntry *de;
- struct vcache *vc;
- struct uio *auio;
- int slen;
-#ifdef AFS_SGI65_ENV
- ssize_t rlen;
-#else
- int rlen;
-#endif
- afs_size_t off;
-{
- int code = 0;
-#if defined(AFS_SUN56_ENV)
- struct dirent64 *direntp;
-#else
-#if defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
- struct dirent *direntp;
-#endif
-#endif /* AFS_SUN56_ENV */
-#ifndef AFS_SGI53_ENV
- struct min_direct sdirEntry;
-#endif /* AFS_SGI53_ENV */
-
- AFS_STATCNT(afs_readdir_move);
-#ifdef AFS_SGI53_ENV
- {
- afs_int32 use64BitDirent;
-
-#ifdef AFS_SGI61_ENV
-#ifdef AFS_SGI62_ENV
- use64BitDirent =
- ABI_IS(ABI_IRIX5_64, GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
-#else
- use64BitDirent =
- (auio->uio_segflg !=
- UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64 |
- ABI_IRIX5_N32,
- u.u_procp->p_abi));
-#endif
-#else /* AFS_SGI61_ENV */
- use64BitDirent =
- (auio->uio_segflg !=
- UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64,
- u.u_procp->p_abi));
-#endif /* AFS_SGI61_ENV */
-
- if (use64BitDirent) {
- struct min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
- sdirEntry.d_reclen = rlen;
- sdirEntry.d_off = (off_t) off;
- AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
- if (code == 0)
- AFS_UIOMOVE(bufofzeros,
- DIRENTSIZE(slen) - (AFS_DIRENT64BASESIZE + slen -
- 1), UIO_READ, auio, code);
- if (DIRENTSIZE(slen) < rlen) {
- while (DIRENTSIZE(slen) < rlen) {
- int minLen = rlen - DIRENTSIZE(slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
- } else {
- struct irix5_min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
- sdirEntry.d_reclen = rlen;
- sdirEntry.d_off = (afs_int32) off;
- AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
- if (code == 0)
- AFS_UIOMOVE(bufofzeros,
- IRIX5_DIRENTSIZE(slen) - (AFS_DIRENT32BASESIZE +
- slen - 1), UIO_READ,
- auio, code);
- if (IRIX5_DIRENTSIZE(slen) < rlen) {
- while (IRIX5_DIRENTSIZE(slen) < rlen) {
- int minLen = rlen - IRIX5_DIRENTSIZE(slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
- }
- }
-#else /* AFS_SGI53_ENV */
-#if defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
-#if defined(AFS_SUN56_ENV)
- direntp = (struct dirent64 *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-#else
- direntp = (struct dirent *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-#endif
- direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(direntp->d_ino);
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- direntp->d_offset = off;
- direntp->d_namlen = slen;
-#else
- direntp->d_off = off;
-#endif
- direntp->d_reclen = rlen;
- strcpy(direntp->d_name, de->name);
- AFS_UIOMOVE((caddr_t) direntp, rlen, UIO_READ, auio, code);
- osi_FreeLargeSpace((char *)direntp);
-#else /* AFS_SUN5_ENV */
- /* Note the odd mechanism for building the inode number */
- sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
- sdirEntry.d_reclen = rlen;
-#if !defined(AFS_SGI_ENV)
- sdirEntry.d_namlen = slen;
-#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
- sdirEntry.d_off = off;
-#endif
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- sdirEntry.d_type = afs_readdir_type(vc, de);
-#endif
-
-#if defined(AFS_SGI_ENV)
- AFS_UIOMOVE(&sdirEntry, DIRENTBASESIZE, UIO_READ, auio, code);
- if (code == 0)
- AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
- if (code == 0)
- AFS_UIOMOVE(bufofzeros,
- DIRSIZ_LEN(slen) - (DIRENTBASESIZE + slen - 1), UIO_READ,
- auio, code);
-#else /* AFS_SGI_ENV */
- AFS_MOVE_UNLOCK();
- AFS_UIOMOVE((char *)&sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
-
- if (code == 0) {
- AFS_UIOMOVE(de->name, slen, UIO_READ, auio, code);
- }
-
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros, ((slen + 1 + DIRPAD) & ~DIRPAD) - slen,
- UIO_READ, auio, code);
- }
- AFS_MOVE_LOCK();
-#endif /* AFS_SGI_ENV */
-
- /* pad out the difference between rlen and slen... */
- if (DIRSIZ_LEN(slen) < rlen) {
- AFS_MOVE_UNLOCK();
- while (DIRSIZ_LEN(slen) < rlen) {
- int minLen = rlen - DIRSIZ_LEN(slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- AFS_MOVE_LOCK();
- }
-#endif /* AFS_SUN5_ENV */
-#endif /* AFS_SGI53_ENV */
- return (code);
-}
-
-
-/*
- *------------------------------------------------------------------------------
- *
- * Read directory entries.
- * There are some weird things to look out for here. The uio_offset
- * field is either 0 or it is the offset returned from a previous
- * readdir. It is an opaque value used by the server to find the
- * correct directory block to read. The byte count must be at least
- * vtoblksz(vp) bytes. The count field is the number of blocks to
- * read on the server. This is advisory only, the server may return
- * only one block's worth of entries. Entries may be compressed on
- * the server.
- *
- * This routine encodes knowledge of Vice dirs.
- */
-
-void
-afs_bulkstat_send(avc, req)
- struct vcache *avc;
- struct vrequest *req;
-{
- afs_rd_stash_i = 0;
-}
-
-/*
- * Here is the bad, bad, really bad news.
- * It has to do with 'offset' (seek locations).
-*/
-
-int
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_readdir(OSI_VC_ARG(avc), auio, acred, eofp)
- int *eofp;
-#else
-#if defined(AFS_HPUX100_ENV)
-afs_readdir2(OSI_VC_ARG(avc), auio, acred)
-#else
-afs_readdir(OSI_VC_ARG(avc), auio, acred)
-#endif
-#endif
- OSI_VC_DECL(avc);
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- struct vrequest treq;
- register struct dcache *tdc;
- afs_size_t origOffset, tlen;
- afs_int32 len;
- int code = 0;
- struct DirEntry *ode = 0, *nde = 0;
- int o_slen = 0, n_slen = 0;
- afs_uint32 us;
- struct afs_fakestat_state fakestate;
-#if defined(AFS_SGI53_ENV)
- afs_int32 use64BitDirent, dirsiz;
-#endif /* defined(AFS_SGI53_ENV) */
- OSI_VC_CONVERT(avc)
-#ifdef AFS_HPUX_ENV
- /*
- * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
- * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
- * translator side XXX
- */
- struct min_direct *sdirEntry =
- (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
- afs_int32 rlen;
-#endif
-
- /* opaque value is pointer into a vice dir; use bit map to decide
- * if the entries are in use. Always assumed to be valid. 0 is
- * special, means start of a new dir. Int32 inode, followed by
- * short reclen and short namelen. Namelen does not include
- * the null byte. Followed by null-terminated string.
- */
- AFS_STATCNT(afs_readdir);
-
-#if defined(AFS_SGI53_ENV)
-#ifdef AFS_SGI61_ENV
-#ifdef AFS_SGI62_ENV
- use64BitDirent =
- ABI_IS(ABI_IRIX5_64, GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
-#else
- use64BitDirent =
- (auio->uio_segflg !=
- UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32,
- u.u_procp->p_abi));
-#endif /* AFS_SGI62_ENV */
-#else /* AFS_SGI61_ENV */
- use64BitDirent =
- (auio->uio_segflg !=
- UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64,
- u.u_procp->p_abi));
-#endif /* AFS_SGI61_ENV */
-#endif /* defined(AFS_SGI53_ENV) */
-
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- /* Not really used by the callee so we ignore it for now */
- if (eofp)
- *eofp = 0;
-#endif
- if (AfsLargeFileUio(auio) /* file is large than 2 GB */
- ||AfsLargeFileSize(auio->uio_offset, auio->uio_resid))
- return EFBIG;
-
- if ((code = afs_InitReq(&treq, acred))) {
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- return code;
- }
- /* update the cache entry */
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code)
- goto done;
- tagain:
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto done;
- /* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
- len = tlen;
- if (!tdc) {
- code = ENOENT;
- goto done;
- }
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((avc->states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- /*
- * iterator for the directory reads. Takes the AFS DirEntry
- * structure and slams them into UFS direct structures.
- * uses afs_readdir_move to get the struct to the user space.
- *
- * The routine works by looking ahead one AFS directory entry.
- * That's because the AFS entry we are currenly working with
- * may not fit into the buffer the user has provided. If it
- * doesn't we have to change the size of the LAST AFS directory
- * entry, so that it will FIT perfectly into the block the
- * user has provided.
- *
- * The 'forward looking' of the code makes it a bit tough to read.
- * Remember we need to get an entry, see if it it fits, then
- * set it up as the LAST entry, and find the next one.
- *
- * Tough to take: We give out an EINVAL if we don't have enough
- * space in the buffer, and at the same time, don't have an entry
- * to put into the buffer. This CAN happen if the first AFS entry
- * we get can't fit into the 512 character buffer provided. Seems
- * it ought not happen...
- *
- * Assumption: don't need to use anything but one dc entry:
- * this means the directory ought not be greater than 64k.
- */
- len = 0;
-#ifdef AFS_HPUX_ENV
- auio->uio_fpflags = 0;
-#endif
- while (code == 0) {
- origOffset = auio->afsio_offset;
- /* scan for the next interesting entry scan for in-use blob otherwise up point at
- * this blob note that ode, if non-zero, also represents a held dir page */
- if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f.inode, us))) {
- /* failed to setup nde, return what we've got, and release ode */
- if (len) {
- /* something to hand over. */
-#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
- sdirEntry->d_off = origOffset;
-#endif
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (DIRSIZ_LEN(o_slen) < rlen) {
- while (DIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - DIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code = afs_readdir_move(ode, avc, auio, o_slen,
-#if defined(AFS_SUN5_ENV)
- len, origOffset);
-#else
- auio->afsio_resid, origOffset);
-#endif
-#endif /* AFS_HPUX_ENV */
-#if !defined(AFS_SUN5_ENV)
- auio->afsio_resid = 0;
-#endif
- } else {
- /* nothin to hand over */
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if (eofp)
- *eofp = 1; /* Set it properly */
-#endif
- if (ode)
- DRelease((struct buffer *)ode, 0);
- goto dirend;
- }
- /* by here nde is set */
-
- /* Do we have enough user space to carry out our mission? */
-#if defined(AFS_SGI_ENV)
- n_slen = strlen(nde->name) + 1; /* NULL terminate */
-#else
- n_slen = strlen(nde->name);
-#endif
-#ifdef AFS_SGI53_ENV
- dirsiz =
- use64BitDirent ? DIRENTSIZE(n_slen) : IRIX5_DIRENTSIZE(n_slen);
- if (dirsiz >= (auio->afsio_resid - len)) {
-#else
- if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
-#endif /* AFS_SGI53_ENV */
- /* No can do no more now; ya know... at this time */
- DRelease((struct buffer *)nde, 0); /* can't use this one. */
- if (len) {
-#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
- sdirEntry->d_off = origOffset;
-#endif
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (DIRSIZ_LEN(o_slen) < rlen) {
- while (DIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - DIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else /* AFS_HPUX_ENV */
- code =
- afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
-#endif /* AFS_HPUX_ENV */
- /* this next line used to be AFSVFS40 or AIX 3.1, but is
- * really generic */
- auio->afsio_offset = origOffset;
- auio->afsio_resid = 0;
- } else { /* trouble, can't give anything to the user! */
- /* even though he has given us a buffer,
- * even though we have something to give us,
- * Looks like we lost something somewhere.
- */
- code = EINVAL;
- }
- if (ode)
- DRelease((struct buffer *)ode, 0);
- goto dirend;
- }
-
- /*
- * In any event, we move out the LAST de entry, getting ready
- * to set up for the next one.
- */
- if (len) {
-#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = len;
- sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
- sdirEntry->d_off = origOffset;
-#endif
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (DIRSIZ_LEN(o_slen) < rlen) {
- while (DIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - DIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else /* AFS_HPUX_ENV */
- code = afs_readdir_move(ode, avc, auio, o_slen, len, origOffset);
-#endif /* AFS_HPUX_ENV */
- }
-#ifdef AFS_SGI53_ENV
- len = use64BitDirent ? DIRENTSIZE(o_slen =
- n_slen) : IRIX5_DIRENTSIZE(o_slen =
- n_slen);
-#else
- len = DIRSIZ_LEN(o_slen = n_slen);
-#endif /* AFS_SGI53_ENV */
- if (ode)
- DRelease((struct buffer *)ode, 0);
- ode = nde;
- auio->afsio_offset =
- (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5);
- }
- if (ode)
- DRelease((struct buffer *)ode, 0);
-
- dirend:
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
-
- done:
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 28);
- return code;
-}
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-#ifdef AFS_OSF_ENV
-afs1_readdir(avc, auio, acred, eofp)
- int *eofp;
-#else
-afs1_readdir(avc, auio, acred)
-#endif
- struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- struct vrequest treq;
- register struct dcache *tdc;
- afs_size_t origOffset, len;
- int code = 0;
- struct DirEntry *ode = 0, *nde = 0;
- int o_slen = 0, n_slen = 0;
- afs_uint32 us;
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- /*
- * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
- * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
- * translator side XXX
- */
- struct minnfs_direct *sdirEntry = (struct minnfs_direct *)
- osi_AllocSmallSpace(sizeof(struct min_direct));
- afs_int32 rlen;
-#endif
- struct afs_fakestat_state fakestate;
-
- AFS_STATCNT(afs_readdir);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
- if (eofp)
- *eofp = 0;
-#endif
- if (code = afs_InitReq(&treq, acred)) {
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- return code;
- }
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- afs_PutFakeStat(&fakestate);
- return code;
- }
- /* update the cache entry */
- tagain:
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto done;
- /* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &len, 1);
- if (!tdc) {
- code = ENOENT;
- goto done;
- }
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((avc->states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- len = 0;
-#ifdef AFS_HPUX_ENV
- auio->uio_fpflags = 0;
-#endif
- while (code == 0) {
- origOffset = auio->afsio_offset;
-
- /* scan for the next interesting entry scan for in-use blob otherwise up point at
- * this blob note that ode, if non-zero, also represents a held dir page */
- if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f.inode, us))) {
- /* failed to setup nde, return what we've got, and release ode */
- if (len) {
- /* something to hand over. */
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0) {
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- }
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code =
- afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
-#endif /* AFS_HPUX_ENV */
- auio->afsio_resid = 0;
- } else {
- /* nothin to hand over */
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
- if (eofp)
- *eofp = 1;
-#endif
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
- /* by here nde is set */
-
- /* Do we have enough user space to carry out our mission? */
-#if defined(AFS_SGI_ENV)
- n_slen = strlen(nde->name) + 1; /* NULL terminate */
-#else
- n_slen = strlen(nde->name);
-#endif
- if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
- /* No can do no more now; ya know... at this time */
- DRelease(nde, 0); /* can't use this one. */
- if (len) {
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code =
- afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
-#endif /* AFS_HPUX_ENV */
- /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
- auio->afsio_offset = origOffset;
- auio->afsio_resid = 0;
- } else { /* trouble, can't give anything to the user! */
- /* even though he has given us a buffer,
- * even though we have something to give us,
- * Looks like we lost something somewhere.
- */
- code = EINVAL;
- }
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
-
- /*
- * In any event, we move out the LAST de entry, getting ready
- * to set up for the next one.
- */
- if (len) {
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = len;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code = afs_readdir_move(ode, avc, auio, o_slen, len, origOffset);
-#endif /* AFS_HPUX_ENV */
- }
- len = NDIRSIZ_LEN(o_slen = n_slen);
- if (ode)
- DRelease(ode, 0);
- ode = nde;
- auio->afsio_offset = ((us + afs_dir_NameBlobs(nde->name)) << 5);
- }
- if (ode)
- DRelease(ode, 0);
-
- dirend:
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
-
- done:
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 29);
- return code;
-}
-
-#endif
-#endif /* !AFS_LINUX20_ENV */
+++ /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
- */
-
-/*
- * Implements:
- * afs_Wire (DUX)
- * FetchWholeEnchilada
- * afs_IsWired (DUX)
- * afsremove
- * afs_remove
- *
- * Local:
- * newname
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_remove.c,v 1.28 2004/04/05 06:26:17 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-extern afs_rwlock_t afs_xvcache;
-extern afs_rwlock_t afs_xcbhash;
-
-
-#ifdef AFS_OSF_ENV
-/*
- * Wire down file in cache: prefetch all data, and turn on CWired flag
- * so that callbacks/callback expirations are (temporarily) ignored
- * and cache file(s) are kept in cache. File will be unwired when
- * afs_inactive is called (ie no one has VN_HOLD on vnode), or when
- * afs_IsWired notices that the file is no longer Active.
- */
-afs_Wire(avc, areq)
-#else /* AFS_OSF_ENV */
-static void
-FetchWholeEnchilada(avc, areq)
-#endif
- struct vrequest *areq;
- register struct vcache *avc;
-{
- register afs_int32 nextChunk;
- register struct dcache *tdc;
- afs_size_t pos, offset, len;
-
- AFS_STATCNT(FetchWholeEnchilada);
- if ((avc->states & CStatd) == 0)
- return; /* don't know size */
- for (nextChunk = 0; nextChunk < 1024; nextChunk++) { /* sanity check on N chunks */
- pos = AFS_CHUNKTOBASE(nextChunk);
-#if defined(AFS_OSF_ENV)
- if (pos >= avc->m.Length)
- break; /* all done */
-#else /* AFS_OSF_ENV */
- if (pos >= avc->m.Length)
- return; /* all done */
-#endif
- tdc = afs_GetDCache(avc, pos, areq, &offset, &len, 0);
- if (!tdc)
-#if defined(AFS_OSF_ENV)
- break;
-#else /* AFS_OSF_ENV */
- return;
-#endif
- afs_PutDCache(tdc);
- }
-#if defined(AFS_OSF_ENV)
- avc->states |= CWired;
-#endif /* AFS_OSF_ENV */
-}
-
-#if defined(AFS_OSF_ENV)
-/*
- * Tests whether file is wired down, after unwiring the file if it
- * is found to be inactive (ie not open and not being paged from).
- */
-afs_IsWired(avc)
- register struct vcache *avc;
-{
- if (avc->states & CWired) {
- if (osi_Active(avc)) {
- return 1;
- }
- avc->states &= ~CWired;
- }
- return 0;
-}
-#endif /* AFS_OSF_ENV */
-
-int
-afsremove(register struct vcache *adp, register struct dcache *tdc,
- register struct vcache *tvc, char *aname, struct AFS_UCRED *acred,
- struct vrequest *treqp)
-{
- register afs_int32 code;
- register struct conn *tc;
- struct AFSFetchStatus OutDirStatus;
- struct AFSVolSync tsync;
- XSTATS_DECLS
- do {
- tc = afs_Conn(&adp->fid, treqp, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_RemoveFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
- aname, &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, treqp, AFS_STATS_FS_RPCIDX_REMOVEFILE,
- SHARED_LOCK, NULL));
-
- osi_dnlc_remove(adp, aname, tvc);
- if (tvc)
- afs_symhint_inval(tvc); /* XXX: don't really need to be so extreme */
-
- if (code) {
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- if (tvc)
- afs_PutVCache(tvc);
-
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 497);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- code = afs_CheckCode(code, treqp, 21);
- return code;
- }
- if (tdc)
- UpgradeSToWLock(&tdc->lock, 637);
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Delete(&tdc->f.inode, aname);
- if (code) {
- ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc); /* drop ref count */
- }
- ReleaseWriteLock(&adp->lock);
-
- /* now, get vnode for unlinked dude, and see if we should force it
- * from cache. adp is now the deleted files vnode. Note that we
- * call FindVCache instead of GetVCache since if the file's really
- * gone, we won't be able to fetch the status info anyway. */
- if (tvc) {
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc);
- /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
- ObtainWriteLock(&tvc->lock, 141);
- /* note that callback will be broken on the deleted file if there are
- * still >0 links left to it, so we'll get the stat right */
- tvc->m.LinkCount--;
- tvc->states &= ~CUnique; /* For the dfs xlator */
- if (tvc->m.LinkCount == 0 && !osi_Active(tvc)) {
- if (!AFS_NFSXLATORREQ(acred))
- afs_TryToSmush(tvc, acred, 0);
- }
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- afs_PutVCache(tvc);
- }
- return (0);
-}
-
-static char *
-newname(void)
-{
- char *name, *sp, *p = ".__afs";
- afs_int32 rd = afs_random() & 0xffff;
-
- sp = name = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- while (*p != '\0')
- *sp++ = *p++;
- while (rd) {
- *sp++ = "0123456789ABCDEF"[rd & 0x0f];
- rd >>= 4;
- }
- *sp = '\0';
- return (name);
-}
-
-/* these variables appear to exist for debugging purposes */
-struct vcache *Tadp1, *Ttvc;
-int Tadpr, Ttvcr;
-char *Tnam;
-char *Tnam1;
-
-/* Note that we don't set CDirty here, this is OK because the unlink
- * RPC is called synchronously */
-int
-#ifdef AFS_OSF_ENV
-afs_remove(ndp)
- struct nameidata *ndp;
-{
- register struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
-afs_remove(OSI_VC_ARG(adp), aname, acred)
-OSI_VC_DECL(adp);
- char *aname;
- struct AFS_UCRED *acred;
-{
-#endif
- struct vrequest treq;
- register struct dcache *tdc;
- struct VenusFid unlinkFid;
- register afs_int32 code;
- register struct vcache *tvc;
- afs_size_t offset, len;
- struct afs_fakestat_state fakestate;
- OSI_VC_CONVERT(adp)
-
- AFS_STATCNT(afs_remove);
- afs_Trace2(afs_iclSetp, CM_TRACE_REMOVE, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, aname);
-
-#ifdef AFS_OSF_ENV
- tvc = (struct vcache *)ndp->ni_vp; /* should never be null */
-#endif
-
- if ((code = afs_InitReq(&treq, acred))) {
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- return code;
- }
-
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- return code;
- }
-
- /* Check if this is dynroot */
- if (afs_IsDynroot(adp)) {
- code = afs_DynrootVOPRemove(adp, acred, aname);
- afs_PutFakeStat(&fakestate);
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- return code;
- }
-
-#if 0
- if (adp->mvstat == 2) {
- afs_PutFakeStat(&fakestate);
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- return EISDIR;
- }
-#endif
-
- if (strlen(aname) > AFSNAMEMAX) {
- afs_PutFakeStat(&fakestate);
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- return ENAMETOOLONG;
- }
- tagain:
- code = afs_VerifyVCache(adp, &treq);
-#ifdef AFS_OSF_ENV
- tvc = VTOAFS(ndp->ni_vp); /* should never be null */
- if (code) {
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
- afs_PutFakeStat(&fakestate);
- return afs_CheckCode(code, &treq, 22);
- }
-#else /* AFS_OSF_ENV */
- tvc = NULL;
- if (code) {
- code = afs_CheckCode(code, &treq, 23);
- afs_PutFakeStat(&fakestate);
- return code;
- }
-#endif
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
- afs_PutVCache(tvc);
-#endif
- code = EROFS;
- afs_PutFakeStat(&fakestate);
- return code;
- }
-
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
- ObtainWriteLock(&adp->lock, 142);
- if (tdc)
- ObtainSharedLock(&tdc->lock, 638);
-
- /*
- * Make sure that the data in the cache is current. We may have
- * received a callback while we were waiting for the write lock.
- */
- if (!(adp->states & CStatd)
- || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
- ReleaseWriteLock(&adp->lock);
- if (tdc) {
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- goto tagain;
- }
-
- unlinkFid.Fid.Vnode = 0;
- if (!tvc) {
- tvc = osi_dnlc_lookup(adp, aname, WRITE_LOCK);
- }
- /* This should not be necessary since afs_lookup() has already
- * done the work */
- if (!tvc)
- if (tdc) {
- code = afs_dir_Lookup(&tdc->f.inode, aname, &unlinkFid.Fid);
- if (code == 0) {
- afs_int32 cached = 0;
-
- unlinkFid.Cell = adp->fid.Cell;
- unlinkFid.Fid.Volume = adp->fid.Fid.Volume;
- if (unlinkFid.Fid.Unique == 0) {
- tvc =
- afs_LookupVCache(&unlinkFid, &treq, &cached, adp,
- aname);
- } else {
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&unlinkFid, 0, DO_STATS);
- ReleaseReadLock(&afs_xvcache);
- }
- }
- }
-
- if (tvc && osi_Active(tvc)) {
- /* about to delete whole file, prefetch it first */
- ReleaseWriteLock(&adp->lock);
- ObtainWriteLock(&tvc->lock, 143);
-#if defined(AFS_OSF_ENV)
- afs_Wire(tvc, &treq);
-#else /* AFS_OSF_ENV */
- FetchWholeEnchilada(tvc, &treq);
-#endif
- ReleaseWriteLock(&tvc->lock);
- ObtainWriteLock(&adp->lock, 144);
- }
-
- osi_dnlc_remove(adp, aname, tvc);
- if (tvc)
- afs_symhint_inval(tvc);
-
- Tadp1 = adp;
- Tadpr = VREFCOUNT(adp);
- Ttvc = tvc;
- Tnam = aname;
- Tnam1 = 0;
- if (tvc)
- Ttvcr = VREFCOUNT(tvc);
-#ifdef AFS_AIX_ENV
- if (tvc && (VREFCOUNT(tvc) > 2) && tvc->opens > 0
- && !(tvc->states & CUnlinked)) {
-#else
- if (tvc && (VREFCOUNT(tvc) > 1) && tvc->opens > 0
- && !(tvc->states & CUnlinked)) {
-#endif
- char *unlname = newname();
-
- ReleaseWriteLock(&adp->lock);
- if (tdc)
- ReleaseSharedLock(&tdc->lock);
- code = afsrename(adp, aname, adp, unlname, acred, &treq);
- Tnam1 = unlname;
- if (!code) {
- tvc->mvid = (struct VenusFid *)unlname;
- crhold(acred);
- if (tvc->uncred) {
- crfree(tvc->uncred);
- }
- tvc->uncred = acred;
- tvc->states |= CUnlinked;
- } else {
- osi_FreeSmallSpace(unlname);
- }
- if (tdc)
- afs_PutDCache(tdc);
- afs_PutVCache(tvc);
- } else {
- code = afsremove(adp, tdc, tvc, aname, acred, &treq);
- }
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp);
-#endif /* AFS_OSF_ENV */
- afs_PutFakeStat(&fakestate);
- return code;
-}
-
-
-/* afs_remunlink -- This tries to delete the file at the server after it has
- * been renamed when unlinked locally but now has been finally released.
- *
- * CAUTION -- may be called with avc unheld. */
-
-int
-afs_remunlink(register struct vcache *avc, register int doit)
-{
- struct AFS_UCRED *cred;
- char *unlname;
- struct vcache *adp;
- struct vrequest treq;
- struct VenusFid dirFid;
- register struct dcache *tdc;
- afs_int32 code = 0;
-
- if (NBObtainWriteLock(&avc->lock, 423))
- return 0;
-
- if (avc->mvid && (doit || (avc->states & CUnlinkedDel))) {
- if ((code = afs_InitReq(&treq, avc->uncred))) {
- ReleaseWriteLock(&avc->lock);
- } else {
- /* Must bump the refCount because GetVCache may block.
- * Also clear mvid so no other thread comes here if we block.
- */
- unlname = (char *)avc->mvid;
- avc->mvid = NULL;
- cred = avc->uncred;
- avc->uncred = NULL;
-
-#ifdef AFS_DARWIN_ENV
- /* this is called by vrele (via VOP_INACTIVE) when the refcount
- * is 0. we can't just call VN_HOLD since vref will panic.
- * we can't just call osi_vnhold because a later AFS_RELE will call
- * vrele again, which will try to call VOP_INACTIVE again after
- * vn_locking the vnode. which would be fine except that our vrele
- * caller also locked the vnode... So instead, we just gimmick the
- * refcounts and hope nobody else can touch the file now */
- osi_Assert(VREFCOUNT(avc) == 0);
- VREFCOUNT_SET(avc, 1);
-#endif
- VN_HOLD(AFSTOV(avc));
-
- /* We'll only try this once. If it fails, just release the vnode.
- * Clear after doing hold so that NewVCache doesn't find us yet.
- */
- avc->states &= ~(CUnlinked | CUnlinkedDel);
-
- ReleaseWriteLock(&avc->lock);
-
- dirFid.Cell = avc->fid.Cell;
- dirFid.Fid.Volume = avc->fid.Fid.Volume;
- dirFid.Fid.Vnode = avc->parentVnode;
- dirFid.Fid.Unique = avc->parentUnique;
- adp = afs_GetVCache(&dirFid, &treq, NULL, NULL);
-
- if (adp) {
- tdc = afs_FindDCache(adp, (afs_size_t) 0);
- ObtainWriteLock(&adp->lock, 159);
- if (tdc)
- ObtainSharedLock(&tdc->lock, 639);
-
- /* afsremove releases the adp & tdc locks, and does vn_rele(avc) */
- code = afsremove(adp, tdc, avc, unlname, cred, &treq);
- afs_PutVCache(adp);
- } else {
- /* we failed - and won't be back to try again. */
- afs_PutVCache(avc);
- }
- osi_FreeSmallSpace(unlname);
- crfree(cred);
-#ifdef AFS_DARWIN_ENV
- osi_Assert(VREFCOUNT(avc) == 1);
- VREFCOUNT_SET(avc, 0);
-#endif
- }
- } else {
- ReleaseWriteLock(&avc->lock);
- }
-
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afsrename
- * afs_rename
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_rename.c,v 1.16 2003/08/29 22:00:04 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-extern afs_rwlock_t afs_xcbhash;
-
-/* Note that we don't set CDirty here, this is OK because the rename
- * RPC is called synchronously. */
-
-int
-afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
- char *aname2, struct AFS_UCRED *acred, struct vrequest *areq)
-{
- register struct conn *tc;
- register afs_int32 code;
- afs_int32 returnCode;
- int oneDir, doLocally;
- afs_size_t offset, len;
- struct VenusFid unlinkFid, fileFid;
- struct vcache *tvc;
- struct dcache *tdc1, *tdc2;
- struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus;
- struct AFSVolSync tsync;
- XSTATS_DECLS AFS_STATCNT(afs_rename);
- afs_Trace4(afs_iclSetp, CM_TRACE_RENAME, ICL_TYPE_POINTER, aodp,
- ICL_TYPE_STRING, aname1, ICL_TYPE_POINTER, andp,
- ICL_TYPE_STRING, aname2);
-
- if (strlen(aname1) > AFSNAMEMAX || strlen(aname2) > AFSNAMEMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
-
- /* verify the latest versions of the stat cache entries */
- tagain:
- code = afs_VerifyVCache(aodp, areq);
- if (code)
- goto done;
- code = afs_VerifyVCache(andp, areq);
- if (code)
- goto done;
-
- /* lock in appropriate order, after some checks */
- if (aodp->fid.Cell != andp->fid.Cell
- || aodp->fid.Fid.Volume != andp->fid.Fid.Volume) {
- code = EXDEV;
- goto done;
- }
- oneDir = 0;
- code = 0;
- if (andp->fid.Fid.Vnode == aodp->fid.Fid.Vnode) {
- if (!strcmp(aname1, aname2)) {
- /* Same directory and same name; this is a noop and just return success
- * to save cycles and follow posix standards */
-
- code = 0;
- goto done;
- }
- ObtainWriteLock(&andp->lock, 147);
- tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
- if (!tdc1) {
- code = ENOENT;
- } else {
- ObtainWriteLock(&tdc1->lock, 643);
- }
- tdc2 = tdc1;
- oneDir = 1; /* only one dude locked */
- } else if ((andp->states & CRO) || (aodp->states & CRO)) {
- code = EROFS;
- goto done;
- } else if (andp->fid.Fid.Vnode < aodp->fid.Fid.Vnode) {
- ObtainWriteLock(&andp->lock, 148); /* lock smaller one first */
- ObtainWriteLock(&aodp->lock, 149);
- tdc2 = afs_FindDCache(andp, (afs_size_t) 0);
- if (tdc2)
- ObtainWriteLock(&tdc2->lock, 644);
- tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
- if (tdc1)
- ObtainWriteLock(&tdc1->lock, 645);
- else
- code = ENOENT;
- } else {
- ObtainWriteLock(&aodp->lock, 150); /* lock smaller one first */
- ObtainWriteLock(&andp->lock, 557);
- tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
- if (tdc1)
- ObtainWriteLock(&tdc1->lock, 646);
- else
- code = ENOENT;
- tdc2 = afs_FindDCache(andp, (afs_size_t) 0);
- if (tdc2)
- ObtainWriteLock(&tdc2->lock, 647);
- }
-
- osi_dnlc_remove(aodp, aname1, 0);
- osi_dnlc_remove(andp, aname2, 0);
- afs_symhint_inval(aodp);
- afs_symhint_inval(andp);
-
- /*
- * Make sure that the data in the cache is current. We may have
- * received a callback while we were waiting for the write lock.
- */
- if (tdc1) {
- if (!(aodp->states & CStatd)
- || !hsame(aodp->m.DataVersion, tdc1->f.versionNo)) {
-
- ReleaseWriteLock(&aodp->lock);
- if (!oneDir) {
- if (tdc2) {
- ReleaseWriteLock(&tdc2->lock);
- afs_PutDCache(tdc2);
- }
- ReleaseWriteLock(&andp->lock);
- }
- ReleaseWriteLock(&tdc1->lock);
- afs_PutDCache(tdc1);
- goto tagain;
- }
- }
-
- if (code == 0)
- code = afs_dir_Lookup(&tdc1->f.inode, aname1, &fileFid.Fid);
- if (code) {
- if (tdc1) {
- ReleaseWriteLock(&tdc1->lock);
- afs_PutDCache(tdc1);
- }
- ReleaseWriteLock(&aodp->lock);
- if (!oneDir) {
- if (tdc2) {
- ReleaseWriteLock(&tdc2->lock);
- afs_PutDCache(tdc2);
- }
- ReleaseWriteLock(&andp->lock);
- }
- goto done;
- }
-
- /* locks are now set, proceed to do the real work */
- do {
- tc = afs_Conn(&aodp->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_Rename(tc->id, (struct AFSFid *)&aodp->fid.Fid, aname1,
- (struct AFSFid *)&andp->fid.Fid, aname2,
- &OutOldDirStatus, &OutNewDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
-
- } while (afs_Analyze
- (tc, code, &andp->fid, areq, AFS_STATS_FS_RPCIDX_RENAME,
- SHARED_LOCK, NULL));
-
- returnCode = code; /* remember for later */
-
- /* Now we try to do things locally. This is really loathsome code. */
- unlinkFid.Fid.Vnode = 0;
- if (code == 0) {
- /* In any event, we don't really care if the data (tdc2) is not
- * in the cache; if it isn't, we won't do the update locally. */
- /* see if version numbers increased properly */
- doLocally = 1;
- if (oneDir) {
- /* number increases by 1 for whole rename operation */
- if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1)) {
- doLocally = 0;
- }
- } else {
- /* two separate dirs, each increasing by 1 */
- if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1))
- doLocally = 0;
- if (!afs_LocalHero(andp, tdc2, &OutNewDirStatus, 1))
- doLocally = 0;
- if (!doLocally) {
- if (tdc1) {
- ZapDCE(tdc1);
- DZap(&tdc1->f.inode);
- }
- if (tdc2) {
- ZapDCE(tdc2);
- DZap(&tdc2->f.inode);
- }
- }
- }
- /* now really do the work */
- if (doLocally) {
- /* first lookup the fid of the dude we're moving */
- code = afs_dir_Lookup(&tdc1->f.inode, aname1, &fileFid.Fid);
- if (code == 0) {
- /* delete the source */
- code = afs_dir_Delete(&tdc1->f.inode, aname1);
- }
- /* first see if target is there */
- if (code == 0
- && afs_dir_Lookup(&tdc2->f.inode, aname2,
- &unlinkFid.Fid) == 0) {
- /* target already exists, and will be unlinked by server */
- code = afs_dir_Delete(&tdc2->f.inode, aname2);
- }
- if (code == 0) {
- code = afs_dir_Create(&tdc2->f.inode, aname2, &fileFid.Fid);
- }
- if (code != 0) {
- ZapDCE(tdc1);
- DZap(&tdc1->f.inode);
- if (!oneDir) {
- ZapDCE(tdc2);
- DZap(&tdc2->f.inode);
- }
- }
- }
-
- /* update dir link counts */
- aodp->m.LinkCount = OutOldDirStatus.LinkCount;
- if (!oneDir)
- andp->m.LinkCount = OutNewDirStatus.LinkCount;
-
- } else { /* operation failed (code != 0) */
- if (code < 0) {
- /* if failed, server might have done something anyway, and
- * assume that we know about it */
- ObtainWriteLock(&afs_xcbhash, 498);
- afs_DequeueCallback(aodp);
- afs_DequeueCallback(andp);
- andp->states &= ~CStatd;
- aodp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(andp);
- osi_dnlc_purgedp(aodp);
- }
- }
-
- /* release locks */
- if (tdc1) {
- ReleaseWriteLock(&tdc1->lock);
- afs_PutDCache(tdc1);
- }
-
- if ((!oneDir) && tdc2) {
- ReleaseWriteLock(&tdc2->lock);
- afs_PutDCache(tdc2);
- }
-
- ReleaseWriteLock(&aodp->lock);
- if (!oneDir)
- ReleaseWriteLock(&andp->lock);
-
- if (returnCode) {
- code = returnCode;
- goto done;
- }
-
- /* now, some more details. if unlinkFid.Fid.Vnode then we should decrement
- * the link count on this file. Note that if fileFid is a dir, then we don't
- * have to invalidate its ".." entry, since its DataVersion # should have
- * changed. However, interface is not good enough to tell us the
- * *file*'s new DataVersion, so we're stuck. Our hack: delete mark
- * the data as having an "unknown" version (effectively discarding the ".."
- * entry */
- if (unlinkFid.Fid.Vnode) {
- unlinkFid.Fid.Volume = aodp->fid.Fid.Volume;
- unlinkFid.Cell = aodp->fid.Cell;
- tvc = NULL;
- if (!unlinkFid.Fid.Unique) {
- tvc = afs_LookupVCache(&unlinkFid, areq, NULL, aodp, aname1);
- }
- if (!tvc) /* lookup failed or wasn't called */
- tvc = afs_GetVCache(&unlinkFid, areq, NULL, NULL);
-
- if (tvc) {
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
- ObtainWriteLock(&tvc->lock, 151);
- tvc->m.LinkCount--;
- tvc->states &= ~CUnique; /* For the dfs xlator */
- if (tvc->m.LinkCount == 0 && !osi_Active(tvc)) {
- /* if this was last guy (probably) discard from cache.
- * We have to be careful to not get rid of the stat
- * information, since otherwise operations will start
- * failing even if the file was still open (or
- * otherwise active), and the server no longer has the
- * info. If the file still has valid links, we'll get
- * a break-callback msg from the server, so it doesn't
- * matter that we don't discard the status info */
- if (!AFS_NFSXLATORREQ(acred))
- afs_TryToSmush(tvc, acred, 0);
- }
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- afs_PutVCache(tvc);
- }
- }
-
- /* now handle ".." invalidation */
- if (!oneDir) {
- fileFid.Fid.Volume = aodp->fid.Fid.Volume;
- fileFid.Cell = aodp->fid.Cell;
- if (!fileFid.Fid.Unique)
- tvc = afs_LookupVCache(&fileFid, areq, NULL, andp, aname2);
- else
- tvc = afs_GetVCache(&fileFid, areq, NULL, (struct vcache *)0);
- if (tvc && (vType(tvc) == VDIR)) {
- ObtainWriteLock(&tvc->lock, 152);
- tdc1 = afs_FindDCache(tvc, (afs_size_t) 0);
- if (tdc1) {
- ObtainWriteLock(&tdc1->lock, 648);
- ZapDCE(tdc1); /* mark as unknown */
- DZap(&tdc1->f.inode);
- ReleaseWriteLock(&tdc1->lock);
- afs_PutDCache(tdc1); /* put it back */
- }
- osi_dnlc_remove(tvc, "..", 0);
- ReleaseWriteLock(&tvc->lock);
- afs_PutVCache(tvc);
- } else if (tvc) {
- /* True we shouldn't come here since tvc SHOULD be a dir, but we
- * 'syntactically' need to unless we change the 'if' above...
- */
- afs_PutVCache(tvc);
- }
- }
- code = returnCode;
- done:
- return code;
-}
-
-int
-#ifdef AFS_OSF_ENV
-afs_rename(fndp, tndp)
- struct nameidata *fndp, *tndp;
-{
- struct vcache *aodp = VTOAFS(fndp->ni_dvp);
- char *aname1 = fndp->ni_dent.d_name;
- struct vcache *andp = VTOAFS(tndp->ni_dvp);
- char *aname2 = tndp->ni_dent.d_name;
- struct ucred *acred = tndp->ni_cred;
-#else /* AFS_OSF_ENV */
-#if defined(AFS_SGI_ENV)
-afs_rename(OSI_VC_ARG(aodp), aname1, andp, aname2, npnp, acred)
- struct pathname *npnp;
-#else
-afs_rename(OSI_VC_ARG(aodp), aname1, andp, aname2, acred)
-#endif
- OSI_VC_DECL(aodp);
- struct vcache *andp;
- char *aname1, *aname2;
- struct AFS_UCRED *acred;
-{
-#endif
- register afs_int32 code;
- struct afs_fakestat_state ofakestate;
- struct afs_fakestat_state nfakestate;
- struct vrequest treq;
- OSI_VC_CONVERT(aodp)
-
- code = afs_InitReq(&treq, acred);
- if (code)
- return code;
- afs_InitFakeStat(&ofakestate);
- afs_InitFakeStat(&nfakestate);
- code = afs_EvalFakeStat(&aodp, &ofakestate, &treq);
- if (code)
- goto done;
- code = afs_EvalFakeStat(&andp, &nfakestate, &treq);
- if (code)
- goto done;
- code = afsrename(aodp, aname1, andp, aname2, acred, &treq);
- done:
- afs_PutFakeStat(&ofakestate);
- afs_PutFakeStat(&nfakestate);
-#ifdef AFS_OSF_ENV
- AFS_RELE(tndp->ni_dvp);
- if (tndp->ni_vp != NULL) {
- AFS_RELE(tndp->ni_vp);
- }
- AFS_RELE(fndp->ni_dvp);
- AFS_RELE(fndp->ni_vp);
-#endif /* AFS_OSF_ENV */
- code = afs_CheckCode(code, &treq, 25);
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_ustrategy
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_strategy.c,v 1.18 2003/08/29 22:00:04 rees Exp $");
-
-#if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-
-int
-#if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_ustrategy(abp, credp)
- struct AFS_UCRED *credp;
-#else
-afs_ustrategy(abp)
-#endif
- register struct buf *abp;
-{
- register afs_int32 code;
- struct uio tuio;
- register struct vcache *tvc = VTOAFS(abp->b_vp);
- register afs_int32 len = abp->b_bcount;
-#if !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#ifdef AFS_AIX41_ENV
- struct ucred *credp;
-#else
- struct AFS_UCRED *credp = u.u_cred;
-#endif
-#endif
- struct iovec tiovec[1];
-
- AFS_STATCNT(afs_ustrategy);
-#ifdef AFS_AIX41_ENV
- /*
- * So that it won't change while reading it
- */
- ObtainReadLock(&tvc->lock);
- if (tvc->credp) {
- credp = tvc->credp;
- crhold(credp);
- } else {
- credp = crref();
- }
- ReleaseReadLock(&tvc->lock);
- osi_Assert(credp);
-#endif
-#ifdef AFS_FBSD50_ENV
- if (abp->b_iocmd == BIO_READ) {
-#else
- if ((abp->b_flags & B_READ) == B_READ) {
-#endif
- /* read b_bcount bytes into kernel address b_un.b_addr starting
- * at byte DEV_BSIZE * b_blkno. Bzero anything we can't read,
- * and finally call iodone(abp). File is in abp->b_vp. Credentials
- * are from u area??
- */
- tuio.afsio_iov = tiovec;
- tuio.afsio_iovcnt = 1;
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
-#ifdef AFS_64BIT_CLIENT
- tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
-#else /* AFS_64BIT_CLIENT */
- tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
-#if defined(AFS_SUN5_ENV)
- tuio._uio_offset._p._u = 0;
-#endif
-#endif /* AFS_64BIT_CLIENT */
-#else
- tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
-#endif
- tuio.afsio_seg = AFS_UIOSYS;
-#ifdef AFS_UIOFMODE
- tuio.afsio_fmode = 0;
-#endif
- tuio.afsio_resid = abp->b_bcount;
-#if defined(AFS_XBSD_ENV)
- tiovec[0].iov_base = abp->b_saveaddr;
-#else
- tiovec[0].iov_base = abp->b_un.b_addr;
-#endif /* AFS_XBSD_ENV */
- tiovec[0].iov_len = abp->b_bcount;
- /* are user's credentials valid here? probably, but this
- * sure seems like the wrong things to do. */
-#if defined(AFS_SUN5_ENV)
- code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
-#else
- code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
-#endif
- if (code == 0) {
- if (tuio.afsio_resid > 0)
-#if defined(AFS_XBSD_ENV)
- memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0,
- tuio.afsio_resid);
-#else
- memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0,
- tuio.afsio_resid);
-#endif /* AFS_XBSD_ENV */
-#ifdef AFS_AIX32_ENV
- /*
- * If we read a block that is past EOF and the user was not storing
- * to it, go ahead and write protect the page. This way we will detect
- * storing beyond EOF in the future
- */
- if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
- if ((abp->b_flags & B_PFSTORE) == 0) {
- AFS_GUNLOCK();
- vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE,
- abp->b_bcount / PAGESIZE, RDONLY);
- AFS_GLOCK();
- }
- }
-#endif
- }
- } else {
- tuio.afsio_iov = tiovec;
- tuio.afsio_iovcnt = 1;
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
-#ifdef AFS_64BIT_CLIENT
- tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
-#else /* AFS_64BIT_CLIENT */
- tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
-#ifdef AFS_SUN5_ENV
- tuio._uio_offset._p._u = 0;
-#endif
-#endif /* AFS_64BIT_CLIENT */
-#ifdef AFS_SUN5_ENV
-#ifdef AFS_SUN59_ENV
- tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
-#else
- tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
-#endif
-#endif
-#else
- tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
-#endif
- tuio.afsio_seg = AFS_UIOSYS;
-#ifdef AFS_UIOFMODE
- tuio.afsio_fmode = 0;
-#endif
-#ifdef AFS_AIX32_ENV
- /*
- * XXX It this really right? Ideally we should always write block size multiple
- * and not any arbitrary size, right? XXX
- */
- len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
-#endif
-#ifdef AFS_ALPHA_ENV
- len =
- MIN(abp->b_bcount,
- (VTOAFS(abp->b_vp))->m.Length - dbtob(abp->b_blkno));
-#endif /* AFS_ALPHA_ENV */
- tuio.afsio_resid = len;
-#if defined(AFS_XBSD_ENV)
- tiovec[0].iov_base = abp->b_saveaddr;
-#else
- tiovec[0].iov_base = abp->b_un.b_addr;
-#endif /* AFS_XBSD_ENV */
- tiovec[0].iov_len = len;
- /* are user's credentials valid here? probably, but this
- * sure seems like the wrong things to do. */
-#if defined(AFS_SUN5_ENV)
- code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
-#else
- code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
-#endif
- }
-#if !defined(AFS_AIX32_ENV) && !defined(AFS_SUN5_ENV)
-#if defined(AFS_DUX40_ENV) || (defined (AFS_XBSD_ENV) && !defined (AFS_FBSD50_ENV))
- if (code) {
- abp->b_error = code;
- abp->b_flags |= B_ERROR;
- }
- biodone(abp);
-#if defined(AFS_DUX40_ENV)
- if (code && !(abp->b_flags & B_READ)) {
- /* prevent ubc from retrying writes */
- AFS_GUNLOCK();
- ubc_invalidate(AFSTOV(tvc)->v_object,
- (vm_offset_t) dbtob(abp->b_blkno), PAGE_SIZE, B_INVAL);
- AFS_GLOCK();
- }
-#endif
-#elif defined(AFS_FBSD50_ENV)
- biodone(&abp->b_io);
-#else /* AFS_DUX40_ENV */
- iodone(abp);
-#endif /* AFS_DUX40_ENV */
-#endif
-#ifdef AFS_AIX32_ENV
- crfree(credp);
-#endif
- afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid);
- return code;
-}
-
-#endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */
+++ /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
- */
-
-/*
- * afs_vnop_symlink.c - symlink and readlink vnodeops.
- *
- * Implements:
- * afs_symlink
- * afs_MemHandleLink
- * afs_UFSHandleLink
- * afs_readlink
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_symlink.c,v 1.19 2003/08/26 15:09:28 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-extern afs_rwlock_t afs_xvcache;
-extern afs_rwlock_t afs_xcbhash;
-
-/* Note: There is the bare bones beginning of symlink hints in the now
- * defunct afs/afs_lookup.c file. Since they are not in use, making the call
- * is just a performance hit.
- */
-
-
-/* don't set CDirty in here because RPC is called synchronously */
-int
-afs_symlink
-#ifdef AFS_OSF_ENV
- (ndp, attrs, atargetName)
- struct nameidata *ndp;
- struct vattr *attrs;
- register char *atargetName;
-{
- register struct vcache *adp = VTOAFS(ndp->ni_dvp);
- char *aname = ndp->ni_dent.d_name;
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
- (OSI_VC_ARG(adp), aname, attrs, atargetName, acred)
- OSI_VC_DECL(adp);
- char *atargetName;
- char *aname;
- struct vattr *attrs;
- struct AFS_UCRED *acred;
-{
-#endif
- afs_uint32 now = 0;
- struct vrequest treq;
- afs_int32 code;
- struct conn *tc;
- struct VenusFid newFid;
- struct dcache *tdc;
- afs_size_t offset, len;
- afs_int32 alen;
- struct server *hostp = 0;
- struct vcache *tvc;
- struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- struct volume *volp = 0;
- struct afs_fakestat_state fakestate;
- XSTATS_DECLS OSI_VC_CONVERT(adp)
-
- AFS_STATCNT(afs_symlink);
- afs_Trace2(afs_iclSetp, CM_TRACE_SYMLINK, ICL_TYPE_POINTER, adp,
- ICL_TYPE_STRING, aname);
-
- if ((code = afs_InitReq(&treq, acred)))
- goto done2;
-
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
- if (code)
- goto done;
-
- if (strlen(aname) > AFSNAMEMAX || strlen(atargetName) > AFSPATHMAX) {
- code = ENAMETOOLONG;
- goto done;
- }
-
- if (afs_IsDynroot(adp)) {
- code = afs_DynrootVOPSymlink(adp, acred, aname, atargetName);
- goto done;
- }
-
- code = afs_VerifyVCache(adp, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 30);
- goto done;
- }
-
- /** If the volume is read-only, return error without making an RPC to the
- * fileserver
- */
- if (adp->states & CRO) {
- code = EROFS;
- goto done;
- }
-
- InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE;
- InStatus.ClientModTime = osi_Time();
- alen = strlen(atargetName); /* we want it to include the null */
- if (*atargetName == '#' || *atargetName == '%') {
- InStatus.UnixModeBits = 0644; /* mt pt: null from "." at end */
- if (alen == 1)
- alen++; /* Empty string */
- } else {
- InStatus.UnixModeBits = 0755;
- alen++; /* add in the null */
- }
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
- volp = afs_FindVolume(&adp->fid, READ_LOCK); /*parent is also in same vol */
- ObtainWriteLock(&adp->lock, 156);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 636);
- ObtainSharedLock(&afs_xvcache, 17); /* prevent others from creating this entry */
- /* XXX Pay attention to afs_xvcache around the whole thing!! XXX */
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- hostp = tc->srvr->server;
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SYMLINK);
- if (adp->states & CForeign) {
- now = osi_Time();
- RX_AFS_GUNLOCK();
- code =
- RXAFS_DFSSymlink(tc->id, (struct AFSFid *)&adp->fid.Fid,
- aname, atargetName, &InStatus,
- (struct AFSFid *)&newFid.Fid,
- &OutFidStatus, &OutDirStatus, &CallBack,
- &tsync);
- RX_AFS_GLOCK();
- } else {
- RX_AFS_GUNLOCK();
- code =
- RXAFS_Symlink(tc->id, (struct AFSFid *)&adp->fid.Fid,
- aname, atargetName, &InStatus,
- (struct AFSFid *)&newFid.Fid, &OutFidStatus,
- &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- }
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_SYMLINK,
- SHARED_LOCK, NULL));
-
- UpgradeSToWLock(&afs_xvcache, 40);
- if (code) {
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 499);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
- }
- ReleaseWriteLock(&adp->lock);
- ReleaseWriteLock(&afs_xvcache);
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- goto done;
- }
- /* otherwise, we should see if we can make the change to the dir locally */
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
- if (code) {
- ZapDCE(tdc); /* surprise error -- use invalid value */
- DZap(&tdc->f.inode);
- }
- }
- if (tdc) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- newFid.Cell = adp->fid.Cell;
- newFid.Fid.Volume = adp->fid.Fid.Volume;
- ReleaseWriteLock(&adp->lock);
-
- /* now we're done with parent dir, create the link's entry. Note that
- * no one can get a pointer to the new cache entry until we release
- * the xvcache lock. */
- tvc = afs_NewVCache(&newFid, hostp);
- ObtainWriteLock(&tvc->lock, 157);
- ObtainWriteLock(&afs_xcbhash, 500);
- tvc->states |= CStatd; /* have valid info */
- tvc->states &= ~CBulkFetching;
-
- if (adp->states & CForeign) {
- tvc->states |= CForeign;
- /* We don't have to worry about losing the callback since we're doing it
- * under the afs_xvcache lock actually, afs_NewVCache may drop the
- * afs_xvcache lock, if it calls afs_FlushVCache */
- tvc->cbExpires = CallBack.ExpirationTime + now;
- afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
- } else {
- tvc->cbExpires = 0x7fffffff; /* never expires, they can't change */
- /* since it never expires, we don't have to queue the callback */
- }
- ReleaseWriteLock(&afs_xcbhash);
- afs_ProcessFS(tvc, &OutFidStatus, &treq);
-
- if (!tvc->linkData) {
- tvc->linkData = (char *)afs_osi_Alloc(alen);
- strncpy(tvc->linkData, atargetName, alen - 1);
- tvc->linkData[alen - 1] = 0;
- }
- ReleaseWriteLock(&tvc->lock);
- ReleaseWriteLock(&afs_xvcache);
- afs_PutVCache(tvc);
- code = 0;
- done:
- afs_PutFakeStat(&fakestate);
- if (volp)
- afs_PutVolume(volp, READ_LOCK);
- code = afs_CheckCode(code, &treq, 31);
- done2:
-#ifdef AFS_OSF_ENV
- AFS_RELE(ndp->ni_dvp);
-#endif /* AFS_OSF_ENV */
- return code;
-}
-
-int
-afs_MemHandleLink(register struct vcache *avc, struct vrequest *areq)
-{
- register struct dcache *tdc;
- register char *tp, *rbuf;
- afs_size_t offset, len;
- afs_int32 tlen, alen;
- register afs_int32 code;
-
- AFS_STATCNT(afs_MemHandleLink);
- /* two different formats, one for links protected 644, have a "." at
- * the end of the file name, which we turn into a null. Others,
- * protected 755, we add a null to the end of */
- if (!avc->linkData) {
- void *addr;
- tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 0);
- if (!tdc) {
- return EIO;
- }
- /* otherwise we have the data loaded, go for it */
- if (len > 1024) {
- afs_PutDCache(tdc);
- return EFAULT;
- }
- if (avc->m.Mode & 0111)
- alen = len + 1; /* regular link */
- else
- alen = len; /* mt point */
- rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- ObtainReadLock(&tdc->lock);
- addr = afs_MemCacheOpen(tdc->f.inode);
- tlen = len;
- code = afs_MemReadBlk(addr, 0, rbuf, tlen);
- afs_MemCacheClose(addr);
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- rbuf[alen - 1] = 0;
- alen = strlen(rbuf) + 1;
- tp = afs_osi_Alloc(alen); /* make room for terminating null */
- memcpy(tp, rbuf, alen);
- osi_FreeLargeSpace(rbuf);
- if (code != len) {
- afs_osi_Free(tp, alen);
- return EIO;
- }
- avc->linkData = tp;
- }
- return 0;
-}
-
-int
-afs_UFSHandleLink(register struct vcache *avc, struct vrequest *areq)
-{
- register struct dcache *tdc;
- register char *tp, *rbuf;
- void *tfile;
- afs_size_t offset, len;
- afs_int32 tlen, alen;
- register afs_int32 code;
-
- /* two different formats, one for links protected 644, have a "." at the
- * end of the file name, which we turn into a null. Others, protected
- * 755, we add a null to the end of */
- AFS_STATCNT(afs_UFSHandleLink);
- if (!avc->linkData) {
- tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 0);
- afs_Trace3(afs_iclSetp, CM_TRACE_UFSLINK, ICL_TYPE_POINTER, avc,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- if (!tdc) {
- return EIO;
- }
- /* otherwise we have the data loaded, go for it */
- if (len > 1024) {
- afs_PutDCache(tdc);
- return EFAULT;
- }
- if (avc->m.Mode & 0111)
- alen = len + 1; /* regular link */
- else
- alen = len; /* mt point */
- rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- tlen = len;
- ObtainReadLock(&tdc->lock);
- tfile = osi_UFSOpen(tdc->f.inode);
- code = afs_osi_Read(tfile, -1, rbuf, tlen);
- osi_UFSClose(tfile);
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- rbuf[alen - 1] = '\0';
- alen = strlen(rbuf) + 1;
- tp = afs_osi_Alloc(alen); /* make room for terminating null */
- memcpy(tp, rbuf, alen);
- osi_FreeLargeSpace(rbuf);
- if (code != tlen) {
- afs_osi_Free(tp, alen);
- return EIO;
- }
- avc->linkData = tp;
- }
- return 0;
-}
-
-int
-afs_readlink(OSI_VC_ARG(avc), auio, acred)
- OSI_VC_DECL(avc);
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- register afs_int32 code;
- struct vrequest treq;
- register char *tp;
- struct afs_fakestat_state fakestat;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_readlink);
- afs_Trace1(afs_iclSetp, CM_TRACE_READLINK, ICL_TYPE_POINTER, avc);
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- afs_InitFakeStat(&fakestat);
- code = afs_EvalFakeStat(&avc, &fakestat, &treq);
- if (code)
- goto done;
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto done;
- if (vType(avc) != VLNK) {
- code = EINVAL;
- goto done;
- }
- ObtainWriteLock(&avc->lock, 158);
- code = afs_HandleLink(avc, &treq);
- /* finally uiomove it to user-land */
- if (code == 0) {
- tp = avc->linkData;
- if (tp)
- AFS_UIOMOVE(tp, strlen(tp), UIO_READ, auio, code);
- else {
- code = EIO;
- }
- }
- ReleaseWriteLock(&avc->lock);
- done:
- afs_PutFakeStat(&fakestat);
- code = afs_CheckCode(code, &treq, 32);
- return code;
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_UFSWrite
- * afs_MemWrite
- * afs_StoreOnLastReference
- * afs_close
- * afs_closex
- * afs_fsync
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_write.c,v 1.35 2003/08/29 22:00:04 rees Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-extern unsigned char *afs_indexFlags;
-
-/* Called by all write-on-close routines: regular afs_close,
- * store via background daemon and store via the
- * afs_FlushActiveVCaches routine (when CCORE is on).
- * avc->lock must be write-locked.
- */
-int
-afs_StoreOnLastReference(register struct vcache *avc,
- register struct vrequest *treq)
-{
- int code = 0;
-
- AFS_STATCNT(afs_StoreOnLastReference);
- /* if CCore flag is set, we clear it and do the extra decrement
- * ourselves now. If we're called by the CCore clearer, the CCore
- * flag will already be clear, so we don't have to worry about
- * clearing it twice. */
- if (avc->states & CCore) {
- avc->states &= ~CCore;
-#if defined(AFS_SGI_ENV)
- osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
-#endif
- /* WARNING: Our linux cm code treats the execsOrWriters counter differently
- * depending on the flags the file was opened with. So, if you make any
- * changes to the way the execsOrWriters flag is handled check with the
- * top level code. */
- avc->opens--;
- avc->execsOrWriters--;
- AFS_RELE(AFSTOV(avc)); /* VN_HOLD at set CCore(afs_FakeClose) */
- crfree((struct AFS_UCRED *)avc->linkData); /* "crheld" in afs_FakeClose */
- avc->linkData = NULL;
- }
- /* Now, send the file back. Used to require 0 writers left, but now do
- * it on every close for write, since two closes in a row are harmless
- * since first will clean all chunks, and second will be noop. Note that
- * this will also save confusion when someone keeps a file open
- * inadvertently, since with old system, writes to the server would never
- * happen again.
- */
- code = afs_StoreAllSegments(avc, treq, AFS_LASTSTORE /*!sync-to-disk */ );
- /*
- * We have to do these after the above store in done: in some systems like
- * aix they'll need to flush all the vm dirty pages to the disk via the
- * strategy routine. During that all procedure (done under no avc locks)
- * opens, refcounts would be zero, since it didn't reach the afs_{rd,wr}
- * routines which means the vcache is a perfect candidate for flushing!
- */
-#if defined(AFS_SGI_ENV)
- osi_Assert(avc->opens > 0 && avc->execsOrWriters > 0);
-#endif
- avc->opens--;
- avc->execsOrWriters--;
- return code;
-}
-
-
-
-int
-afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
- struct AFS_UCRED *acred, int noLock)
-{
- afs_size_t totalLength;
- afs_size_t transferLength;
- afs_size_t filePos;
- afs_size_t offset, len;
- afs_int32 tlen, trimlen;
- afs_int32 startDate;
- afs_int32 max;
- register struct dcache *tdc;
-#ifdef _HIGHC_
- volatile
-#endif
- afs_int32 error;
- struct uio tuio;
- struct iovec *tvec; /* again, should have define */
- register afs_int32 code;
- struct vrequest treq;
-
- AFS_STATCNT(afs_MemWrite);
- if (avc->vc_error)
- return avc->vc_error;
-
- startDate = osi_Time();
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- /* otherwise we read */
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
- error = 0;
- transferLength = 0;
- afs_Trace4(afs_iclSetp, CM_TRACE_WRITE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(totalLength), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- if (!noLock) {
- afs_MaybeWakeupTruncateDaemon();
- ObtainWriteLock(&avc->lock, 126);
- }
-#if defined(AFS_SGI_ENV)
- {
- off_t diff;
- /*
- * afs_xwrite handles setting m.Length
- * and handles APPEND mode.
- * Since we are called via strategy, we need to trim the write to
- * the actual size of the file
- */
- osi_Assert(filePos <= avc->m.Length);
- diff = avc->m.Length - filePos;
- auio->afsio_resid = MIN(totalLength, diff);
- totalLength = auio->afsio_resid;
- }
-#else
- if (aio & IO_APPEND) {
- /* append mode, start it at the right spot */
-#if defined(AFS_SUN56_ENV)
- auio->uio_loffset = 0;
-#endif
- filePos = auio->afsio_offset = avc->m.Length;
- }
-#endif
- /*
- * Note that we use startDate rather than calling osi_Time() here.
- * This is to avoid counting lock-waiting time in file date (for ranlib).
- */
- avc->m.Date = startDate;
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_GFS_ENV)
-#if defined(AFS_HPUX101_ENV)
- if ((totalLength + filePos) >> 9 >
- (p_rlimit(u.u_procp))[RLIMIT_FSIZE].rlim_cur) {
-#else
-#ifdef AFS_HPUX_ENV
- if ((totalLength + filePos) >> 9 > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
-#else
- if (totalLength + filePos > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
-#endif
-#endif
- if (!noLock)
- ReleaseWriteLock(&avc->lock);
- return (EFBIG);
- }
-#endif
-#ifdef AFS_VM_RDWR_ENV
- /*
- * If write is implemented via VM, afs_FakeOpen() is called from the
- * high-level write op.
- */
- if (avc->execsOrWriters <= 0) {
- printf("WARNING: afs_ufswr vp=%x, exOrW=%d\n", avc,
- avc->execsOrWriters);
- }
-#else
- afs_FakeOpen(avc);
-#endif
- avc->states |= CDirty;
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- while (totalLength > 0) {
- /* Read the cached info. If we call GetDCache while the cache
- * truncate daemon is running we risk overflowing the disk cache.
- * Instead we check for an existing cache slot. If we cannot
- * find an existing slot we wait for the cache to drain
- * before calling GetDCache.
- */
- if (noLock) {
- tdc = afs_FindDCache(avc, filePos);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 653);
- } else if (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- tdc = afs_FindDCache(avc, filePos);
- if (tdc) {
- ObtainWriteLock(&tdc->lock, 654);
- if (!hsame(tdc->f.versionNo, avc->m.DataVersion)
- || (tdc->dflags & DFFetching)) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = NULL;
- }
- }
- if (!tdc) {
- afs_MaybeWakeupTruncateDaemon();
- while (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- ReleaseWriteLock(&avc->lock);
- if (afs_blocksUsed - afs_blocksDiscarded >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 1;
- afs_osi_Sleep(&afs_WaitForCacheDrain);
- }
- afs_MaybeFreeDiscardedDCache();
- afs_MaybeWakeupTruncateDaemon();
- ObtainWriteLock(&avc->lock, 506);
- }
- avc->states |= CDirty;
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 655);
- }
- } else {
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 656);
- }
- if (!tdc) {
- error = EIO;
- break;
- }
- if (!(afs_indexFlags[tdc->index] & IFDataMod)) {
- afs_stats_cmperf.cacheCurrDirtyChunks++;
- afs_indexFlags[tdc->index] |= IFDataMod; /* so it doesn't disappear */
- }
- if (!(tdc->f.states & DWriting)) {
- /* don't mark entry as mod if we don't have to */
- tdc->f.states |= DWriting;
- tdc->dflags |= DFEntryMod;
- }
- len = totalLength; /* write this amount by default */
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- max = AFS_CHUNKTOSIZE(tdc->f.chunk); /* max size of this chunk */
- if (max <= len + offset) { /*if we'd go past the end of this chunk */
- /* it won't all fit in this chunk, so write as much
- * as will fit */
- len = max - offset;
- }
- /* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
-
- code = afs_MemWriteUIO(tdc->f.inode, &tuio);
- if (code) {
- void *mep; /* XXX in prototype world is struct memCacheEntry * */
- error = code;
- ZapDCE(tdc); /* bad data */
- mep = afs_MemCacheOpen(tdc->f.inode);
- afs_MemCacheTruncate(mep, 0);
- afs_MemCacheClose(mep);
- afs_stats_cmperf.cacheCurrDirtyChunks--;
- afs_indexFlags[tdc->index] &= ~IFDataMod; /* so it does disappear */
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- break;
- }
- /* otherwise we've written some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
- tlen = len;
- afsio_skip(auio, tlen); /* advance auio over data written */
- /* compute new file size */
- if (offset + len > tdc->f.chunkBytes) {
- afs_int32 tlength = offset + len;
- afs_AdjustSize(tdc, tlength);
- if (tdc->validPos < filePos + len)
- tdc->validPos = filePos + len;
- }
- totalLength -= len;
- transferLength += len;
- filePos += len;
-#if defined(AFS_SGI_ENV)
- /* afs_xwrite handles setting m.Length */
- osi_Assert(filePos <= avc->m.Length);
-#else
- if (filePos > avc->m.Length) {
- afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(filePos));
- avc->m.Length = filePos;
- }
-#endif
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
-#if !defined(AFS_VM_RDWR_ENV)
- /*
- * If write is implemented via VM, afs_DoPartialWrite() is called from
- * the high-level write op.
- */
- if (!noLock) {
- code = afs_DoPartialWrite(avc, &treq);
- if (code) {
- error = code;
- break;
- }
- }
-#endif
- }
-#ifndef AFS_VM_RDWR_ENV
- afs_FakeClose(avc, acred);
-#endif
- if (error && !avc->vc_error)
- avc->vc_error = error;
- if (!noLock)
- ReleaseWriteLock(&avc->lock);
- osi_FreeSmallSpace(tvec);
-#ifdef AFS_DEC_ENV
- /* next, on GFS systems, we update g_size so that lseek's relative to EOF will
- * work. GFS is truly a poorly-designed interface! */
- afs_gfshack((struct gnode *)avc);
-#endif
- error = afs_CheckCode(error, &treq, 6);
- return error;
-}
-
-
-/* called on writes */
-int
-afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
- struct AFS_UCRED *acred, int noLock)
-{
- afs_size_t totalLength;
- afs_size_t transferLength;
- afs_size_t filePos;
- afs_size_t offset, len;
- afs_int32 tlen;
- afs_int32 trimlen;
- afs_int32 startDate;
- afs_int32 max;
- register struct dcache *tdc;
-#ifdef _HIGHC_
- volatile
-#endif
- afs_int32 error;
- struct uio tuio;
- struct iovec *tvec; /* again, should have define */
- struct osi_file *tfile;
- register afs_int32 code;
- struct vrequest treq;
-
- AFS_STATCNT(afs_UFSWrite);
- if (avc->vc_error)
- return avc->vc_error;
-
- startDate = osi_Time();
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- /* otherwise we read */
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
- error = 0;
- transferLength = 0;
- afs_Trace4(afs_iclSetp, CM_TRACE_WRITE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(totalLength), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- if (!noLock) {
- afs_MaybeWakeupTruncateDaemon();
- ObtainWriteLock(&avc->lock, 556);
- }
-#if defined(AFS_SGI_ENV)
- {
- off_t diff;
- /*
- * afs_xwrite handles setting m.Length
- * and handles APPEND mode.
- * Since we are called via strategy, we need to trim the write to
- * the actual size of the file
- */
- osi_Assert(filePos <= avc->m.Length);
- diff = avc->m.Length - filePos;
- auio->afsio_resid = MIN(totalLength, diff);
- totalLength = auio->afsio_resid;
- }
-#else
- if (aio & IO_APPEND) {
- /* append mode, start it at the right spot */
-#if defined(AFS_SUN56_ENV)
- auio->uio_loffset = 0;
-#endif
- filePos = auio->afsio_offset = avc->m.Length;
- }
-#endif
- /*
- * Note that we use startDate rather than calling osi_Time() here.
- * This is to avoid counting lock-waiting time in file date (for ranlib).
- */
- avc->m.Date = startDate;
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_GFS_ENV)
-#if defined(AFS_HPUX101_ENV)
- if ((totalLength + filePos) >> 9 >
- p_rlimit(u.u_procp)[RLIMIT_FSIZE].rlim_cur) {
-#else
-#ifdef AFS_HPUX_ENV
- if ((totalLength + filePos) >> 9 > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
-#else
- if (totalLength + filePos > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
-#endif
-#endif
- if (!noLock)
- ReleaseWriteLock(&avc->lock);
- return (EFBIG);
- }
-#endif
-#ifdef AFS_VM_RDWR_ENV
- /*
- * If write is implemented via VM, afs_FakeOpen() is called from the
- * high-level write op.
- */
- if (avc->execsOrWriters <= 0) {
- printf("WARNING: afs_ufswr vcp=%x, exOrW=%d\n", avc,
- avc->execsOrWriters);
- }
-#else
- afs_FakeOpen(avc);
-#endif
- avc->states |= CDirty;
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- while (totalLength > 0) {
- /*
- * The following line is necessary because afs_GetDCache with
- * flag == 4 expects the length field to be filled. It decides
- * from this whether it's necessary to fetch data into the chunk
- * before writing or not (when the whole chunk is overwritten!).
- */
- len = totalLength; /* write this amount by default */
- /* read the cached info */
- if (noLock) {
- tdc = afs_FindDCache(avc, filePos);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 657);
- } else if (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- tdc = afs_FindDCache(avc, filePos);
- if (tdc) {
- ObtainWriteLock(&tdc->lock, 658);
- if (!hsame(tdc->f.versionNo, avc->m.DataVersion)
- || (tdc->dflags & DFFetching)) {
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = NULL;
- }
- }
- if (!tdc) {
- afs_MaybeWakeupTruncateDaemon();
- while (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- ReleaseWriteLock(&avc->lock);
- if (afs_blocksUsed - afs_blocksDiscarded >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 1;
- afs_osi_Sleep(&afs_WaitForCacheDrain);
- }
- afs_MaybeFreeDiscardedDCache();
- afs_MaybeWakeupTruncateDaemon();
- ObtainWriteLock(&avc->lock, 509);
- }
- avc->states |= CDirty;
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 659);
- }
- } else {
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 4);
- if (tdc)
- ObtainWriteLock(&tdc->lock, 660);
- }
- if (!tdc) {
- error = EIO;
- break;
- }
- if (!(afs_indexFlags[tdc->index] & IFDataMod)) {
- afs_stats_cmperf.cacheCurrDirtyChunks++;
- afs_indexFlags[tdc->index] |= IFDataMod; /* so it doesn't disappear */
- }
- if (!(tdc->f.states & DWriting)) {
- /* don't mark entry as mod if we don't have to */
- tdc->f.states |= DWriting;
- tdc->dflags |= DFEntryMod;
- }
- tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
- len = totalLength; /* write this amount by default */
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- max = AFS_CHUNKTOSIZE(tdc->f.chunk); /* max size of this chunk */
- if (max <= len + offset) { /*if we'd go past the end of this chunk */
- /* it won't all fit in this chunk, so write as much
- * as will fit */
- len = max - offset;
- }
- /* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
-#if defined(AFS_AIX41_ENV)
- AFS_GUNLOCK();
- code =
- VNOP_RDWR(tfile->vnode, UIO_WRITE, FWRITE, &tuio, NULL, NULL,
- NULL, afs_osi_credp);
- AFS_GLOCK();
-#elif defined(AFS_AIX32_ENV)
- code = VNOP_RDWR(tfile->vnode, UIO_WRITE, FWRITE, &tuio, NULL, NULL);
-#elif defined(AFS_AIX_ENV)
- code =
- VNOP_RDWR(tfile->vnode, UIO_WRITE, FWRITE, (off_t) & offset,
- &tuio, NULL, NULL, -1);
-#elif defined(AFS_SUN5_ENV)
- AFS_GUNLOCK();
- VOP_RWLOCK(tfile->vnode, 1);
- code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_RWUNLOCK(tfile->vnode, 1);
- AFS_GLOCK();
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is full - decrease cachesize!!! ***\n\n\n");
-#elif defined(AFS_SGI_ENV)
- AFS_GUNLOCK();
- avc->states |= CWritingUFS;
- AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_WRITE);
- AFS_VOP_WRITE(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp, code);
- AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_WRITE);
- avc->states &= ~CWritingUFS;
- AFS_GLOCK();
-#elif defined(AFS_OSF_ENV)
- {
- struct ucred *tmpcred = u.u_cred;
- u.u_cred = afs_osi_credp;
- tuio.uio_rw = UIO_WRITE;
- AFS_GUNLOCK();
- VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp, code);
- AFS_GLOCK();
- u.u_cred = tmpcred;
- }
-#elif defined(AFS_HPUX100_ENV)
- {
- AFS_GUNLOCK();
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_WRITE, 0, afs_osi_credp);
- AFS_GLOCK();
- }
-#elif defined(AFS_LINUX20_ENV)
- AFS_GUNLOCK();
- code = osi_file_uio_rdwr(tfile, &tuio, UIO_WRITE);
- AFS_GLOCK();
-#elif defined(AFS_DARWIN_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
- code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, current_proc());
- AFS_GLOCK();
-#elif defined(AFS_FBSD50_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
- code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, curthread);
- AFS_GLOCK();
-#elif defined(AFS_XBSD_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
- code = VOP_WRITE(tfile->vnode, &tuio, 0, afs_osi_credp);
- VOP_UNLOCK(tfile->vnode, 0, curproc);
- AFS_GLOCK();
-#else
-#ifdef AFS_HPUX_ENV
- tuio.uio_fpflags &= ~FSYNCIO; /* don't do sync io */
-#endif
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_WRITE, 0, afs_osi_credp);
-#endif
- if (code) {
- error = code;
- ZapDCE(tdc); /* bad data */
- osi_UFSTruncate(tfile, 0); /* fake truncate the segment */
- afs_AdjustSize(tdc, 0); /* sets f.chunkSize to 0 */
- afs_stats_cmperf.cacheCurrDirtyChunks--;
- afs_indexFlags[tdc->index] &= ~IFDataMod; /* so it does disappear */
- afs_CFileClose(tfile);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- break;
- }
- /* otherwise we've written some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
- tlen = len;
- afsio_skip(auio, tlen); /* advance auio over data written */
- /* compute new file size */
- if (offset + len > tdc->f.chunkBytes) {
- afs_int32 tlength = offset + len;
- afs_AdjustSize(tdc, tlength);
- if (tdc->validPos < filePos + len)
- tdc->validPos = filePos + len;
- }
- totalLength -= len;
- transferLength += len;
- filePos += len;
-#if defined(AFS_SGI_ENV)
- /* afs_xwrite handles setting m.Length */
- osi_Assert(filePos <= avc->m.Length);
-#else
- if (filePos > avc->m.Length) {
- afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(filePos));
- avc->m.Length = filePos;
- }
-#endif
- osi_UFSClose(tfile);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
-#if !defined(AFS_VM_RDWR_ENV)
- /*
- * If write is implemented via VM, afs_DoPartialWrite() is called from
- * the high-level write op.
- */
- if (!noLock) {
- code = afs_DoPartialWrite(avc, &treq);
- if (code) {
- error = code;
- break;
- }
- }
-#endif
- }
-#ifndef AFS_VM_RDWR_ENV
- afs_FakeClose(avc, acred);
-#endif
- error = afs_CheckCode(error, &treq, 7);
- /* This set is here so we get the CheckCode. */
- if (error && !avc->vc_error)
- avc->vc_error = error;
- if (!noLock)
- ReleaseWriteLock(&avc->lock);
- osi_FreeSmallSpace(tvec);
-#ifdef AFS_DEC_ENV
- /* next, on GFS systems, we update g_size so that lseek's relative to EOF will
- * work. GFS is truly a poorly-designed interface! */
- afs_gfshack((struct gnode *)avc);
-#endif
-#ifndef AFS_VM_RDWR_ENV
- /*
- * If write is implemented via VM, afs_fsync() is called from the high-level
- * write op.
- */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if (noLock && (aio & IO_SYNC)) {
-#else
-#ifdef AFS_HPUX_ENV
- /* On hpux on synchronous writes syncio will be set to IO_SYNC. If
- * we're doing them because the file was opened with O_SYNCIO specified,
- * we have to look in the u area. No single mechanism here!!
- */
- if (noLock && ((aio & IO_SYNC) | (auio->uio_fpflags & FSYNCIO))) {
-#else
- if (noLock && (aio & FSYNC)) {
-#endif
-#endif
- if (!AFS_NFSXLATORREQ(acred))
- afs_fsync(avc, acred);
- }
-#endif
- return error;
-}
-
-/* do partial write if we're low on unmodified chunks */
-int
-afs_DoPartialWrite(register struct vcache *avc, struct vrequest *areq)
-{
- register afs_int32 code;
-
- if (afs_stats_cmperf.cacheCurrDirtyChunks <=
- afs_stats_cmperf.cacheMaxDirtyChunks)
- return 0; /* nothing to do */
- /* otherwise, call afs_StoreDCache (later try to do this async, if possible) */
- afs_Trace2(afs_iclSetp, CM_TRACE_PARTIALWRITE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
-#if defined(AFS_SUN5_ENV)
- code = afs_StoreAllSegments(avc, areq, AFS_ASYNC | AFS_VMSYNC_INVAL);
-#else
- code = afs_StoreAllSegments(avc, areq, AFS_ASYNC);
-#endif
- return code;
-}
-
-
-
-#if !defined (AFS_AIX_ENV) && !defined (AFS_HPUX_ENV) && !defined (AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#ifdef AFS_DUX50_ENV
-#define vno_close(X) vn_close((X), 0, NOCRED)
-#elif defined(AFS_DUX40_ENV)
-#define vno_close vn_close
-#endif
-/* We don't need this for AIX since:
- * (1) aix doesn't use fileops and it call close directly intead
- * (where the unlocking should be done) and
- * (2) temporarily, the aix lockf isn't supported yet.
- *
- * this stupid routine is used to release the flocks held on a
- * particular file descriptor. Sun doesn't pass file descr. info
- * through to the vnode layer, and yet we must unlock flocked files
- * on the *appropriate* (not first, as in System V) close call. Thus
- * this code.
- * How does this code get invoked? The afs AFS_FLOCK plugs in the new afs
- * file ops structure into any afs file when it gets flocked.
- * N.B: Intercepting close syscall doesn't trap aborts or exit system
- * calls.
-*/
-int
-afs_closex(register struct file *afd)
-{
- struct vrequest treq;
- struct vcache *tvc;
- afs_int32 flags;
- int closeDone;
- afs_int32 code = 0;
- struct afs_fakestat_state fakestat;
-
- AFS_STATCNT(afs_closex);
- /* setup the credentials */
- if ((code = afs_InitReq(&treq, u.u_cred)))
- return code;
- afs_InitFakeStat(&fakestat);
-
- closeDone = 0;
- /* we're the last one. If we're an AFS vnode, clear the flags,
- * close the file and release the lock when done. Otherwise, just
- * let the regular close code work. */
- if (afd->f_type == DTYPE_VNODE) {
- tvc = VTOAFS(afd->f_data);
- if (IsAfsVnode(AFSTOV(tvc))) {
- code = afs_EvalFakeStat(&tvc, &fakestat, &treq);
- if (code) {
- afs_PutFakeStat(&fakestat);
- return code;
- }
- VN_HOLD(AFSTOV(tvc));
- flags = afd->f_flag & (FSHLOCK | FEXLOCK);
- afd->f_flag &= ~(FSHLOCK | FEXLOCK);
- code = vno_close(afd);
- if (flags)
-#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
- HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
- 1 /*onlymine */ );
-#else
- HandleFlock(tvc, LOCK_UN, &treq, 0, 1 /*onlymine */ );
-#endif
-#ifdef AFS_DEC_ENV
- grele((struct gnode *)tvc);
-#else
- AFS_RELE(AFSTOV(tvc));
-#endif
- closeDone = 1;
- }
- }
- /* now, if close not done, do it */
- if (!closeDone) {
- code = vno_close(afd);
- }
- afs_PutFakeStat(&fakestat);
- return code; /* return code from vnode layer */
-}
-#endif
-
-
-/* handle any closing cleanup stuff */
-int
-#ifdef AFS_SGI_ENV
-afs_close(OSI_VC_ARG(avc), aflags, lastclose,
-#if !defined(AFS_SGI65_ENV)
- offset,
-#endif
- acred
-#if defined(AFS_SGI64_ENV) && !defined(AFS_SGI65_ENV)
- , flp
-#endif
- )
- lastclose_t lastclose;
-#if !defined(AFS_SGI65_ENV)
- off_t offset;
-#if defined(AFS_SGI64_ENV)
- struct flid *flp;
-#endif
-#endif
-#elif defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN5_ENV
-afs_close(OSI_VC_ARG(avc), aflags, count, offset, acred)
- offset_t offset;
-#else
-afs_close(OSI_VC_ARG(avc), aflags, count, acred)
-#endif
- int count;
-#else
-afs_close(OSI_VC_ARG(avc), aflags, acred)
-#endif
-OSI_VC_DECL(avc);
- afs_int32 aflags;
- struct AFS_UCRED *acred;
-{
- register afs_int32 code;
- register struct brequest *tb;
- struct vrequest treq;
-#ifdef AFS_SGI65_ENV
- struct flid flid;
-#endif
- struct afs_fakestat_state fakestat;
- OSI_VC_CONVERT(avc)
-
- AFS_STATCNT(afs_close);
- afs_Trace2(afs_iclSetp, CM_TRACE_CLOSE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, aflags);
- code = afs_InitReq(&treq, acred);
- if (code)
- return code;
- afs_InitFakeStat(&fakestat);
- code = afs_EvalFakeStat(&avc, &fakestat, &treq);
- if (code) {
- afs_PutFakeStat(&fakestat);
- return code;
- }
-#ifdef AFS_SUN5_ENV
- if (avc->flockCount) {
- HandleFlock(avc, LOCK_UN, &treq, 0, 1 /*onlymine */ );
- }
-#endif
-#if defined(AFS_SGI_ENV)
- if (!lastclose) {
- afs_PutFakeStat(&fakestat);
- return 0;
- }
-#elif defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV)
- if (count > 1) {
- /* The vfs layer may call this repeatedly with higher "count"; only on the last close (i.e. count = 1) we should actually proceed with the close. */
- afs_PutFakeStat(&fakestat);
- return 0;
- }
-#endif
-#ifndef AFS_SUN5_ENV
-#if defined(AFS_SGI_ENV)
- /* unlock any locks for pid - could be wrong for child .. */
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#ifdef AFS_SGI65_ENV
- get_current_flid(&flid);
- cleanlocks((vnode_t *) avc, flid.fl_pid, flid.fl_sysid);
- HandleFlock(avc, LOCK_UN, &treq, flid.fl_pid, 1 /*onlymine */ );
-#else
-#ifdef AFS_SGI64_ENV
- cleanlocks((vnode_t *) avc, flp);
-#else /* AFS_SGI64_ENV */
- cleanlocks((vnode_t *) avc, u.u_procp->p_epid, u.u_procp->p_sysid);
-#endif /* AFS_SGI64_ENV */
- HandleFlock(avc, LOCK_UN, &treq, OSI_GET_CURRENT_PID(), 1 /*onlymine */ );
-#endif /* AFS_SGI65_ENV */
- /* afs_chkpgoob will drop and re-acquire the global lock. */
- afs_chkpgoob(&avc->v, btoc(avc->m.Length));
-#else /* AFS_SGI_ENV */
- if (avc->flockCount) { /* Release Lock */
-#if defined(AFS_OSF_ENV) || defined(AFS_SUN_ENV)
- HandleFlock(avc, LOCK_UN, &treq, u.u_procp->p_pid, 1 /*onlymine */ );
-#else
- HandleFlock(avc, LOCK_UN, &treq, 0, 1 /*onlymine */ );
-#endif
- }
-#endif /* AFS_SGI_ENV */
-#endif /* AFS_SUN5_ENV */
- if (aflags & (FWRITE | FTRUNC)) {
- if (afs_BBusy()) {
- /* do it yourself if daemons are all busy */
- ObtainWriteLock(&avc->lock, 124);
- code = afs_StoreOnLastReference(avc, &treq);
- ReleaseWriteLock(&avc->lock);
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
- } else {
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
-#endif
- /* at least one daemon is idle, so ask it to do the store.
- * Also, note that we don't lock it any more... */
- tb = afs_BQueue(BOP_STORE, avc, 0, 1, acred,
- (afs_size_t) acred->cr_uid, (afs_size_t) 0,
- (void *)0);
- /* sleep waiting for the store to start, then retrieve error code */
- while ((tb->flags & BUVALID) == 0) {
- tb->flags |= BUWAIT;
- afs_osi_Sleep(tb);
- }
- code = tb->code;
- afs_BRelease(tb);
- }
-
- /* VNOVNODE is "acceptable" error code from close, since
- * may happen when deleting a file on another machine while
- * it is open here. We do the same for ENOENT since in afs_CheckCode we map VNOVNODE -> ENOENT */
- if (code == VNOVNODE || code == ENOENT)
- code = 0;
-
- /* Ensure last closer gets the error. If another thread caused
- * DoPartialWrite and this thread does not actually store the data,
- * it may not see the quota error.
- */
- ObtainWriteLock(&avc->lock, 406);
- if (avc->vc_error) {
-#ifdef AFS_AIX32_ENV
- osi_ReleaseVM(avc, acred);
-#endif
- code = avc->vc_error;
- avc->vc_error = 0;
- }
- ReleaseWriteLock(&avc->lock);
-
- /* some codes merit specific complaint */
- if (code < 0) {
- afs_warnuser("afs: failed to store file (network problems)\n");
- }
-#ifdef AFS_SUN5_ENV
- else if (code == ENOSPC) {
- afs_warnuser
- ("afs: failed to store file (over quota or partition full)\n");
- }
-#else
- else if (code == ENOSPC) {
- afs_warnuser("afs: failed to store file (partition full)\n");
- } else if (code == EDQUOT) {
- afs_warnuser("afs: failed to store file (over quota)\n");
- }
-#endif
- else if (code != 0)
- afs_warnuser("afs: failed to store file (%d)\n", code);
-
- /* finally, we flush any text pages lying around here */
- hzero(avc->flushDV);
- osi_FlushText(avc);
- } else {
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
- osi_Assert(avc->opens > 0);
-#endif
- /* file open for read */
- ObtainWriteLock(&avc->lock, 411);
- if (avc->vc_error) {
-#ifdef AFS_AIX32_ENV
- osi_ReleaseVM(avc, acred);
-#endif
- code = avc->vc_error;
- avc->vc_error = 0;
- }
- avc->opens--;
- ReleaseWriteLock(&avc->lock);
- }
-#ifdef AFS_OSF_ENV
- if ((VREFCOUNT(avc) <= 2) && (avc->states & CUnlinked)) {
- afs_remunlink(avc, 1); /* ignore any return code */
- }
-#endif
- afs_PutFakeStat(&fakestat);
- code = afs_CheckCode(code, &treq, 5);
- return code;
-}
-
-
-int
-#ifdef AFS_OSF_ENV
-afs_fsync(avc, fflags, acred, waitfor)
- int fflags;
- int waitfor;
-#else /* AFS_OSF_ENV */
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN53_ENV)
-afs_fsync(OSI_VC_ARG(avc), flag, acred
-#ifdef AFS_SGI65_ENV
- , start, stop
-#endif
- )
-#else
-afs_fsync(avc, acred)
-#endif
-#endif
-OSI_VC_DECL(avc);
- struct AFS_UCRED *acred;
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN53_ENV)
- int flag;
-#ifdef AFS_SGI65_ENV
- off_t start, stop;
-#endif
-#endif
-{
- register afs_int32 code;
- struct vrequest treq;
- OSI_VC_CONVERT(avc)
-
- if (avc->vc_error)
- return avc->vc_error;
-
-#if defined(AFS_SUN5_ENV)
- /* back out if called from NFS server */
- if (curthread->t_flag & T_DONTPEND)
- return 0;
-#endif
-
- AFS_STATCNT(afs_fsync);
- afs_Trace1(afs_iclSetp, CM_TRACE_FSYNC, ICL_TYPE_POINTER, avc);
- if ((code = afs_InitReq(&treq, acred)))
- return code;
-
-#if defined(AFS_SGI_ENV)
- AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
- if (flag & FSYNC_INVAL)
- osi_VM_FSyncInval(avc);
-#endif /* AFS_SGI_ENV */
-
- ObtainSharedLock(&avc->lock, 18);
- code = 0;
- if (avc->execsOrWriters > 0) {
- /* put the file back */
- UpgradeSToWLock(&avc->lock, 41);
- code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
- ConvertWToSLock(&avc->lock);
- }
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
- if (code == VNOVNODE) {
- /* syncing an unlinked file! - non-informative to pass an errno
- * 102 (== VNOVNODE) to user
- */
- code = ENOENT;
- }
-#endif
-
- code = afs_CheckCode(code, &treq, 33);
- ReleaseSharedLock(&avc->lock);
- return code;
-}
+++ /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
- */
-
-#ifndef _AFS_H_
-#define _AFS_H_
-/*
- * AFS system call opcodes
- */
-#ifdef KDUMP_KERNEL
-#include <afs/afs_args.h>
-#else
-#include "afs/afs_args.h"
-#endif
-
-
-/* Upper bound on number of iovecs out uio routines will deal with. */
-#define AFS_MAXIOVCNT 16
-
-
-extern int afs_shuttingdown;
-
-/*
- * Macros to uniquely identify the AFS vfs struct
- */
-#define AFS_VFSMAGIC 0x1234
-#if defined(AFS_SUN_ENV) || defined(AFS_HPUX90_ENV) || defined(AFS_LINUX20_ENV)
-#define AFS_VFSFSID 99
-#else
-#if defined(AFS_SGI_ENV)
-#define AFS_VFSFSID afs_fstype
-#else
-#define AFS_VFSFSID AFS_MOUNT_AFS
-#endif
-#endif
-
-/* Moved from VNOPS/afs_vnop_flocks so can be used in prototypes */
-#if defined(AFS_HPUX102_ENV)
-#define AFS_FLOCK k_flock
-#else
-#if defined(AFS_SUN56_ENV) || defined(AFS_LINUX24_ENV)
-#define AFS_FLOCK flock64
-#else
-#define AFS_FLOCK flock
-#endif /* AFS_SUN65_ENV */
-#endif /* AFS_HPUX102_ENV */
-
-/* The following are various levels of afs debugging */
-#define AFSDEB_GENERAL 1 /* Standard debugging */
-#define AFSDEB_NETWORK 2 /* low level afs networking */
-#define AFSDEB_RX 4 /* RX debugging */
-#define AFSDEB_VNLAYER 8 /* interface layer to AFS (aixops, gfsops, etc) */
-
-/* generic undefined vice id */
-#define UNDEFVID (-1)
-
-/* The basic defines for the Andrew file system
- better keep things powers of two so "& (foo-1)" hack works for masking bits */
-#define MAXHOSTS 13 /* max hosts per single volume */
-#define OMAXHOSTS 8 /* backwards compatibility */
-#define MAXCELLHOSTS 8 /* max vldb servers per cell */
-#define NBRS 15 /* max number of queued daemon requests */
-#define NUSERS 16 /* hash table size for unixuser table */
-#define NSERVERS 16 /* hash table size for server table */
-#define NVOLS 64 /* hash table size for volume table */
-#define NFENTRIES 256 /* hash table size for disk volume table */
-#define VCSIZE 1024 /* stat cache hash table size */
-#define DCSIZE 512 /* disk cache hash table size */
-#define CBRSIZE 512 /* call back returns hash table size */
-#define PIGGYSIZE 1350 /* max piggyback size */
-#define MAXVOLS 128 /* max vols we can store */
-#define MAXSYSNAME 128 /* max sysname (i.e. @sys) size */
-#define MAXNUMSYSNAMES 16 /* max that current constants allow */
-#define NOTOKTIMEOUT (2*3600) /* time after which to timeout conns sans tokens */
-#define NOPAG 0xffffffff
-#define AFS_NCBRS 300 /* max # of call back return entries */
-#define AFS_MAXCBRSCALL 16 /* max to return in a given call */
-#define AFS_SALLOC_LOW_WATER 250 /* Min free blocks before allocating more */
-#define AFS_LRALLOCSIZ 4096 /* "Large" allocated size */
-#define VCACHE_FREE 5
-#define AFS_NRXPACKETS 80
-#define AFS_RXDEADTIME 50
-#define AFS_HARDDEADTIME 120
-
-extern afs_int32 afs_rx_deadtime;
-extern afs_int32 afs_rx_harddead;
-
-struct sysname_info {
- char *name;
- short offset;
- char index, allocked;
-};
-
-/* flags to use with AFSOP_CACHEINIT */
-#define AFSCALL_INIT_MEMCACHE 0x1 /* use a memory-based cache */
-
-/* below here used only for kernel procedures */
-#ifdef KERNEL
-/* Store synchrony flags - SYNC means that data should be forced to server's
- * disk immediately upon completion. */
-#define AFS_ASYNC 0
-#define AFS_SYNC 1
-#define AFS_VMSYNC_INVAL 2 /* sync and invalidate pages */
-#define AFS_LASTSTORE 4
-
-
-/* background request structure */
-#define BPARMS 4
-
-#define BOP_NOOP 0 /* leave 0 unused */
-#define BOP_FETCH 1 /* parm1 is chunk to get */
-#define BOP_STORE 2 /* parm1 is chunk to store */
-#define BOP_PATH 3 /* parm1 is path, parm2 is chunk to fetch */
-
-#define B_DONTWAIT 1 /* On failure return; don't wait */
-
-/* protocol is: refCount is incremented by user to take block out of free pool.
- Next, BSTARTED is set when daemon finds request. This prevents
- other daemons from picking up the same request. Finally, when
- request is done, refCount is zeroed. BDONE and BWAIT are used by
- dudes waiting for operation to proceed to a certain point before returning.
-*/
-#define BSTARTED 1 /* request picked up by a daemon */
-#define BUVALID 2 /* code is valid (store) */
-#define BUWAIT 4 /* someone is waiting for BUVALID */
-struct brequest {
- struct vcache *vc; /* vnode to use, with vrefcount bumped */
- struct AFS_UCRED *cred; /* credentials to use for operation */
- afs_size_t size_parm[BPARMS]; /* random parameters */
- void *ptr_parm[BPARMS]; /* pointer parameters */
- afs_int32 code; /* return code */
- short refCount; /* use counter for this structure */
- char opcode; /* what to do (store, fetch, etc) */
- char flags; /* free, etc */
- afs_int32 ts; /* counter "timestamp" */
-};
-
-struct SecretToken {
- char data[56];
-};
-
-struct ClearToken {
- afs_int32 AuthHandle;
- char HandShakeKey[8];
- afs_int32 ViceId;
- afs_int32 BeginTimestamp;
- afs_int32 EndTimestamp;
-};
-
-struct VenusFid {
- afs_int32 Cell; /* better sun packing if at end of structure */
- struct AFSFid Fid;
-};
-
-/* Temporary struct to be passed between afs_fid and afs_vget; in SunOS4.x we can only pass a maximum of 10 bytes for a handle (we ideally need 16!) */
-struct SmallFid {
- afs_int32 Volume;
- afs_int32 CellAndUnique;
- u_short Vnode;
-};
-/* The actual number of bytes in the SmallFid, not the sizeof struct. */
-#define SIZEOF_SMALLFID 10
-
-
-/*
- * Queues implemented with both pointers and short offsets into a disk file.
- */
-struct afs_q {
- struct afs_q *next;
- struct afs_q *prev;
-};
-
-struct vrequest {
- afs_int32 uid; /* user id making the request */
- afs_int32 busyCount; /* how many busies we've seen so far */
- afs_int32 flags; /* things like O_SYNC, O_NONBLOCK go here */
- char initd; /* if non-zero, non-uid fields meaningful */
- char accessError; /* flags for overriding error return code */
- char volumeError; /* encountered a missing or busy volume */
- char networkError; /* encountered network problems */
- char permWriteError; /* fileserver returns permenent error. */
-};
-#define VOLMISSING 1
-#define VOLBUSY 2
-
-/* structure linked off of a server to keep track of queued returned
- * callbacks. Sent asynchronously when we run a little low on free dudes.
- */
-struct afs_cbr {
- struct afs_cbr **pprev;
- struct afs_cbr *next;
-
- struct afs_cbr **hash_pprev;
- struct afs_cbr *hash_next;
-
- struct AFSFid fid;
-};
-
-/* cellinfo file magic number */
-#define AFS_CELLINFO_MAGIC 0xf32817cd
-
-/* cell flags */
-#define CNoSUID 0x02 /* disable suid bit for this cell */
-#define CLinkedCell4 0x04 /* reserved for ADDCELL2 pioctl */
-#define CNoAFSDB 0x08 /* never bother trying AFSDB */
-#define CHasVolRef 0x10 /* volumes were referenced */
-#define CLinkedCell 0x20 /* has a linked cell in lcellp */
-
-struct cell {
- struct afs_q lruq; /* lru q next and prev */
- char *cellName; /* char string name of cell */
- afs_int32 cellIndex; /* sequence number */
- afs_int32 cellNum; /* semi-permanent cell number */
- struct server *cellHosts[MAXCELLHOSTS]; /* volume *location* hosts */
- struct cell *lcellp; /* Associated linked cell */
- u_short fsport; /* file server port */
- u_short vlport; /* volume server port */
- short states; /* state flags */
- time_t timeout; /* data expire time, if non-zero */
- struct cell_name *cnamep; /* pointer to our cell_name */
- afs_rwlock_t lock; /* protects cell data */
-};
-
-struct cell_name {
- struct cell_name *next;
- afs_int32 cellnum;
- char *cellname;
- char used;
-};
-
-struct cell_alias {
- struct cell_alias *next;
- afs_int32 index;
- char *alias;
- char *cell;
-};
-
-#define afs_PutCell(cellp, locktype)
-
-/* the unixuser flag bit definitions */
-#define UHasTokens 1 /* are the st and ct fields valid (ever set)? */
-#define UTokensBad 2 /* are tokens bad? */
-#define UPrimary 4 /* on iff primary identity */
-#define UNeedsReset 8 /* needs afs_ResetAccessCache call done */
-#define UPAGCounted 16 /* entry seen during PAG search (for stats) */
-/* A flag used by afs_GCPAGs to keep track of
- * which entries in afs_users need to be deleted.
- * The lifetime of its presence in the table is the
- * lifetime of the afs_GCPAGs function.
- */
-#define TMP_UPAGNotReferenced 128
-
-/* values for afs_gcpags */
-enum { AFS_GCPAGS_NOTCOMPILED = 0, AFS_GCPAGS_OK =
- 1, AFS_GCPAGS_USERDISABLED, AFS_GCPAGS_EPROC0, AFS_GCPAGS_EPROCN,
- AFS_GCPAGS_EEQPID, AFS_GCPAGS_EINEXACT, AFS_GCPAGS_EPROCEND,
- AFS_GCPAGS_EPROCWALK, AFS_GCPAGS_ECREDWALK, AFS_GCPAGS_EPIDCHECK,
- AFS_GCPAGS_ENICECHECK
-};
-
-extern afs_int32 afs_gcpags;
-extern afs_int32 afs_gcpags_procsize;
-extern afs_int32 afs_bkvolpref;
-
-struct unixuser {
- struct unixuser *next; /* next hash pointer */
- afs_int32 uid; /* search based on uid and cell */
- afs_int32 cell;
- afs_int32 vid; /* corresponding vice id in specified cell */
- short refCount; /* reference count for allocation */
- char states; /* flag info */
- afs_int32 tokenTime; /* last time tokens were set, used for timing out conn data */
- afs_int32 stLen; /* ticket length (if kerberos, includes kvno at head) */
- char *stp; /* pointer to ticket itself */
- struct ClearToken ct;
- struct afs_exporter *exporter; /* more info about the exporter for the remote user */
-};
-
-struct conn {
- /* Per-connection block. */
- struct conn *next; /* Next dude same server. */
- struct unixuser *user; /* user validated with respect to. */
- struct rx_connection *id; /* RPC connid. */
- struct srvAddr *srvr; /* server associated with this conn */
- short refCount; /* reference count for allocation */
- unsigned short port; /* port associated with this connection */
- char forceConnectFS; /* Should we try again with these tokens? */
-};
-
-
-#define SQNULL -1
-
-/* Fid comparison routines */
-#define FidCmp(a,b) ((a)->Fid.Unique != (b)->Fid.Unique \
- || (a)->Fid.Vnode != (b)->Fid.Vnode \
- || (a)->Fid.Volume != (b)->Fid.Volume \
- || (a)->Cell != (b)->Cell)
-
-#define FidMatches(afid,tvc) ((tvc)->fid.Fid.Vnode == (afid)->Fid.Vnode && \
- (tvc)->fid.Fid.Volume == (afid)->Fid.Volume && \
- (tvc)->fid.Cell == (afid)->Cell && \
- ( (tvc)->fid.Fid.Unique == (afid)->Fid.Unique || \
- (!(afid)->Fid.Unique && ((tvc)->states & CUnique))))
-
-
-/*
- * Operations on circular queues implemented with pointers. Note: these queue
- * objects are always located at the beginning of the structures they are linking.
- */
-#define QInit(q) ((q)->prev = (q)->next = (q))
-#define QAdd(q,e) ((e)->next = (q)->next, (e)->prev = (q), \
- (q)->next->prev = (e), (q)->next = (e))
-#define QRemove(e) ((e)->next->prev = (e)->prev, (e)->prev->next = (e)->next)
-#define QNext(e) ((e)->next)
-#define QPrev(e) ((e)->prev)
-#define QEmpty(q) ((q)->prev == (q))
-/* this one takes q1 and sticks it on the end of q2 - that is, the other end, not the end
- * that things are added onto. q1 shouldn't be empty, it's silly */
-#define QCat(q1,q2) ((q2)->prev->next = (q1)->next, (q1)->next->prev=(q2)->prev, (q1)->prev->next=(q2), (q2)->prev=(q1)->prev, (q1)->prev=(q1)->next=(q1))
-/*
- * Do lots of address arithmetic to go from vlruq to the base of the vcache
- * structure. Don't move struct vnode, since we think of a struct vcache as
- * a specialization of a struct vnode
- */
-#define QTOV(e) ((struct vcache *)(((char *) (e)) - (((char *)(&(((struct vcache *)(e))->vlruq))) - ((char *)(e)))))
-#define QTOC(e) ((struct cell *)((char *) (e)))
-
-#define SRVADDR_MH 1
-#define SRVADDR_ISDOWN 0x20 /* same as SRVR_ISDOWN */
-#define SRVADDR_NOUSE 0x40 /* Don't use this srvAddr */
-struct srvAddr {
- struct srvAddr *next_bkt; /* next item in hash bucket */
- struct srvAddr *next_sa; /* another interface on same host */
- struct server *server; /* back to parent */
- struct conn *conns; /* All user connections to this server */
- afs_int32 sa_ip; /* Host addr in network byte order */
- u_short sa_iprank; /* indiv ip address priority */
- u_short sa_portal; /* port addr in network byte order */
- u_char sa_flags;
-};
-
-/*
- * Values used in the flags field of the server structure below.
- *
- * AFS_SERVER_FLAG_ACTIVATED Has the server ever had a user connection
- * associated with it?
- */
-#define AFS_SERVER_FLAG_ACTIVATED 0x01
-#define SNO_LHOSTS 0x04
-#define SYES_LHOSTS 0x08
-#define SVLSRV_UUID 0x10
-#define SRVR_ISDOWN 0x20
-#define SRVR_MULTIHOMED 0x40
-#define SRVR_ISGONE 0x80
-#define SNO_INLINEBULK 0x100
-#define SNO_64BIT 0x200
-
-#define afs_serverSetNo64Bit(s) ((s)->srvr->server->flags |= SNO_64BIT)
-#define afs_serverHasNo64Bit(s) ((s)->srvr->server->flags & SNO_64BIT)
-
-struct server {
- union {
- struct {
- afsUUID suuid;
- afs_int32 addr_uniquifier;
- afs_int32 spares[2];
- } _srvUuid;
- struct {
- struct srvAddr haddr;
- } _srvId;
- } _suid;
-#define sr_uuid _suid._srvUuid.suuid
-#define sr_addr_uniquifier _suid._srvUuid.addr_uniquifier
-#define sr_host _suid._srvId.haddr.ip
-#define sr_portal _suid._srvId.haddr.portal
-#define sr_rank _suid._srvId.haddr.ip_rank
-#define sr_flags _suid._srvId.haddr.flags
-#define sr_conns _suid._srvId.haddr.conns
- struct server *next; /* Ptr to next server in hash chain */
- struct cell *cell; /* Cell in which this host resides */
- struct afs_cbr *cbrs; /* Return list of callbacks */
- afs_int32 activationTime; /* Time when this record was first activated */
- afs_int32 lastDowntimeStart; /* Time when last downtime incident began */
- afs_int32 numDowntimeIncidents; /* # (completed) downtime incidents */
- afs_int32 sumOfDowntimes; /* Total downtime experienced, in seconds */
- struct srvAddr *addr;
- afs_uint32 flags; /* Misc flags */
-};
-
-#define afs_PutServer(servp, locktype)
-
-/* structs for some pioctls - these are (or should be)
- * also in venus.h
- */
-struct spref {
- struct in_addr host;
- unsigned short rank;
-};
-
-struct sprefrequest_33 {
- unsigned short offset;
- unsigned short num_servers;
-};
-
-
-struct sprefrequest { /* new struct for 3.4 */
- unsigned short offset;
- unsigned short num_servers;
- unsigned short flags;
-};
-#define DBservers 1
-
-struct sprefinfo {
- unsigned short next_offset;
- unsigned short num_servers;
- struct spref servers[1]; /* we overrun this array intentionally... */
-};
-
-struct setspref {
- unsigned short flags;
- unsigned short num_servers;
- struct spref servers[1]; /* we overrun this array intentionally... */
-};
-/* struct for GAG pioctl
- */
-struct gaginfo {
- afs_uint32 showflags, logflags, logwritethruflag, spare[3];
- unsigned char spare2[128];
-};
-#define GAGUSER 1
-#define GAGCONSOLE 2
-#define logwritethruON 1
-
-struct rxparams {
- afs_int32 rx_initReceiveWindow, rx_maxReceiveWindow, rx_initSendWindow,
- rx_maxSendWindow, rxi_nSendFrags, rxi_nRecvFrags, rxi_OrphanFragSize;
- afs_int32 rx_maxReceiveSize, rx_MyMaxSendSize;
- afs_uint32 spare[21];
-};
-
-/* struct for checkservers */
-
-struct chservinfo {
- int magic;
- char tbuffer[128];
- int tsize;
- afs_int32 tinterval;
- afs_int32 tflags;
-};
-
-
-/* state bits for volume */
-#define VRO 1 /* volume is readonly */
-#define VRecheck 2 /* recheck volume info with server */
-#define VBackup 4 /* is this a backup volume? */
-#define VForeign 8 /* this is a non-afs volume */
-#define VResort 16 /* server order was rearranged, sort when able */
-#define VMoreReps 32 /* This volume has more replicas than we are */
- /* keeping track of now -- check with VLDB */
-
-enum repstate { not_busy, end_not_busy = 6, rd_busy, rdwr_busy, offline };
-
-struct volume {
- /* One structure per volume, describing where the volume is located
- * and where its mount points are. */
- struct volume *next; /* Next volume in hash list. */
- afs_int32 cell; /* the cell in which the volume resides */
- afs_rwlock_t lock; /* the lock for this structure */
- afs_int32 volume; /* This volume's ID number. */
- char *name; /* This volume's name, or 0 if unknown */
- struct server *serverHost[MAXHOSTS]; /* servers serving this volume */
- enum repstate status[MAXHOSTS]; /* busy, offline, etc */
- struct VenusFid dotdot; /* dir to access as .. */
- struct VenusFid mtpoint; /* The mount point for this volume. */
- afs_int32 rootVnode, rootUnique; /* Volume's root fid */
- afs_int32 roVol;
- afs_int32 backVol;
- afs_int32 rwVol; /* For r/o vols, original read/write volume. */
- afs_int32 accessTime; /* last time we used it */
- afs_int32 vtix; /* volume table index */
- afs_int32 copyDate; /* copyDate field, for tracking vol releases */
- afs_int32 expireTime; /* for per-volume callbacks... */
- short refCount; /* reference count for allocation */
- char states; /* here for alignment reasons */
-};
-
-#define afs_PutVolume(av, locktype) ((av)->refCount--)
-
-/* format of an entry in volume info file */
-struct fvolume {
- afs_int32 cell; /* cell for this entry */
- afs_int32 volume; /* volume */
- afs_int32 next; /* has index */
- struct VenusFid dotdot; /* .. value */
- struct VenusFid mtpoint; /* mt point's fid */
- afs_int32 rootVnode, rootUnique; /* Volume's root fid */
-};
-
-struct SimpleLocks {
- struct SimpleLocks *next;
- int type;
- afs_int32 boff, eoff;
- afs_int32 pid;
-#if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
- afs_int32 sysid;
-#endif
-};
-
-/* vcache state bits */
-#define CStatd 0x00000001 /* has this file ever been stat'd? */
-#define CBackup 0x00000002 /* file is on a backup volume */
-#define CRO 0x00000004 /* is it on a read-only volume */
-#define CMValid 0x00000008 /* is the mount point info valid? */
-#define CCore 0x00000010 /* storing a core file, needed since we don't get an open */
-#define CDirty 0x00000020 /* file has been modified since first open (... O_RDWR) */
-#define CSafeStore 0x00000040 /* close must wait for store to finish (should be in fd) */
-#define CMAPPED 0x00000080 /* Mapped files; primarily used by SunOS 4.0.x */
-#define CNSHARE 0x00000100 /* support O_NSHARE semantics */
-#define CLied 0x00000200
-#define CTruth 0x00000400
-#ifdef AFS_OSF_ENV
-#define CWired 0x00000800 /* OSF hack only */
-#else
-#ifdef AFS_DARWIN_ENV
-#define CUBCinit 0x00000800
-#else
-#define CWRITE_IGN 0x00000800 /* Next OS hack only */
-#endif
-#endif
-#define CUnique 0x00001000 /* vc's uniquifier - latest unifiquier for fid */
-#define CForeign 0x00002000 /* this is a non-afs vcache */
-#define CUnlinked 0x00010000
-#define CBulkStat 0x00020000 /* loaded by a bulk stat, and not ref'd since */
-#define CUnlinkedDel 0x00040000
-#define CVFlushed 0x00080000
-#define CCore1 0x00100000 /* osf1 core file; not same as CCore above */
-#define CWritingUFS 0x00200000 /* to detect vm deadlock - used by sgi */
-#define CCreating 0x00400000 /* avoid needless store after open truncate */
-#define CPageHog 0x00800000 /* AIX - dumping large cores is a page hog. */
-#define CDCLock 0x02000000 /* Vnode lock held over call to GetDownD */
-#define CBulkFetching 0x04000000 /* stats are being fetched by bulk stat */
-#define CExtendedFile 0x08000000 /* extended file via ftruncate call. */
-
-/* vcache vstate bits */
-#define VRevokeWait 0x1
-#define VPageCleaning 0x2 /* Solaris - Cache Trunc Daemon sez keep out */
-
-#define CPSIZE 2
-#if defined(AFS_XBSD_ENV)
-#define vrefCount v->v_usecount
-#else
-#define vrefCount v.v_count
-#endif /* AFS_XBSD_ENV */
-
-#if defined(AFS_LINUX24_ENV)
-#define VREFCOUNT(v) atomic_read(&((vnode_t *) v)->v_count)
-#define VREFCOUNT_SET(v, c) atomic_set(&((vnode_t *) v)->v_count, c)
-#define VREFCOUNT_DEC(v) atomic_dec(&((vnode_t *) v)->v_count)
-#define VREFCOUNT_INC(v) atomic_inc(&((vnode_t *) v)->v_count)
-#define DLOCK() spin_lock(&dcache_lock)
-#define DUNLOCK() spin_unlock(&dcache_lock)
-#define DGET(d) dget_locked(d)
-#define DCOUNT(d) atomic_read(&(d)->d_count)
-#else
-#define VREFCOUNT(v) ((v)->vrefCount)
-#define VREFCOUNT_SET(v, c) (v)->vrefCount = c;
-#define VREFCOUNT_DEC(v) (v)->vrefCount--;
-#define VREFCOUNT_INC(v) (v)->vrefCount++;
-#define DLOCK()
-#define DUNLOCK()
-#define DGET(d) dget(d)
-#define DCOUNT(d) ((d)->d_count)
-#endif
-
-#define AFS_MAXDV 0x7fffffff /* largest dataversion number */
-#ifdef AFS_64BIT_CLIENT
-#define AFS_NOTRUNC 0x7fffffffffffffffLL /* largest positive int64 number */
-#else /* AFS_64BIT_CLIENT */
-#define AFS_NOTRUNC 0x7fffffff /* largest dataversion number */
-#endif /* AFS_64BIT_CLIENT */
-
-extern afs_int32 vmPageHog; /* counter for # of vnodes which are page hogs. */
-
-/*
- * Fast map from vcache to dcache
- */
-struct vtodc {
- struct dcache *dc;
- afs_uint32 stamp;
- struct osi_file *f;
- afs_offs_t minLoc; /* smallest offset into dc. */
- afs_offs_t len; /* largest offset into dc. */
-};
-
-extern afs_uint32 afs_stampValue; /* stamp for pair's usage */
-#define MakeStamp() (++afs_stampValue)
-
-#if defined(AFS_XBSD_ENV)
-#define VTOAFS(v) ((struct vcache *)(v)->v_data)
-#define AFSTOV(vc) ((vc)->v)
-#else
-#define VTOAFS(V) ((struct vcache *)(V))
-#define AFSTOV(V) (&(V)->v)
-#endif
-
-#ifdef AFS_LINUX22_ENV
-#define ITOAFS(V) ((struct vcache*)(V))
-#define AFSTOI(V) (struct inode *)(&(V)->v)
-#endif
-
-/* INVARIANTs: (vlruq.next != NULL) == (vlruq.prev != NULL)
- * nextfree => !vlruq.next && ! vlruq.prev
- * !(avc->nextfree) && !avc->vlruq.next => (FreeVCList == avc->nextfree)
- */
-struct vcache {
-#if defined(AFS_XBSD_ENV)
- struct vnode *v;
-#else
- struct vnode v; /* Has reference count in v.v_count */
-#endif
- struct afs_q vlruq; /* lru q next and prev */
- struct vcache *nextfree; /* next on free list (if free) */
- struct vcache *hnext; /* Hash next */
- struct VenusFid fid;
- struct mstat {
- afs_size_t Length;
- afs_hyper_t DataVersion;
- afs_uint32 Date;
- afs_uint32 Owner;
- afs_uint32 Group;
- ushort Mode; /* XXXX Should be afs_int32 XXXX */
- ushort LinkCount;
- /* vnode type is in v.v_type */
- } m;
- afs_rwlock_t lock; /* The lock on the vcache contents. */
-#if defined(AFS_SUN5_ENV)
- /* Lock used to protect the activeV, multipage, and vstates fields.
- * Do not try to get the vcache lock when the vlock is held */
- afs_rwlock_t vlock;
-#endif /* defined(AFS_SUN5_ENV) */
-#if defined(AFS_SUN5_ENV)
- krwlock_t rwlock;
- struct cred *credp;
-#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- afs_bozoLock_t pvnLock; /* see locks.x */
-#endif
-#ifdef AFS_AIX32_ENV
- afs_lock_t pvmlock;
- vmhandle_t vmh;
-#if defined(AFS_AIX51_ENV)
- vmid_t segid;
-#else
- int segid;
-#endif
- struct ucred *credp;
-#endif
-#ifdef AFS_AIX_ENV
- int ownslock; /* pid of owner of excl lock, else 0 - defect 3083 */
-#endif
-#ifdef AFS_DARWIN_ENV
- struct lock__bsd__ rwlock;
-#endif
-#ifdef AFS_XBSD_ENV
- struct lock rwlock;
-#endif
- afs_int32 parentVnode; /* Parent dir, if a file. */
- afs_int32 parentUnique;
- struct VenusFid *mvid; /* Either parent dir (if root) or root (if mt pt) */
- char *linkData; /* Link data if a symlink. */
- afs_hyper_t flushDV; /* data version last flushed from text */
- afs_hyper_t mapDV; /* data version last flushed from map */
- afs_size_t truncPos; /* truncate file to this position at next store */
- struct server *callback; /* The callback host, if any */
- afs_uint32 cbExpires; /* time the callback expires */
- struct afs_q callsort; /* queue in expiry order, sort of */
- struct axscache *Access; /* a list of cached access bits */
- afs_int32 anyAccess; /* System:AnyUser's access to this. */
- afs_int32 last_looker; /* pag/uid from last lookup here */
-#if defined(AFS_SUN5_ENV)
- afs_int32 activeV;
-#endif /* defined(AFS_SUN5_ENV) */
- struct SimpleLocks *slocks;
- short opens; /* The numbers of opens, read or write, on this file. */
- short execsOrWriters; /* The number of execs (if < 0) or writers (if > 0) of
- * this file. */
- short flockCount; /* count of flock readers, or -1 if writer */
- char mvstat; /* 0->normal, 1->mt pt, 2->root. */
- afs_uint32 states; /* state bits */
-#if defined(AFS_SUN5_ENV)
- afs_uint32 vstates; /* vstate bits */
-#endif /* defined(AFS_SUN5_ENV) */
- struct vtodc quick;
- afs_uint32 symhintstamp;
- union {
- struct vcache *symhint;
- struct dcache *dchint;
- } h1;
-#ifdef AFS_LINUX22_ENV
- u_short flushcnt; /* Number of flushes which haven't released yet. */
- u_short mapcnt; /* Number of mappings of this file. */
-#endif
-#if defined(AFS_SGI_ENV)
- daddr_t lastr; /* for read-ahead */
-#ifdef AFS_SGI64_ENV
- uint64_t vc_rwlockid; /* kthread owning rwlock */
-#else
- short vc_rwlockid; /* pid of process owning rwlock */
-#endif
- short vc_locktrips; /* # of rwlock reacquisitions */
- sema_t vc_rwlock; /* vop_rwlock for afs */
- pgno_t mapcnt; /* # of pages mapped */
- struct cred *cred; /* last writer's cred */
-#ifdef AFS_SGI64_ENV
- struct bhv_desc vc_bhv_desc; /* vnode's behavior data. */
-#endif
-#endif /* AFS_SGI_ENV */
- afs_int32 vc_error; /* stash write error for this vnode. */
- int xlatordv; /* Used by nfs xlator */
- struct AFS_UCRED *uncred;
- int asynchrony; /* num kbytes to store behind */
-#ifdef AFS_SUN5_ENV
- short multiPage; /* count of multi-page getpages in progress */
-#endif
-};
-
-#define afs_symhint_inval(avc)
-
-
-#define DONT_CHECK_MODE_BITS 0
-#define CHECK_MODE_BITS 1
-#define CMB_ALLOW_EXEC_AS_READ 2 /* For the NFS xlator */
-
-#if defined(AFS_SGI_ENV)
-#define AVCRWLOCK(avc) (valusema(&(avc)->vc_rwlock) <= 0)
-
-/* SGI vnode rwlock macros and flags. */
-#ifndef AFS_SGI62_ENV
-/* The following are defined here. SGI 6.2 declares them in vnode.h */
-#define VRWLOCK_READ 0
-#define VRWLOCK_WRITE 1
-#define VRWLOCK_WRITE_DIRECT 2
-#endif
-
-#ifdef AFS_SGI53_ENV
-#ifdef AFS_SGI62_ENV
-#define AFS_RWLOCK_T vrwlock_t
-#else
-#define AFS_RWLOCK_T int
-#endif /* AFS_SGI62_ENV */
-#ifdef AFS_SGI64_ENV
-#include <ksys/behavior.h>
-#define AFS_RWLOCK(V,F) \
- afs_rwlock(&VTOAFS(V)->vc_bhv_desc, (F));
-#define AFS_RWUNLOCK(V,F) \
- afs_rwunlock(&VTOAFS(V)->vc_bhv_desc, (F));
-
-#else
-#define AFS_RWLOCK(V,F) afs_rwlock((vnode_t *)(V), (F) )
-#define AFS_RWUNLOCK(V,F) afs_rwunlock((vnode_t *)(V), (F) )
-#endif
-#else /* AFS_SGI53_ENV */
-#define AFS_RWLOCK(V,F) afs_rwlock((V))
-#define AFS_RWUNLOCK(V,F) afs_rwunlock((V))
-#endif /* AFS_SGI53_ENV */
-#endif /* AFS_SGI_ENV */
-
-struct vcxstat {
- struct VenusFid fid;
- afs_hyper_t DataVersion;
- afs_rwlock_t lock;
- afs_int32 parentVnode;
- afs_int32 parentUnique;
- afs_hyper_t flushDV;
- afs_hyper_t mapDV;
- afs_int32 truncPos;
- afs_int32 randomUid[CPSIZE];
- afs_int32 callback; /* Now a pointer to 'server' struct */
- afs_int32 cbExpires;
- afs_int32 randomAccess[CPSIZE];
- afs_int32 anyAccess;
- short opens;
- short execsOrWriters;
- short flockCount;
- char mvstat;
- afs_uint32 states;
-};
-
-struct sbstruct {
- int sb_thisfile;
- int sb_default;
-};
-
-/* CM inititialization parameters. What CM actually used after calculations
- * based on passed in arguments.
- */
-#define CMI_VERSION 1 /* increment when adding new fields. */
-struct cm_initparams {
- int cmi_version;
- int cmi_nChunkFiles;
- int cmi_nStatCaches;
- int cmi_nDataCaches;
- int cmi_nVolumeCaches;
- int cmi_firstChunkSize;
- int cmi_otherChunkSize;
- int cmi_cacheSize; /* The original cache size, in 1K blocks. */
- unsigned cmi_setTime:1;
- unsigned cmi_memCache:1;
- int spare[16 - 9]; /* size of struct is 16 * 4 = 64 bytes */
-};
-
-
-/*----------------------------------------------------------------------
- * AFS Data cache definitions
- *
- * Each entry describes a Unix file on the local disk that is
- * is serving as a cached copy of all or part of a Vice file.
- * Entries live in circular queues for each hash table slot
- *
- * Which queue is this thing in? Good question.
- * A struct dcache entry is in the freeDSlot queue when not associated with a cache slot (file).
- * Otherwise, it is in the DLRU queue. The freeDSlot queue uses the lruq.next field as
- * its "next" pointer.
- *
- * Cache entries in the DLRU queue are either associated with vice files, in which case
- * they are hashed by afs_dvnextTbl and afs_dcnextTbl pointers, or they are in the freeDCList
- * and are not associated with any vice file. This last list uses the afs_dvnextTbl pointer for
- * its "next" pointer.
- *----------------------------------------------------------------------*/
-
-#define NULLIDX (-1) /* null index definition */
-/* struct dcache states bits */
-#define DWriting 8 /* file being written (used for cache validation) */
-
-/* dcache data flags */
-#define DFEntryMod 0x02 /* has entry itself been modified? */
-#define DFFetching 0x04 /* file is currently being fetched */
-
-/* dcache meta flags */
-#define DFNextStarted 0x01 /* next chunk has been prefetched already */
-#define DFFetchReq 0x10 /* someone is waiting for DFFetching to go on */
-
-
-/* flags in afs_indexFlags array */
-#define IFEverUsed 1 /* index entry has >= 1 byte of data */
-#define IFFree 2 /* index entry in freeDCList */
-#define IFDataMod 4 /* file needs to be written out */
-#define IFFlag 8 /* utility flag */
-#define IFDirtyPages 16
-#define IFAnyPages 32
-#define IFDiscarded 64 /* index entry in discardDCList */
-
-struct afs_ioctl {
- char *in; /* input buffer */
- char *out; /* output buffer */
- short in_size; /* Size of input buffer <= 2K */
- short out_size; /* Maximum size of output buffer, <= 2K */
-};
-
-/*
- * This version of afs_ioctl is required to pass in 32 bit user space
- * pointers into a 64 bit kernel.
- */
-
-struct afs_ioctl32 {
- unsigned int in;
- unsigned int out;
- short in_size;
- short out_size;
-};
-
-
-/* CacheItems file has a header of type struct afs_fheader
- * (keep aligned properly). Since we already have sgi_62 clients running
- * with a 32 bit inode, a change is required to the header so that
- * they can distinguish the old 32 bit inode CacheItems file and zap it
- * instead of using it.
- */
-struct afs_fheader {
-#define AFS_FHMAGIC 0x7635abaf /* uses version number */
- afs_int32 magic;
-#if defined(AFS_SUN57_64BIT_ENV)
-#define AFS_CI_VERSION 3
-#else
-#define AFS_CI_VERSION 2
-#endif
- afs_int32 version;
- afs_int32 firstCSize;
- afs_int32 otherCSize;
-};
-
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_64BIT_ENV)
-/* Using ino64_t here so that user level debugging programs compile
- * the size correctly.
- */
-#define afs_inode_t ino64_t
-#else
-#if defined(AFS_LINUX_64BIT_KERNEL)
-#define afs_inode_t long
-#else
-#if defined(AFS_AIX51_ENV) || defined(AFS_HPUX1123_ENV)
-#define afs_inode_t ino_t
-#else
-#define afs_inode_t afs_int32
-#endif
-#endif
-#endif
-
-/* kept on disk and in dcache entries */
-struct fcache {
- struct VenusFid fid; /* Fid for this file */
- afs_int32 modTime; /* last time this entry was modified */
- afs_hyper_t versionNo; /* Associated data version number */
- afs_int32 chunk; /* Relative chunk number */
- afs_inode_t inode; /* Unix inode for this chunk */
- afs_int32 chunkBytes; /* Num bytes in this chunk */
- char states; /* Has this chunk been modified? */
-};
-
-/* magic numbers to specify the cache type */
-
-#define AFS_FCACHE_TYPE_UFS 0x0
-#define AFS_FCACHE_TYPE_MEM 0x1
-#define AFS_FCACHE_TYPE_NFS 0x2
-#define AFS_FCACHE_TYPE_EPI 0x3
-
-/* kept in memory */
-struct dcache {
- struct afs_q lruq; /* Free queue for in-memory images */
- struct afs_q dirty; /* Queue of dirty entries that need written */
- afs_rwlock_t lock; /* Protects validPos, some f */
- afs_rwlock_t tlock; /* Atomizes updates to refCount */
- afs_rwlock_t mflock; /* Atomizes accesses/updates to mflags */
- afs_size_t validPos; /* number of valid bytes during fetch */
- afs_int32 index; /* The index in the CacheInfo file */
- short refCount; /* Associated reference count. */
- char dflags; /* Data flags */
- char mflags; /* Meta flags */
- struct fcache f; /* disk image */
- afs_int32 stamp; /* used with vtodc struct for hints */
-
- /*
- * Locking rules:
- *
- * dcache.lock protects the actual contents of the cache file (in
- * f.inode), subfields of f except those noted below, dflags and
- * validPos.
- *
- * dcache.tlock is used to make atomic updates to refCount. Zero
- * refCount dcache entries are protected by afs_xdcache instead of
- * tlock.
- *
- * dcache.mflock is used to access and update mflags. It cannot be
- * held without holding the corresponding dcache.lock. Updating
- * mflags requires holding dcache.lock(R) and dcache.mflock(W), and
- * checking for mflags requires dcache.lock(R) and dcache.mflock(R).
- * Note that dcache.lock(W) gives you the right to update mflags,
- * as dcache.mflock(W) can only be held with dcache.lock(R).
- *
- * dcache.stamp is protected by the associated vcache lock, because
- * it's only purpose is to establish correspondence between vcache
- * and dcache entries.
- *
- * dcache.index, dcache.f.fid, dcache.f.chunk and dcache.f.inode are
- * write-protected by afs_xdcache and read-protected by refCount.
- * Once an entry is referenced, these values cannot change, and if
- * it's on the free list (with refCount=0), it can be reused for a
- * different file/chunk. These values can only be written while
- * holding afs_xdcache(W) and allocating this dcache entry (thereby
- * ensuring noone else has a refCount on it).
- */
-};
-/* this is obsolete and should be removed */
-#define ihint stamp
-
-/* macro to mark a dcache entry as bad */
-#define ZapDCE(x) \
- do { \
- (x)->f.fid.Fid.Unique = 0; \
- afs_indexUnique[(x)->index] = 0; \
- (x)->dflags |= DFEntryMod; \
- } while(0)
-
-/* FakeOpen and Fake Close used to be real subroutines. They're only used in
- * sun_subr and afs_vnodeops, and they're very frequently called, so I made
- * them into macros. They do:
- * FakeOpen: fake the file being open for writing. avc->lock must be held
- * in write mode. Having the file open for writing is like having a DFS
- * write-token: you're known to have the best version of the data around,
- * and so the CM won't let it be overwritten by random server info.
- * FakeClose: undo the effects of FakeOpen, noting that we want to ensure
- * that a real close eventually gets done. We use CCore to achieve this if
- * we would end up closing the file. avc->lock must be held in write mode */
-
-#ifdef AFS_AIX_IAUTH_ENV
-#define CRKEEP(V, C) (V)->linkData = (char*)crdup((C))
-#else
-#define CRKEEP(V, C) crhold((C)); (V)->linkData = (char*)(C)
-#endif
-
-#define afs_FakeOpen(avc) { avc->opens++; avc->execsOrWriters++; }
-#define afs_FakeClose(avc, acred) \
-{ if (avc->execsOrWriters == 1) { \
- /* we're the last writer, just use CCore flag */ \
- avc->states |= CCore; /* causes close to be called later */ \
- \
- /* The cred and vnode holds will be released in afs_FlushActiveVcaches */ \
- VN_HOLD(AFSTOV(avc)); /* So it won't disappear */ \
- CRKEEP(avc, acred); /* Should use a better place for the creds */ \
- } \
- else { \
- /* we're not the last writer, let the last one do the store-back for us */ \
- avc->opens--; \
- avc->execsOrWriters--; \
- } \
-}
-
-#define AFS_ZEROS 64 /* zero buffer */
-
-/*#define afs_DirtyPages(avc) (((avc)->states & CDirty) || osi_VMDirty_p((avc)))*/
-#define afs_DirtyPages(avc) ((avc)->states & CDirty)
-
-/* The PFlush algorithm makes use of the fact that Fid.Unique is not used in
- below hash algorithms. Change it if need be so that flushing algorithm
- doesn't move things from one hash chain to another
-*/
-/* extern int afs_dhashsize; */
-#define DCHash(v, c) ((((v)->Fid.Vnode + (v)->Fid.Volume + (c))) & (afs_dhashsize-1))
- /*Vnode, Chunk -> Hash table index */
-#define DVHash(v) ((((v)->Fid.Vnode + (v)->Fid.Volume )) & (afs_dhashsize-1))
- /*Vnode -> Other hash table index */
-/* don't hash on the cell, our callback-breaking code sometimes fails to compute
- the cell correctly, and only scans one hash bucket */
-#define VCHash(fid) (((fid)->Fid.Volume + (fid)->Fid.Vnode) & (VCSIZE-1))
-
-extern struct dcache **afs_indexTable; /*Pointers to in-memory dcache entries */
-extern afs_int32 *afs_indexUnique; /*dcache entry Fid.Unique */
-extern afs_int32 *afs_dvnextTbl; /*Dcache hash table links */
-extern afs_int32 *afs_dcnextTbl; /*Dcache hash table links */
-extern afs_int32 afs_cacheFiles; /*Size of afs_indexTable */
-extern afs_int32 afs_cacheBlocks; /*1K blocks in cache */
-extern afs_int32 afs_cacheStats; /*Stat entries in cache */
-extern struct vcache *afs_vhashT[VCSIZE]; /*Stat cache hash table */
-extern afs_int32 afs_initState; /*Initialization state */
-extern afs_int32 afs_termState; /* Termination state */
-extern struct VenusFid afs_rootFid; /*Root for whole file system */
-extern afs_int32 afs_allCBs; /* Count of callbacks */
-extern afs_int32 afs_oddCBs; /* Count of odd callbacks */
-extern afs_int32 afs_evenCBs; /* Count of even callbacks */
-extern afs_int32 afs_allZaps; /* Count of fid deletes */
-extern afs_int32 afs_oddZaps; /* Count of odd fid deletes */
-extern afs_int32 afs_evenZaps; /* Count of even fid deletes */
-extern struct brequest afs_brs[NBRS]; /* request structures */
-
-#define UHash(auid) ((auid) & (NUSERS-1))
-#define VHash(avol) ((avol)&(NVOLS-1))
-#define SHash(aserv) ((ntohl(aserv)) & (NSERVERS-1))
-#define FVHash(acell,avol) (((avol)+(acell)) & (NFENTRIES-1))
-
-/* Performance hack - we could replace VerifyVCache2 with the appropriate
- * GetVCache incantation, and could eliminate even this code from afs_UFSRead
- * by making intentionally invalidating quick.stamp in the various callbacks
- * expiration/breaking code */
-#ifdef AFS_LINUX20_ENV
-#define afs_VerifyVCache(avc, areq) \
- (((avc)->states & CStatd) ? (vcache2inode(avc), 0) : \
- afs_VerifyVCache2((avc),areq))
-#else
-#ifdef AFS_DARWIN_ENV
-#define afs_VerifyVCache(avc, areq) \
- (((avc)->states & CStatd) ? (osi_VM_Setup(avc, 0), 0) : \
- afs_VerifyVCache2((avc),areq))
-#else
-#define afs_VerifyVCache(avc, areq) \
- (((avc)->states & CStatd) ? 0 : afs_VerifyVCache2((avc),areq))
-#endif
-#endif
-
-#define DO_STATS 1 /* bits used by FindVCache */
-#define DO_VLRU 2
-
-/* values for flag param of afs_CheckVolumeNames */
-#define AFS_VOLCHECK_EXPIRED 0x1 /* volumes whose callbacks have expired */
-#define AFS_VOLCHECK_BUSY 0x2 /* volumes which were marked busy */
-#define AFS_VOLCHECK_MTPTS 0x4 /* mount point invalidation also */
-#define AFS_VOLCHECK_FORCE 0x8 /* do all forcibly */
-
-#endif /* KERNEL */
-
-#define AFS_FSPORT ((unsigned short) htons(7000))
-#define AFS_VLPORT ((unsigned short) htons(7003))
-
-#define afs_read(avc, uio, acred, albn, abpp, nolock) \
- (*(afs_cacheType->vread))(avc, uio, acred, albn, abpp, nolock)
-#define afs_write(avc, uio, aio, acred, nolock) \
- (*(afs_cacheType->vwrite))(avc, uio, aio, acred, nolock)
-
-#define afs_rdwr(avc, uio, rw, io, cred) \
- (((rw) == UIO_WRITE) ? afs_write(avc, uio, io, cred, 0) : afs_read(avc, uio, cred, 0, 0, 0))
-#define afs_nlrdwr(avc, uio, rw, io, cred) \
- (((rw) == UIO_WRITE) ? afs_write(avc, uio, io, cred, 1) : afs_read(avc, uio, cred, 0, 0, 1))
-
-/* Cache size truncation uses the following low and high water marks:
- * If the cache is more than 95% full (CM_DCACHECOUNTFREEPCT), the cache
- * truncation daemon is awakened and will free up space until the cache is 85%
- * (CM_DCACHESPACEFREEPCT - CM_DCACHEEXTRAPCT) full.
- * afs_UFSWrite and afs_GetDCache (when it needs to fetch data) will wait on
- * afs_WaitForCacheDrain if the cache is 98% (CM_WAITFORDRAINPCT) full.
- * afs_GetDownD wakes those processes once the cache is 95% full
- * (CM_CACHESIZEDRAINEDPCT).
- */
-#define CM_MAXDISCARDEDCHUNKS 16 /* # of chunks */
-#define CM_DCACHECOUNTFREEPCT 95 /* max pct of chunks in use */
-#define CM_DCACHESPACEFREEPCT 90 /* max pct of space in use */
-#define CM_DCACHEEXTRAPCT 5 /* extra to get when freeing */
-#define CM_CACHESIZEDRAINEDPCT 95 /* wakeup processes when down to here. */
-#define CM_WAITFORDRAINPCT 98 /* sleep if cache is this full. */
-
-#define afs_CacheIsTooFull() \
- (afs_blocksUsed - afs_blocksDiscarded > \
- (CM_DCACHECOUNTFREEPCT*afs_cacheBlocks)/100 || \
- afs_freeDCCount - afs_discardDCCount < \
- ((100-CM_DCACHECOUNTFREEPCT)*afs_cacheFiles)/100)
-
-/* Handy max length of a numeric string. */
-#define CVBS 12 /* max afs_int32 is 2^32 ~ 4*10^9, +1 for NULL, +luck */
-
-#define refpanic(foo) if (afs_norefpanic) \
- { printf( foo ); afs_norefpanic++;} else osi_Panic( foo )
-
-/*
-** these are defined in the AIX source code sys/fs_locks.h but are not
-** defined anywhere in the /usr/include directory
-*/
-#if defined(AFS_AIX41_ENV)
-#define VN_LOCK(vp) simple_lock(&(vp)->v_lock)
-#define VN_UNLOCK(vp) simple_unlock(&(vp)->v_lock)
-#endif
-
-/* get a file's serial number from a vnode */
-#ifndef afs_vnodeToInumber
-#if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
-#define afs_vnodeToInumber(V) VnodeToIno(V)
-#else
-#ifdef AFS_DECOSF_ENV
-#define afs_vnodeToInumber(V) osi_vnodeToInumber(V)
-#else
-#define afs_vnodeToInumber(V) (VTOI(V)->i_number)
-#endif /* AFS_DECOSF_ENV */
-#endif /* AFS_SGI62_ENV */
-#endif
-
-/* get a file's device number from a vnode */
-#ifndef afs_vnodeToDev
-#if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
-#define afs_vnodeToDev(V) VnodeToDev(V)
-#elif defined(AFS_DECOSF_ENV)
-#define afs_vnodeToDev(V) osi_vnodeToDev(V)
-#else
-#define afs_vnodeToDev(V) (VTOI(V)->i_dev)
-#endif
-#endif
-
-
-/* Note: this should agree with the definition in kdump.c */
-#if defined(AFS_OSF_ENV)
-#if !defined(UKERNEL)
-#define AFS_USEBUFFERS 1
-#endif
-#endif
-
-#if !defined(UKERNEL) && !defined(HAVE_STRUCT_BUF)
-/* declare something so that prototypes don't flip out */
-/* appears struct buf stuff is only actually passed around as a pointer,
- except with libuafs, in which case it is actually defined */
-
-struct buf;
-#endif
-
-/* fakestat support: opaque storage for afs_EvalFakeStat to remember
- * what vcache should be released.
- */
-struct afs_fakestat_state {
- char valid;
- char did_eval;
- char need_release;
- struct vcache *root_vp;
-};
-
-extern int afs_fakestat_enable;
-
-struct buffer {
- ino_t fid[1]; /* Unique cache key + i/o addressing */
- afs_int32 page;
- afs_int32 accesstime;
- struct buffer *hashNext;
- char *data;
- char lockers;
- char dirty;
- char hashIndex;
-#if AFS_USEBUFFERS
- struct buf *bufp;
-#endif
- afs_rwlock_t lock; /* the lock for this structure */
-};
-
-/* afs_memcache.c */
-struct memCacheEntry {
- int size; /* # of valid bytes in this entry */
- int dataSize; /* size of allocated data area */
- afs_lock_t afs_memLock;
- char *data; /* bytes */
-};
-
-/* First 32 bits of capabilities */
-#define CAPABILITY_ERRORTRANS (1<<0)
-
-#define CAPABILITY_BITS 1
-
-#endif /* _AFS_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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_analyze.c,v 1.22 2003/08/27 21:43:16 rees Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#ifndef UKERNEL
-#if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
-#include <net/if.h>
-#include <netinet/in.h>
-#endif
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif
-#endif /* !UKERNEL */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/afs_util.h"
-#include "afs/unified_afs.h"
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-
-/* shouldn't do it this way, but for now will do */
-#ifndef ERROR_TABLE_BASE_U
-#define ERROR_TABLE_BASE_U (5376L)
-#endif /* ubik error base define */
-
-/* shouldn't do it this way, but for now will do */
-#ifndef ERROR_TABLE_BASE_uae
-#define ERROR_TABLE_BASE_uae (49733376L)
-#endif /* unified afs error base define */
-
-/* same hack for vlserver error base as for ubik error base */
-#ifndef ERROR_TABLE_BASE_VL
-#define ERROR_TABLE_BASE_VL (363520L)
-#define VL_NOENT (363524L)
-#endif /* vlserver error base define */
-
-
-int afs_BusyWaitPeriod = 15; /* poll every 15 seconds */
-
-afs_int32 hm_retry_RO = 0; /* don't wait */
-afs_int32 hm_retry_RW = 0; /* don't wait */
-afs_int32 hm_retry_int = 0; /* don't wait */
-
-static int et2sys[512];
-
-void
-init_et_to_sys_error(void)
-{
- memset(&et2sys, 0, sizeof(et2sys));
- et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
- et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
- et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
- et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
- et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
- et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
- et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
- et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
- et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
- et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
- et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
- et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
- et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
- et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
- et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
- et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
- et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
- et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
- et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
- et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
- et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
- et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
- et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
- et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
- et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
- et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
- et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
- et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
- et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
- et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
- et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
- et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
- et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
- et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
- et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
- et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
- et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
- et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
- et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
- et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
- et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
- et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
- et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
- et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
- et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
- et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
- et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
- et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
- et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
- et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
- et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
- et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
- et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
- et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
- et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
- et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
- et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
- et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
- et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
- et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
- et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
- et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
- et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
- et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
- et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
- et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
- et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
- et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
- et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
- et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
- et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
- et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
- et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
- et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
- et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
- et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
- et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
- et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
- et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
- et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
- et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
- et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
- et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
- et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
- et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
- et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
- et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
- et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
- et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
- et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
- et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
- et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
- et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
- et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
- et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
- et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
- et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
- et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
- et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
- et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
- et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
- et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
- et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
- et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
- et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
- et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
- et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
- et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
- et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
- et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
- et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
- et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
- et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
- et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
- et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
- et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
- et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
- et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
- et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
- et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
- et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
- et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
- et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
-}
-
-static afs_int32
-et_to_sys_error(afs_int32 in)
-{
- if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
- return in;
- if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
- return et2sys[in - ERROR_TABLE_BASE_uae];
- return in;
-}
-
-void
-afs_CopyError(register struct vrequest *afrom, register struct vrequest *ato)
-{
- AFS_STATCNT(afs_CopyError);
- if (!afrom->initd)
- return;
- afs_FinalizeReq(ato);
- if (afrom->accessError)
- ato->accessError = 1;
- if (afrom->volumeError)
- ato->volumeError = 1;
- if (afrom->networkError)
- ato->networkError = 1;
- if (afrom->permWriteError)
- ato->permWriteError = 1;
-
-}
-
-void
-afs_FinalizeReq(register struct vrequest *areq)
-{
- AFS_STATCNT(afs_FinalizeReq);
- if (areq->initd)
- return;
- areq->busyCount = 0;
- areq->accessError = 0;
- areq->volumeError = 0;
- areq->networkError = 0;
- areq->permWriteError = 0;
- areq->initd = 1;
-
-}
-
-int
-afs_CheckCode(afs_int32 acode, struct vrequest *areq, int where)
-{
- AFS_STATCNT(afs_CheckCode);
- if (acode) {
- afs_Trace2(afs_iclSetp, CM_TRACE_CHECKCODE, ICL_TYPE_INT32, acode,
- ICL_TYPE_INT32, where);
- }
- if ((acode & ~0xff) == ERROR_TABLE_BASE_uae)
- acode = et_to_sys_error(acode);
- if (!areq || !areq->initd)
- return acode;
- if (areq->networkError)
- return ETIMEDOUT;
- if (acode == 0)
- return 0;
- if (areq->accessError)
- return EACCES;
- if (areq->volumeError == VOLMISSING)
- return ENODEV;
- if (areq->volumeError == VOLBUSY)
- return EWOULDBLOCK;
- if (acode == VNOVNODE)
- return ENOENT;
- if (acode == VDISKFULL)
- return ENOSPC;
- if (acode == VOVERQUOTA)
- return
-#ifdef EDQUOT
- EDQUOT
-#else
- ENOSPC
-#endif
- ;
-
- return acode;
-
-} /*afs_CheckCode */
-
-
-#define VSleep(at) afs_osi_Wait((at)*1000, 0, 0)
-
-
-int lastcode;
-/* returns:
- * 0 if the vldb record for a specific volume is different from what
- * we have cached -- perhaps the volume has moved.
- * 1 if the vldb record is the same
- * 2 if we can't tell if it's the same or not.
- *
- * If 0, the caller will probably start over at the beginning of our
- * list of servers for this volume and try to find one that is up. If
- * not 0, we will probably just keep plugging with what we have
- * cached. If we fail to contact the VL server, we should just keep
- * trying with the information we have, rather than failing. */
-#define DIFFERENT 0
-#define SAME 1
-#define DUNNO 2
-static int
-VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
-{
- struct vrequest treq;
- struct conn *tconn;
- int i, type = 0;
- union {
- struct vldbentry tve;
- struct nvldbentry ntve;
- struct uvldbentry utve;
- } *v;
- struct volume *tvp;
- struct cell *tcell;
- char *bp, tbuf[CVBS]; /* biggest volume id is 2^32, ~ 4*10^9 */
- unsigned int changed;
- struct server *(oldhosts[NMAXNSERVERS]);
-
- AFS_STATCNT(CheckVLDB);
- afs_FinalizeReq(areq);
-
- if ((i = afs_InitReq(&treq, afs_osi_credp)))
- return DUNNO;
- v = afs_osi_Alloc(sizeof(*v));
- tcell = afs_GetCell(afid->Cell, READ_LOCK);
- bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
- do {
- VSleep(2); /* Better safe than sorry. */
- tconn =
- afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
- &treq, SHARED_LOCK);
- if (tconn) {
- if (tconn->srvr->server->flags & SNO_LHOSTS) {
- type = 0;
- RX_AFS_GUNLOCK();
- i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
- RX_AFS_GLOCK();
- } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
- type = 1;
- RX_AFS_GUNLOCK();
- i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
- RX_AFS_GLOCK();
- } else {
- type = 2;
- RX_AFS_GUNLOCK();
- i = VL_GetEntryByNameU(tconn->id, bp, &v->utve);
- RX_AFS_GLOCK();
- if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
- if (i == RXGEN_OPCODE) {
- type = 1;
- RX_AFS_GUNLOCK();
- i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
- RX_AFS_GLOCK();
- if (i == RXGEN_OPCODE) {
- type = 0;
- tconn->srvr->server->flags |= SNO_LHOSTS;
- RX_AFS_GUNLOCK();
- i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
- RX_AFS_GLOCK();
- } else if (!i)
- tconn->srvr->server->flags |= SYES_LHOSTS;
- } else if (!i)
- tconn->srvr->server->flags |= SVLSRV_UUID;
- }
- lastcode = i;
- }
- } else
- i = -1;
- } while (afs_Analyze(tconn, i, NULL, &treq, -1, /* no op code for this */
- SHARED_LOCK, tcell));
-
- afs_PutCell(tcell, READ_LOCK);
- afs_Trace2(afs_iclSetp, CM_TRACE_CHECKVLDB, ICL_TYPE_FID, &afid,
- ICL_TYPE_INT32, i);
-
- if (i) {
- afs_osi_Free(v, sizeof(*v));
- return DUNNO;
- }
- /* have info, copy into serverHost array */
- changed = 0;
- tvp = afs_FindVolume(afid, WRITE_LOCK);
- if (tvp) {
- ObtainWriteLock(&tvp->lock, 107);
- for (i = 0; i < NMAXNSERVERS && tvp->serverHost[i]; i++) {
- oldhosts[i] = tvp->serverHost[i];
- }
-
- if (type == 2) {
- InstallUVolumeEntry(tvp, &v->utve, afid->Cell, tcell, &treq);
- } else if (type == 1) {
- InstallNVolumeEntry(tvp, &v->ntve, afid->Cell);
- } else {
- InstallVolumeEntry(tvp, &v->tve, afid->Cell);
- }
-
- if (i < NMAXNSERVERS && tvp->serverHost[i]) {
- changed = 1;
- }
- for (--i; !changed && i >= 0; i--) {
- if (tvp->serverHost[i] != oldhosts[i]) {
- changed = 1; /* also happens if prefs change. big deal. */
- }
- }
-
- ReleaseWriteLock(&tvp->lock);
- afs_PutVolume(tvp, WRITE_LOCK);
- } else { /* can't find volume */
- tvp = afs_GetVolume(afid, &treq, WRITE_LOCK);
- if (tvp) {
- afs_PutVolume(tvp, WRITE_LOCK);
- afs_osi_Free(v, sizeof(*v));
- return DIFFERENT;
- } else {
- afs_osi_Free(v, sizeof(*v));
- return DUNNO;
- }
- }
-
- afs_osi_Free(v, sizeof(*v));
- return (changed ? DIFFERENT : SAME);
-} /*VLDB_Same */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED afs_Analyze
- *
- * Description:
- * Analyze the outcome of an RPC operation, taking whatever support
- * actions are necessary.
- *
- * Arguments:
- * aconn : Ptr to the relevant connection on which the call was made.
- * acode : The return code experienced by the RPC.
- * afid : The FID of the file involved in the action. This argument
- * may be null if none was involved.
- * areq : The request record associated with this operation.
- * op : which RPC we are analyzing.
- * cellp : pointer to a cell struct. Must provide either fid or cell.
- *
- * Returns:
- * Non-zero value if the related RPC operation should be retried,
- * zero otherwise.
- *
- * Environment:
- * This routine is typically called in a do-while loop, causing the
- * embedded RPC operation to be called repeatedly if appropriate
- * until whatever error condition (if any) is intolerable.
- *
- * Side Effects:
- * As advertised.
- *
- * NOTE:
- * The retry return value is used by afs_StoreAllSegments to determine
- * if this is a temporary or permanent error.
- *------------------------------------------------------------------------*/
-int
-afs_Analyze(register struct conn *aconn, afs_int32 acode,
- struct VenusFid *afid, register struct vrequest *areq, int op,
- afs_int32 locktype, struct cell *cellp)
-{
- afs_int32 i;
- struct srvAddr *sa;
- struct server *tsp;
- struct volume *tvp;
- afs_int32 shouldRetry = 0;
- struct afs_stats_RPCErrors *aerrP;
-
- AFS_STATCNT(afs_Analyze);
- afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
- ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
- areq->uid);
-
- aerrP = (struct afs_stats_RPCErrors *)0;
-
- if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
- aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
-
- afs_FinalizeReq(areq);
- if (!aconn && areq->busyCount) { /* one RPC or more got VBUSY/VRESTARTING */
-
- tvp = afs_FindVolume(afid, READ_LOCK);
- if (tvp) {
- afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
- (afid ? afid->Fid.Volume : 0),
- (tvp->name ? tvp->name : ""),
- ((tvp->serverHost[0]
- && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
- cell->cellName : ""));
-
- for (i = 0; i < MAXHOSTS; i++) {
- if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
- tvp->status[i] = not_busy;
- }
- if (tvp->status[i] == not_busy)
- shouldRetry = 1;
- }
- afs_PutVolume(tvp, READ_LOCK);
- } else {
- afs_warnuser("afs: Waiting for busy volume %u\n",
- (afid ? afid->Fid.Volume : 0));
- }
-
- if (areq->busyCount > 100) {
- if (aerrP)
- (aerrP->err_Volume)++;
- areq->volumeError = VOLBUSY;
- shouldRetry = 0;
- } else {
- VSleep(afs_BusyWaitPeriod); /* poll periodically */
- }
- if (shouldRetry != 0)
- areq->busyCount++;
-
- return shouldRetry; /* should retry */
- }
-
- if (!aconn) {
- if (!areq->volumeError) {
- if (aerrP)
- (aerrP->err_Network)++;
- if (hm_retry_int && !(areq->flags & O_NONBLOCK) && /* "hard" mount */
- ((afid && afs_IsPrimaryCellNum(afid->Cell))
- || (cellp && afs_IsPrimaryCell(cellp)))) {
- if (!afid) {
- afs_warnuser
- ("afs: hard-mount waiting for a vlserver to return to service\n");
- VSleep(hm_retry_int);
- afs_CheckServers(1, cellp);
- shouldRetry = 1;
- } else {
- tvp = afs_FindVolume(afid, READ_LOCK);
- if (!tvp || (tvp->states & VRO)) {
- shouldRetry = hm_retry_RO;
- } else {
- shouldRetry = hm_retry_RW;
- }
- if (tvp)
- afs_PutVolume(tvp, READ_LOCK);
- if (shouldRetry) {
- afs_warnuser
- ("afs: hard-mount waiting for volume %u\n",
- afid->Fid.Volume);
- VSleep(hm_retry_int);
- afs_CheckServers(1, cellp);
- }
- }
- } /* if (hm_retry_int ... */
- else {
- areq->networkError = 1;
- }
- }
- return shouldRetry;
- }
-
- /* Find server associated with this connection. */
- sa = aconn->srvr;
- tsp = sa->server;
-
- /* Before we do anything with acode, make sure we translate it back to
- * a system error */
- if ((acode & ~0xff) == ERROR_TABLE_BASE_uae)
- acode = et_to_sys_error(acode);
-
- if (acode == 0) {
- /* If we previously took an error, mark this volume not busy */
- if (areq->volumeError) {
- tvp = afs_FindVolume(afid, READ_LOCK);
- if (tvp) {
- for (i = 0; i < MAXHOSTS; i++) {
- if (tvp->serverHost[i] == tsp) {
- tvp->status[i] = not_busy;
- }
- }
- afs_PutVolume(tvp, READ_LOCK);
- }
- }
-
- afs_PutConn(aconn, locktype);
- return 0;
- }
-
- /* If network troubles, mark server as having bogued out again. */
- /* VRESTARTING is < 0 because of backward compatibility issues
- * with 3.4 file servers and older cache managers */
-#ifdef AFS_64BIT_CLIENT
- if (acode == -455)
- acode = 455;
-#endif /* AFS_64BIT_CLIENT */
- if ((acode < 0) && (acode != VRESTARTING)) {
- afs_ServerDown(sa);
- ForceNewConnections(sa); /*multi homed clients lock:afs_xsrvAddr? */
- if (aerrP)
- (aerrP->err_Server)++;
- }
-
- if (acode == VBUSY || acode == VRESTARTING) {
- if (acode == VBUSY) {
- areq->busyCount++;
- if (aerrP)
- (aerrP->err_VolumeBusies)++;
- } else
- areq->busyCount = 1;
-
- tvp = afs_FindVolume(afid, READ_LOCK);
- if (tvp) {
- for (i = 0; i < MAXHOSTS; i++) {
- if (tvp->serverHost[i] == tsp) {
- tvp->status[i] = rdwr_busy; /* can't tell which yet */
- /* to tell which, have to look at the op code. */
- }
- }
- afs_PutVolume(tvp, READ_LOCK);
- } else {
- afs_warnuser("afs: Waiting for busy volume %u in cell %s\n",
- (afid ? afid->Fid.Volume : 0), tsp->cell->cellName);
- VSleep(afs_BusyWaitPeriod); /* poll periodically */
- }
- shouldRetry = 1;
- acode = 0;
- } else if (acode == VICETOKENDEAD
- || (acode & ~0xff) == ERROR_TABLE_BASE_RXK) {
- /* any rxkad error is treated as token expiration */
- struct unixuser *tu;
-
- /*
- * I'm calling these errors protection errors, since they involve
- * faulty authentication.
- */
- if (aerrP)
- (aerrP->err_Protection)++;
-
- tu = afs_FindUser(areq->uid, tsp->cell->cellNum, READ_LOCK);
- if (tu) {
- if ((acode == VICETOKENDEAD) || (acode == RXKADEXPIRED))
- afs_warnuser
- ("afs: Tokens for user of AFS id %d for cell %s have expired\n",
- tu->vid, aconn->srvr->server->cell->cellName);
- else
- afs_warnuser
- ("afs: Tokens for user of AFS id %d for cell %s are discarded (rxkad error=%d)\n",
- tu->vid, aconn->srvr->server->cell->cellName, acode);
- afs_PutUser(tu, READ_LOCK);
- } else {
- /* The else case shouldn't be possible and should probably be replaced by a panic? */
- if ((acode == VICETOKENDEAD) || (acode == RXKADEXPIRED))
- afs_warnuser
- ("afs: Tokens for user %d for cell %s have expired\n",
- areq->uid, aconn->srvr->server->cell->cellName);
- else
- afs_warnuser
- ("afs: Tokens for user %d for cell %s are discarded (rxkad error = %d)\n",
- areq->uid, aconn->srvr->server->cell->cellName, acode);
- }
- aconn->forceConnectFS = 0; /* don't check until new tokens set */
- aconn->user->states |= UTokensBad;
- shouldRetry = 1; /* Try again (as root). */
- }
- /* Check for access violation. */
- else if (acode == EACCES) {
- /* should mark access error in non-existent per-user global structure */
- if (aerrP)
- (aerrP->err_Protection)++;
- areq->accessError = 1;
- if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
- areq->permWriteError = 1;
- shouldRetry = 0;
- }
- /* check for ubik errors; treat them like crashed servers */
- else if (acode >= ERROR_TABLE_BASE_U && acode < ERROR_TABLE_BASE_U + 255) {
- afs_ServerDown(sa);
- if (aerrP)
- (aerrP->err_Server)++;
- shouldRetry = 1; /* retryable (maybe one is working) */
- VSleep(1); /* just in case */
- }
- /* Check for bad volume data base / missing volume. */
- else if (acode == VSALVAGE || acode == VOFFLINE || acode == VNOVOL
- || acode == VNOSERVICE || acode == VMOVED) {
- struct cell *tcell;
- int same;
-
- shouldRetry = 1;
- areq->volumeError = VOLMISSING;
- if (aerrP)
- (aerrP->err_Volume)++;
- if (afid && (tcell = afs_GetCell(afid->Cell, 0))) {
- same = VLDB_Same(afid, areq);
- tvp = afs_FindVolume(afid, READ_LOCK);
- if (tvp) {
- for (i = 0; i < MAXHOSTS && tvp->serverHost[i]; i++) {
- if (tvp->serverHost[i] == tsp) {
- if (tvp->status[i] == end_not_busy)
- tvp->status[i] = offline;
- else
- tvp->status[i]++;
- } else if (!same) {
- tvp->status[i] = not_busy; /* reset the others */
- }
- }
- afs_PutVolume(tvp, READ_LOCK);
- }
- }
- } else if (acode >= ERROR_TABLE_BASE_VL && acode <= ERROR_TABLE_BASE_VL + 255) { /* vlserver errors */
- shouldRetry = 0;
- areq->volumeError = VOLMISSING;
- } else if (acode >= 0) {
- if (aerrP)
- (aerrP->err_Other)++;
- if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
- areq->permWriteError = 1;
- shouldRetry = 0; /* Other random Vice error. */
- } else if (acode == RX_MSGSIZE) { /* same meaning as EMSGSIZE... */
- VSleep(1); /* Just a hack for desperate times. */
- if (aerrP)
- (aerrP->err_Other)++;
- shouldRetry = 1; /* packet was too big, please retry call */
- }
-
- if (acode < 0 && acode != RX_MSGSIZE && acode != VRESTARTING) {
- /* If we get here, code < 0 and we have network/Server troubles.
- * areq->networkError is not set here, since we always
- * retry in case there is another server. However, if we find
- * no connection (aconn == 0) we set the networkError flag.
- */
- afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
- if (aerrP)
- (aerrP->err_Server)++;
- VSleep(1); /* Just a hack for desperate times. */
- shouldRetry = 1;
- }
-
- /* now unlock the connection and return */
- afs_PutConn(aconn, locktype);
- return (shouldRetry);
-} /*afs_Analyze */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_axscache.c,v 1.7 2003/07/15 23:14:11 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/stds.h"
-static struct axscache *afs_axsfreelist = NULL;
-static struct xfreelist {
- struct xfreelist *next;
-} *xfreemallocs = 0;
-static int afs_xaxscnt = 0;
-afs_rwlock_t afs_xaxs;
-
-/* takes an address of an access cache & uid, returns ptr */
-/* PRECONDITION: first field has been checked and doesn't match!
- * INVARIANT: isparent(i,j) ^ isparent(j,i) (ie, they switch around)
- */
-struct axscache *
-afs_SlowFindAxs(struct axscache **cachep, afs_int32 id)
-{
- register struct axscache *i, *j;
-
- j = (*cachep);
- i = j->next;
- while (i) {
- if (i->uid == id) {
- axs_Front(cachep, j, i); /* maintain LRU queue */
- return (i);
- }
-
- if ((j = i->next)) { /* ASSIGNMENT HERE! */
- if (j->uid == id) {
- axs_Front(cachep, i, j);
- return (j);
- }
- } else
- return ((struct axscache *)NULL);
- i = j->next;
- }
- return ((struct axscache *)NULL);
-}
-
-
-#define NAXSs (1000 / sizeof(struct axscache))
-struct axscache *
-axs_Alloc(void)
-{
- register struct axscache *i, *j, *xsp;
- struct axscache *h;
- int k;
-
- ObtainWriteLock(&afs_xaxs, 174);
- if ((h = afs_axsfreelist)) {
- afs_axsfreelist = h->next;
- } else {
- h = i = j =
- (struct axscache *)afs_osi_Alloc(NAXSs * sizeof(struct axscache));
- afs_xaxscnt++;
- xsp = (struct axscache *)xfreemallocs;
- xfreemallocs = (struct xfreelist *)h;
- xfreemallocs->next = (struct xfreelist *)xsp;
- for (k = 0; k < NAXSs - 1; k++, i++) {
- i->uid = -2;
- i->axess = 0;
- i->next = ++j; /* need j because order of evaluation not defined */
- }
- i->uid = -2;
- i->axess = 0;
- i->next = NULL;
- afs_axsfreelist = h->next;
- }
- ReleaseWriteLock(&afs_xaxs);
- return (h);
-}
-
-
-#define axs_Free(axsp) { \
- ObtainWriteLock(&afs_xaxs,175); \
- axsp->next = afs_axsfreelist; \
- afs_axsfreelist = axsp; \
- ReleaseWriteLock(&afs_xaxs); \
-}
-
-
-/* I optimize for speed on lookup, and don't give a RIP about delete.
- */
-void
-afs_RemoveAxs(struct axscache **headp, struct axscache *axsp)
-{
- struct axscache *i, *j;
-
- if (*headp && axsp) { /* is bullet-proofing really neccessary? */
- if (*headp == axsp) { /* most common case, I think */
- *headp = axsp->next;
- axs_Free(axsp);
- return;
- }
-
- i = *headp;
- j = i->next;
-
- while (j) {
- if (j == axsp) {
- i->next = j->next;
- axs_Free(axsp);
- return;
- }
- if ((i = j->next)) { /* ASSIGNMENT HERE! */
- j->next = i->next;
- axs_Free(axsp);
- return;
- }
- }
- }
- /* end of "if neither pointer is NULL" */
- return; /* !#@ FAILED to find it! */
-}
-
-
-/*
- * Takes an entire list of access cache structs and prepends them, lock, stock,
- * and barrel, to the front of the freelist.
- */
-void
-afs_FreeAllAxs(struct axscache **headp)
-{
- struct axscache *i, *j;
-
- i = *headp;
- j = NULL;
-
- while (i) { /* chase down the list 'til we reach the end */
- j = i->next;
- if (!j) {
- ObtainWriteLock(&afs_xaxs, 176);
- i->next = afs_axsfreelist; /* tack on the freelist to the end */
- afs_axsfreelist = *headp;
- ReleaseWriteLock(&afs_xaxs);
- *headp = NULL;
- return;
- }
- i = j->next;
- }
-
- if (j) { /* we ran off the end of the list... */
- ObtainWriteLock(&afs_xaxs, 177);
- j->next = afs_axsfreelist; /* tack on the freelist to the end */
- afs_axsfreelist = *headp;
- ReleaseWriteLock(&afs_xaxs);
- }
- *headp = NULL;
- return;
-}
-
-
-/* doesn't appear to be used at all */
-#if 0
-static void
-shutdown_xscache(void)
-{
- struct xfreelist *xp, *nxp;
-
- RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
- xp = xfreemallocs;
- while (xp) {
- nxp = xp->next;
- afs_osi_Free((char *)xp, NAXSs * sizeof(struct axscache));
- xp = nxp;
- }
- afs_axsfreelist = NULL;
- xfreemallocs = NULL;
-}
-#endif
+++ /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
- */
-
-#ifndef AFSAXCACHEH
-#define AFSAXCACHEH
-
-/* Access cache -
- * The way to use this package is:
- * If the cache pointer is not NULL, call afs_findAxs, and if it's not
- * NULL, use its access field
- * Otherwise,
- * axs_Alloc a new one,
- * fill it in,
- * insert it at the head of the list.
- *
- * Of course, don't forget to axs_Free them occasionally,
- *
- * Alloc and Free need a lock on the freelist, the other guys are safe if the
- * parent structure is locked, but probably REQUIRE the parent to be locked...
- */
-
-struct axscache {
- afs_int32 uid; /* most frequently used field, I think */
- afs_int32 axess;
- struct axscache *next;
-};
-
-/* DON'T use this with a NULL pointer!
- * the quick check should cover 99.9% of the cases
- */
-#define afs_FindAxs(cachep,id) (((cachep)->uid == id) ? (cachep) : afs_SlowFindAxs(&(cachep),(id)))
-
-#define axs_Front(head,pp,p) {(pp)->next = (p)->next; (p)->next= *(head);*(head)=(p);}
-
-#define afs_AddAxs(cachep,id,bits) { \
- struct axscache *ac; \
- if ((ac = axs_Alloc())) { \
- ac->uid = (id); \
- ac->axess = (afs_int32)(bits); \
- ac->next = (cachep); \
- cachep = ac; }}
-
-#endif
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_buffer.c,v 1.16 2004/01/23 16:53:35 rees Exp $");
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#if !defined(UKERNEL)
-#include "h/param.h"
-#include "h/types.h"
-#include "h/time.h"
-#if defined(AFS_AIX31_ENV) || defined(AFS_DEC_ENV)
-#include "h/limits.h"
-#endif
-#if !defined(AFS_AIX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
-#include "h/kernel.h" /* Doesn't needed, so it should go */
-#endif
-#endif /* !defined(UKERNEL) */
-
-#include "afs/afs_osi.h"
-#include "afsint.h"
-#include "afs/lock.h"
-
-#if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
-#include "h/buf.h"
-#endif /* !defined(UKERNEL) */
-
-#include "afs/stds.h"
-#include "afs/volerrors.h"
-#include "afs/exporter.h"
-#include "afs/prs_fs.h"
-#include "afs/afs_chunkops.h"
-#include "afs/dir.h"
-
-#include "afs/afs_stats.h"
-#include "afs/longc_procs.h"
-#include "afs/afs.h"
-
-#ifndef BUF_TIME_MAX
-#define BUF_TIME_MAX 0x7fffffff
-#endif
-/* number of pages per Unix buffer, when we're using Unix buffer pool */
-#define NPB 4
-/* page size */
-#define AFS_BUFFER_PAGESIZE 2048
-/* log page size */
-#define LOGPS 11
-/* If you change any of this PH stuff, make sure you don't break DZap() */
-/* use last two bits for page */
-#define PHPAGEMASK 3
-/* use next five bits for fid */
-#define PHFIDMASK 124
-/* page hash table size - this is pretty intertwined with pHash */
-#define PHSIZE (PHPAGEMASK + PHFIDMASK + 1)
-/* the pHash macro */
-#define pHash(fid,page) ((((afs_int32)((fid)[0])) & PHFIDMASK) \
- | (page & PHPAGEMASK))
-
-#ifdef dirty
-#undef dirty /* XXX */
-#endif
-
-static struct buffer *Buffers = 0;
-static char *BufferData;
-
-#ifdef AFS_AIX_ENV
-extern struct buf *geteblk();
-#endif
-#ifdef AFS_FBSD_ENV
-#define timecounter afs_timecounter
-#endif
-/* The locks for individual buffer entries are now sometimes obtained while holding the
- * afs_bufferLock. Thus we now have a locking hierarchy: afs_bufferLock -> Buffers[].lock.
- */
-static afs_lock_t afs_bufferLock;
-static struct buffer *phTable[PHSIZE]; /* page hash table */
-static int nbuffers;
-static afs_int32 timecounter;
-
-/* Prototypes for static routines */
-static struct buffer *afs_newslot(afs_inode_t * afid, afs_int32 apage,
- register struct buffer *lp);
-
-static int dinit_flag = 0;
-void
-DInit(int abuffers)
-{
- /* Initialize the venus buffer system. */
- register int i;
- register struct buffer *tb;
-#if AFS_USEBUFFERS
- struct buf *tub; /* unix buffer for allocation */
-#endif
-
- AFS_STATCNT(DInit);
- if (dinit_flag)
- return;
- dinit_flag = 1;
-#if AFS_USEBUFFERS
- /* round up to next multiple of NPB, since we allocate multiple pages per chunk */
- abuffers = ((abuffers - 1) | (NPB - 1)) + 1;
-#endif
- LOCK_INIT(&afs_bufferLock, "afs_bufferLock");
- Buffers =
- (struct buffer *)afs_osi_Alloc(abuffers * sizeof(struct buffer));
-#if !AFS_USEBUFFERS
- BufferData = (char *)afs_osi_Alloc(abuffers * AFS_BUFFER_PAGESIZE);
-#endif
- timecounter = 1;
- afs_stats_cmperf.bufAlloced = nbuffers = abuffers;
- for (i = 0; i < PHSIZE; i++)
- phTable[i] = 0;
- for (i = 0; i < abuffers; i++) {
-#if AFS_USEBUFFERS
- if ((i & (NPB - 1)) == 0) {
- /* time to allocate a fresh buffer */
- tub = geteblk(AFS_BUFFER_PAGESIZE * NPB);
- BufferData = (char *)tub->b_un.b_addr;
- }
-#endif
- /* Fill in each buffer with an empty indication. */
- tb = &Buffers[i];
- dirp_Zap(tb->fid);
- tb->accesstime = 0;
- tb->lockers = 0;
-#if AFS_USEBUFFERS
- if ((i & (NPB - 1)) == 0)
- tb->bufp = tub;
- else
- tb->bufp = 0;
- tb->data = &BufferData[AFS_BUFFER_PAGESIZE * (i & (NPB - 1))];
-#else
- tb->data = &BufferData[AFS_BUFFER_PAGESIZE * i];
-#endif
- tb->hashIndex = 0;
- tb->dirty = 0;
- RWLOCK_INIT(&tb->lock, "buffer lock");
- }
- return;
-}
-
-void *
-DRead(register afs_inode_t * fid, register int page)
-{
- /* Read a page from the disk. */
- register struct buffer *tb, *tb2;
- struct osi_file *tfile;
- int code;
-
- AFS_STATCNT(DRead);
- MObtainWriteLock(&afs_bufferLock, 256);
-
-#define bufmatch(tb) (tb->page == page && dirp_Eq(tb->fid, fid))
-#define buf_Front(head,parent,p) {(parent)->hashNext = (p)->hashNext; (p)->hashNext= *(head);*(head)=(p);}
-
- /* this apparently-complicated-looking code is simply an example of
- * a little bit of loop unrolling, and is a standard linked-list
- * traversal trick. It saves a few assignments at the the expense
- * of larger code size. This could be simplified by better use of
- * macros.
- */
- if ((tb = phTable[pHash(fid, page)])) {
- if (bufmatch(tb)) {
- MObtainWriteLock(&tb->lock, 257);
- ReleaseWriteLock(&afs_bufferLock);
- tb->lockers++;
- tb->accesstime = timecounter++;
- AFS_STATS(afs_stats_cmperf.bufHits++);
- MReleaseWriteLock(&tb->lock);
- return tb->data;
- } else {
- register struct buffer **bufhead;
- bufhead = &(phTable[pHash(fid, page)]);
- while ((tb2 = tb->hashNext)) {
- if (bufmatch(tb2)) {
- buf_Front(bufhead, tb, tb2);
- MObtainWriteLock(&tb2->lock, 258);
- ReleaseWriteLock(&afs_bufferLock);
- tb2->lockers++;
- tb2->accesstime = timecounter++;
- AFS_STATS(afs_stats_cmperf.bufHits++);
- MReleaseWriteLock(&tb2->lock);
- return tb2->data;
- }
- if ((tb = tb2->hashNext)) {
- if (bufmatch(tb)) {
- buf_Front(bufhead, tb2, tb);
- MObtainWriteLock(&tb->lock, 259);
- ReleaseWriteLock(&afs_bufferLock);
- tb->lockers++;
- tb->accesstime = timecounter++;
- AFS_STATS(afs_stats_cmperf.bufHits++);
- MReleaseWriteLock(&tb->lock);
- return tb->data;
- }
- } else
- break;
- }
- }
- } else
- tb2 = NULL;
-
- AFS_STATS(afs_stats_cmperf.bufMisses++);
- /* can't find it */
- /* The last thing we looked at was either tb or tb2 (or nothing). That
- * is at least the oldest buffer on one particular hash chain, so it's
- * a pretty good place to start looking for the truly oldest buffer.
- */
- tb = afs_newslot(fid, page, (tb ? tb : tb2));
- if (!tb) {
- MReleaseWriteLock(&afs_bufferLock);
- return NULL;
- }
- MObtainWriteLock(&tb->lock, 260);
- MReleaseWriteLock(&afs_bufferLock);
- tb->lockers++;
- tfile = afs_CFileOpen(fid[0]);
- if (page * AFS_BUFFER_PAGESIZE >= tfile->size) {
- dirp_Zap(tb->fid);
- tb->lockers--;
- MReleaseWriteLock(&tb->lock);
- afs_CFileClose(tfile);
- return NULL;
- }
- code =
- afs_CFileRead(tfile, tb->page * AFS_BUFFER_PAGESIZE, tb->data,
- AFS_BUFFER_PAGESIZE);
- afs_CFileClose(tfile);
- if (code < AFS_BUFFER_PAGESIZE) {
- dirp_Zap(tb->fid);
- tb->lockers--;
- MReleaseWriteLock(&tb->lock);
- return NULL;
- }
- /* Note that findslot sets the page field in the buffer equal to
- * what it is searching for. */
- MReleaseWriteLock(&tb->lock);
- return tb->data;
-}
-
-static void
-FixupBucket(register struct buffer *ap)
-{
- register struct buffer **lp, *tp;
- register int i;
- /* first try to get it out of its current hash bucket, in which it
- * might not be */
- AFS_STATCNT(FixupBucket);
- i = ap->hashIndex;
- lp = &phTable[i];
- for (tp = *lp; tp; tp = tp->hashNext) {
- if (tp == ap) {
- *lp = tp->hashNext;
- break;
- }
- lp = &tp->hashNext;
- }
- /* now figure the new hash bucket */
- i = pHash(ap->fid, ap->page);
- ap->hashIndex = i; /* remember where we are for deletion */
- ap->hashNext = phTable[i]; /* add us to the list */
- phTable[i] = ap; /* at the front, since it's LRU */
-}
-
-/* lp is pointer to a fairly-old buffer */
-static struct buffer *
-afs_newslot(afs_inode_t * afid, afs_int32 apage, register struct buffer *lp)
-{
- /* Find a usable buffer slot */
- register afs_int32 i;
- afs_int32 lt;
- register struct buffer *tp;
- struct osi_file *tfile;
-
- AFS_STATCNT(afs_newslot);
- /* we take a pointer here to a buffer which was at the end of an
- * LRU hash chain. Odds are, it's one of the older buffers, not
- * one of the newer. Having an older buffer to start with may
- * permit us to avoid a few of the assignments in the "typical
- * case" for loop below.
- */
- if (lp && (lp->lockers == 0)) {
- lt = lp->accesstime;
- } else {
- lp = 0;
- lt = BUF_TIME_MAX;
- }
-
- /* timecounter might have wrapped, if machine is very very busy
- * and stays up for a long time. Timecounter mustn't wrap twice
- * (positive->negative->positive) before calling newslot, but that
- * would require 2 billion consecutive cache hits... Anyway, the
- * penalty is only that the cache replacement policy will be
- * almost MRU for the next ~2 billion DReads... newslot doesn't
- * get called nearly as often as DRead, so in order to avoid the
- * performance penalty of using the hypers, it's worth doing the
- * extra check here every time. It's probably cheaper than doing
- * hcmp, anyway. There is a little performance hit resulting from
- * resetting all the access times to 0, but it only happens once
- * every month or so, and the access times will rapidly sort
- * themselves back out after just a few more DReads.
- */
- if (timecounter < 0) {
- timecounter = 1;
- tp = Buffers;
- for (i = 0; i < nbuffers; i++, tp++) {
- tp->accesstime = 0;
- if (!lp && !tp->lockers) /* one is as good as the rest, I guess */
- lp = tp;
- }
- } else {
- /* this is the typical case */
- tp = Buffers;
- for (i = 0; i < nbuffers; i++, tp++) {
- if (tp->lockers == 0) {
- if (tp->accesstime < lt) {
- lp = tp;
- lt = tp->accesstime;
- }
- }
- }
- }
-
- if (lp == 0) {
- /* There are no unlocked buffers -- this used to panic, but that
- * seems extreme. To the best of my knowledge, all the callers
- * of DRead are prepared to handle a zero return. Some of them
- * just panic directly, but not all of them. */
- afs_warn("all buffers locked");
- return 0;
- }
-
- if (lp->dirty) {
- tfile = afs_CFileOpen(lp->fid[0]);
- afs_CFileWrite(tfile, lp->page * AFS_BUFFER_PAGESIZE, lp->data,
- AFS_BUFFER_PAGESIZE);
- lp->dirty = 0;
- afs_CFileClose(tfile);
- AFS_STATS(afs_stats_cmperf.bufFlushDirty++);
- }
-
- /* Now fill in the header. */
- dirp_Cpy(lp->fid, afid); /* set this */
- lp->page = apage;
- lp->accesstime = timecounter++;
- FixupBucket(lp); /* move to the right hash bucket */
-
- return lp;
-}
-
-void
-DRelease(register struct buffer *bp, int flag)
-{
- /* Release a buffer, specifying whether or not the buffer has been
- * modified by the locker. */
- register int index;
-#if AFS_USEBUFFERS
- register struct buffer *tp;
-#endif
-
- AFS_STATCNT(DRelease);
- if (!bp)
- return;
-#if AFS_USEBUFFERS
- /* look for buffer by scanning Unix buffers for appropriate address */
- tp = Buffers;
- for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
- if ((afs_int32) bp >= (afs_int32) tp->data
- && (afs_int32) bp <
- (afs_int32) tp->data + AFS_BUFFER_PAGESIZE * NPB) {
- /* we found the right range */
- index += ((afs_int32) bp - (afs_int32) tp->data) >> LOGPS;
- break;
- }
- }
-#else
- index = (((char *)bp) - ((char *)BufferData)) >> LOGPS;
-#endif
- bp = &(Buffers[index]);
- MObtainWriteLock(&bp->lock, 261);
- bp->lockers--;
- if (flag)
- bp->dirty = 1;
- MReleaseWriteLock(&bp->lock);
-}
-
-int
-DVOffset(register void *ap)
-{
- /* Return the byte within a file represented by a buffer pointer. */
- register struct buffer *bp;
- register int index;
-#if AFS_USEBUFFERS
- register struct buffer *tp;
-#endif
- AFS_STATCNT(DVOffset);
- bp = ap;
-#if AFS_USEBUFFERS
- /* look for buffer by scanning Unix buffers for appropriate address */
- tp = Buffers;
- for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
- if ((afs_int32) bp >= (afs_int32) tp->data
- && (afs_int32) bp <
- (afs_int32) tp->data + AFS_BUFFER_PAGESIZE * NPB) {
- /* we found the right range */
- index += ((afs_int32) bp - (afs_int32) tp->data) >> LOGPS;
- break;
- }
- }
-#else
- index = (((char *)bp) - ((char *)BufferData)) >> LOGPS;
-#endif
- if (index < 0 || index >= nbuffers)
- return -1;
- bp = &(Buffers[index]);
- return AFS_BUFFER_PAGESIZE * bp->page + (int)(((char *)ap) - bp->data);
-}
-
-/* 1/1/91 - I've modified the hash function to take the page as well
- * as the *fid, so that lookup will be a bit faster. That presents some
- * difficulties for Zap, which now has to have some knowledge of the nature
- * of the hash function. Oh well. This should use the list traversal
- * method of DRead...
- */
-void
-DZap(afs_inode_t * fid)
-{
- register int i;
- /* Destroy all buffers pertaining to a particular fid. */
- register struct buffer *tb;
-
- AFS_STATCNT(DZap);
- MObtainReadLock(&afs_bufferLock);
-
- for (i = 0; i <= PHPAGEMASK; i++)
- for (tb = phTable[pHash(fid, i)]; tb; tb = tb->hashNext)
- if (dirp_Eq(tb->fid, fid)) {
- MObtainWriteLock(&tb->lock, 262);
- dirp_Zap(tb->fid);
- tb->dirty = 0;
- MReleaseWriteLock(&tb->lock);
- }
- MReleaseReadLock(&afs_bufferLock);
-}
-
-void
-DFlush(void)
-{
- /* Flush all the modified buffers. */
- register int i;
- register struct buffer *tb;
- struct osi_file *tfile;
-
- AFS_STATCNT(DFlush);
- tb = Buffers;
- MObtainReadLock(&afs_bufferLock);
- for (i = 0; i < nbuffers; i++, tb++) {
- if (tb->dirty) {
- MObtainWriteLock(&tb->lock, 263);
- tb->lockers++;
- MReleaseReadLock(&afs_bufferLock);
- if (tb->dirty) {
- tfile = afs_CFileOpen(tb->fid[0]);
- afs_CFileWrite(tfile, tb->page * AFS_BUFFER_PAGESIZE,
- tb->data, AFS_BUFFER_PAGESIZE);
- tb->dirty = 0; /* Clear the dirty flag */
- afs_CFileClose(tfile);
- }
- tb->lockers--;
- MReleaseWriteLock(&tb->lock);
- MObtainReadLock(&afs_bufferLock);
- }
- }
- MReleaseReadLock(&afs_bufferLock);
-}
-
-void *
-DNew(register afs_inode_t * fid, register int page)
-{
- /* Same as read, only do *not* even try to read the page, since it probably doesn't exist. */
- register struct buffer *tb;
- AFS_STATCNT(DNew);
- MObtainWriteLock(&afs_bufferLock, 264);
- if ((tb = afs_newslot(fid, page, NULL)) == 0) {
- MReleaseWriteLock(&afs_bufferLock);
- return 0;
- }
- MObtainWriteLock(&tb->lock, 265);
- MReleaseWriteLock(&afs_bufferLock);
- tb->lockers++;
- MReleaseWriteLock(&tb->lock);
- return tb->data;
-}
-
-void
-shutdown_bufferpackage(void)
-{
-#if AFS_USEBUFFERS
- register struct buffer *tp;
-#endif
- int i;
- extern int afs_cold_shutdown;
-
- AFS_STATCNT(shutdown_bufferpackage);
- /* Free all allocated Buffers and associated buffer pages */
- DFlush();
- if (afs_cold_shutdown) {
- dinit_flag = 0;
-#if !AFS_USEBUFFERS
- afs_osi_Free(BufferData, nbuffers * AFS_BUFFER_PAGESIZE);
-#else
- tp = Buffers;
- for (i = 0; i < nbuffers; i += NPB, tp += NPB) {
- /* The following check shouldn't be necessary and it will be removed soon */
- if (!tp->bufp)
- afs_warn
- ("shutdown_bufferpackage: bufp == 0!! Shouldn't happen\n");
- else {
- brelse(tp->bufp);
- tp->bufp = 0;
- }
- }
-#endif
- afs_osi_Free(Buffers, nbuffers * sizeof(struct buffer));
- nbuffers = 0;
- timecounter = 1;
- for (i = 0; i < PHSIZE; i++)
- phTable[i] = 0;
- memset((char *)&afs_bufferLock, 0, sizeof(afs_lock_t));
- }
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_call.c,v 1.66 2004/04/12 16:04:31 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h"
-#include "rx/rx_globals.h"
-#if !defined(UKERNEL) && !defined(AFS_LINUX20_ENV)
-#include "net/if.h"
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_DARWIN60_ENV)
-#include "netinet/in_var.h"
-#endif
-#endif /* !defined(UKERNEL) */
-#ifdef AFS_LINUX22_ENV
-#include "h/smp_lock.h"
-#endif
-
-
-#if defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV)
-#define AFS_MINBUFFERS 100
-#else
-#define AFS_MINBUFFERS 50
-#endif
-
-struct afsop_cell {
- afs_int32 hosts[MAXCELLHOSTS];
- char cellName[100];
-};
-
-char afs_zeros[AFS_ZEROS];
-char afs_rootVolumeName[64] = "";
-struct afs_icl_set *afs_iclSetp = (struct afs_icl_set *)0;
-struct afs_icl_set *afs_iclLongTermSetp = (struct afs_icl_set *)0;
-
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-kmutex_t afs_global_lock;
-kmutex_t afs_rxglobal_lock;
-#endif
-
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
-long afs_global_owner;
-#endif
-
-#if defined(AFS_OSF_ENV)
-simple_lock_data_t afs_global_lock;
-#endif
-
-#if defined(AFS_DARWIN_ENV)
-struct lock__bsd__ afs_global_lock;
-#endif
-
-#if defined(AFS_XBSD_ENV) && !defined(AFS_FBSD50_ENV)
-struct lock afs_global_lock;
-struct proc *afs_global_owner;
-#endif
-#ifdef AFS_FBSD50_ENV
-struct mtx afs_global_mtx;
-#endif
-
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
-thread_t afs_global_owner;
-#endif /* AFS_OSF_ENV */
-
-#if defined(AFS_AIX41_ENV)
-simple_lock_data afs_global_lock;
-#endif
-
-afs_int32 afs_initState = 0;
-afs_int32 afs_termState = 0;
-afs_int32 afs_setTime = 0;
-int afs_cold_shutdown = 0;
-char afs_SynchronousCloses = '\0';
-static int afs_CB_Running = 0;
-static int AFS_Running = 0;
-static int afs_CacheInit_Done = 0;
-static int afs_Go_Done = 0;
-extern struct interfaceAddr afs_cb_interface;
-static int afs_RX_Running = 0;
-static int afs_InitSetup_done = 0;
-
-afs_int32 afs_rx_deadtime = AFS_RXDEADTIME;
-afs_int32 afs_rx_harddead = AFS_HARDDEADTIME;
-
-static int
- Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval);
-
-#if defined(AFS_HPUX_ENV)
-extern int afs_vfs_mount();
-#endif /* defined(AFS_HPUX_ENV) */
-
-/* This is code which needs to be called once when the first daemon enters
- * the client. A non-zero return means an error and AFS should not start.
- */
-static int
-afs_InitSetup(int preallocs)
-{
- extern void afs_InitStats();
- int code;
-
- if (afs_InitSetup_done)
- return EAGAIN;
-
-#ifndef AFS_NOSTATS
- /*
- * Set up all the AFS statistics variables. This should be done
- * exactly once, and it should be done here, the first resource-setting
- * routine to be called by the CM/RX.
- */
- afs_InitStats();
-#endif /* AFS_NOSTATS */
-
- memset(afs_zeros, 0, AFS_ZEROS);
-
- /* start RX */
- rx_extraPackets = AFS_NRXPACKETS; /* smaller # of packets */
- code = rx_Init(htons(7001));
- if (code) {
- printf("AFS: RX failed to initialize.\n");
- return code;
- }
- rx_SetRxDeadTime(afs_rx_deadtime);
- /* resource init creates the services */
- afs_ResourceInit(preallocs);
-
- afs_InitSetup_done = 1;
- afs_osi_Wakeup(&afs_InitSetup_done);
-
- return code;
-}
-
-#if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)
-struct afsd_thread_info {
- unsigned long parm;
- struct completion *complete;
-};
-
-static int
-afsd_thread(void *rock)
-{
- struct afsd_thread_info *arg = rock;
- unsigned long parm = arg->parm;
-#ifdef SYS_SETPRIORITY_EXPORTED
- int (*sys_setpriority) (int, int, int) = sys_call_table[__NR_setpriority];
-#endif
-#if defined(AFS_LINUX26_ENV)
- daemonize("afsd");
-#else
- daemonize();
-#endif
- /* doesn't do much, since we were forked from keventd, but
- * does call mm_release, which wakes up our parent (since it
- * used CLONE_VFORK) */
-#if !defined(AFS_LINUX26_ENV)
- reparent_to_init();
-#endif
- afs_osi_MaskSignals();
- switch (parm) {
- case AFSOP_START_RXCALLBACK:
- sprintf(current->comm, "afs_cbstart");
- AFS_GLOCK();
- complete(arg->complete);
- afs_CB_Running = 1;
- while (afs_RX_Running != 2)
- afs_osi_Sleep(&afs_RX_Running);
- sprintf(current->comm, "afs_callback");
- afs_RXCallBackServer();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_START_AFS:
- sprintf(current->comm, "afs_afsstart");
- AFS_GLOCK();
- complete(arg->complete);
- AFS_Running = 1;
- while (afs_initState < AFSOP_START_AFS)
- afs_osi_Sleep(&afs_initState);
- afs_initState = AFSOP_START_BKG;
- afs_osi_Wakeup(&afs_initState);
- sprintf(current->comm, "afsd");
- afs_Daemon();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_START_BKG:
- sprintf(current->comm, "afs_bkgstart");
- AFS_GLOCK();
- complete(arg->complete);
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
- if (afs_initState < AFSOP_GO) {
- afs_initState = AFSOP_GO;
- afs_osi_Wakeup(&afs_initState);
- }
- sprintf(current->comm, "afs_background");
- afs_BackgroundDaemon();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_START_TRUNCDAEMON:
- sprintf(current->comm, "afs_trimstart");
- AFS_GLOCK();
- complete(arg->complete);
- while (afs_initState < AFSOP_GO)
- afs_osi_Sleep(&afs_initState);
- sprintf(current->comm, "afs_cachetrim");
- afs_CacheTruncateDaemon();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_START_CS:
- sprintf(current->comm, "afs_checkserver");
- AFS_GLOCK();
- complete(arg->complete);
- afs_CheckServerDaemon();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_RXEVENT_DAEMON:
- sprintf(current->comm, "afs_evtstart");
-#ifdef SYS_SETPRIORITY_EXPORTED
- sys_setpriority(PRIO_PROCESS, 0, -10);
-#else
-#ifdef CURRENT_INCLUDES_NICE
- current->nice = -10;
-#endif
-#endif
- AFS_GLOCK();
- complete(arg->complete);
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
- sprintf(current->comm, "afs_rxevent");
- afs_rxevent_daemon();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- case AFSOP_RXLISTENER_DAEMON:
- sprintf(current->comm, "afs_lsnstart");
-#ifdef SYS_SETPRIORITY_EXPORTED
- sys_setpriority(PRIO_PROCESS, 0, -10);
-#else
-#ifdef CURRENT_INCLUDES_NICE
- current->nice = -10;
-#endif
-#endif
- AFS_GLOCK();
- complete(arg->complete);
- afs_initState = AFSOP_START_AFS;
- afs_osi_Wakeup(&afs_initState);
- afs_RX_Running = 2;
- afs_osi_Wakeup(&afs_RX_Running);
- afs_osi_RxkRegister();
- sprintf(current->comm, "afs_rxlistener");
- rxk_Listener();
- AFS_GUNLOCK();
- complete_and_exit(0, 0);
- break;
- default:
- printf("Unknown op %d in StartDaemon()\n");
- break;
- }
- return 0;
-}
-
-void
-afsd_launcher(void *rock)
-{
- if (!kernel_thread(afsd_thread, rock, CLONE_VFORK | SIGCHLD))
- printf("kernel_thread failed. afs startup will not complete\n");
-}
-
-void
-afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
- long parm6)
-{
- int code;
- DECLARE_COMPLETION(c);
-#if defined(AFS_LINUX26_ENV)
- struct work_struct tq;
-#else
- struct tq_struct tq;
-#endif
- struct afsd_thread_info info;
- if (parm == AFSOP_START_RXCALLBACK) {
- if (afs_CB_Running)
- return;
- } else if (parm == AFSOP_RXLISTENER_DAEMON) {
- if (afs_RX_Running)
- return;
- afs_RX_Running = 1;
- code = afs_InitSetup(parm2);
- if (parm3) {
- rx_enablePeerRPCStats();
- }
- if (parm4) {
- rx_enableProcessRPCStats();
- }
- if (code)
- return;
- } else if (parm == AFSOP_START_AFS) {
- if (AFS_Running)
- return;
- } /* other functions don't need setup in the parent */
- info.complete = &c;
- info.parm = parm;
-#if defined(AFS_LINUX26_ENV)
- INIT_WORK(&tq, afsd_launcher, &info);
- schedule_work(&tq);
-#else
- tq.sync = 0;
- INIT_LIST_HEAD(&tq.list);
- tq.routine = afsd_launcher;
- tq.data = &info;
- schedule_task(&tq);
-#endif
- AFS_GUNLOCK();
- /* we need to wait cause we passed stack pointers around.... */
- wait_for_completion(&c);
- AFS_GLOCK();
-}
-#endif
-
-/* leaving as is, probably will barf if we add prototypes here since it's likely being called
-with partial list */
-int
-afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
- long parm, parm2, parm3, parm4, parm5, parm6;
-{
- afs_int32 code = 0;
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- size_t bufferSize;
-#else /* AFS_SGI61_ENV */
- u_int bufferSize;
-#endif /* AFS_SGI61_ENV */
-
- AFS_STATCNT(afs_syscall_call);
-#ifdef AFS_SUN5_ENV
- if (!afs_suser(CRED()) && (parm != AFSOP_GETMTU)
- && (parm != AFSOP_GETMASK)) {
- /* only root can run this code */
- return (EACCES);
-#else
- if (!afs_suser() && (parm != AFSOP_GETMTU)
- && (parm != AFSOP_GETMASK)) {
- /* only root can run this code */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(EACCES);
- return (EACCES);
-#else
-#if defined(AFS_OSF_ENV)
- return EACCES;
-#else /* AFS_OSF_ENV */
- return EPERM;
-#endif /* AFS_OSF_ENV */
-#endif
-#endif
- }
- AFS_GLOCK();
-#if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS) && !defined(UKERNEL)
- if (parm < AFSOP_ADDCELL || parm == AFSOP_RXEVENT_DAEMON
- || parm == AFSOP_RXLISTENER_DAEMON) {
- afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
- }
-#else /* !(AFS_LINUX24_ENV && !UKERNEL) */
- if (parm == AFSOP_START_RXCALLBACK) {
- if (afs_CB_Running)
- goto out;
- afs_CB_Running = 1;
-#ifndef RXK_LISTENER_ENV
- code = afs_InitSetup(parm2);
- if (!code)
-#endif /* !RXK_LISTENER_ENV */
- {
-#ifdef RXK_LISTENER_ENV
- while (afs_RX_Running != 2)
- afs_osi_Sleep(&afs_RX_Running);
-#else /* !RXK_LISTENER_ENV */
- afs_initState = AFSOP_START_AFS;
- afs_osi_Wakeup(&afs_initState);
-#endif /* RXK_LISTENER_ENV */
- afs_osi_Invisible();
- afs_RXCallBackServer();
- }
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, code);
-#endif /* AFS_SGI_ENV */
- }
-#ifdef RXK_LISTENER_ENV
- else if (parm == AFSOP_RXLISTENER_DAEMON) {
- if (afs_RX_Running)
- goto out;
- afs_RX_Running = 1;
- code = afs_InitSetup(parm2);
- if (parm3) {
- rx_enablePeerRPCStats();
- }
- if (parm4) {
- rx_enableProcessRPCStats();
- }
- if (!code) {
- afs_initState = AFSOP_START_AFS;
- afs_osi_Wakeup(&afs_initState);
- afs_osi_Invisible();
- afs_RX_Running = 2;
- afs_osi_Wakeup(&afs_RX_Running);
-#ifndef UKERNEL
- afs_osi_RxkRegister();
-#endif /* !UKERNEL */
- rxk_Listener();
- }
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, code);
-#endif /* AFS_SGI_ENV */
- }
-#endif /* RXK_LISTENER_ENV */
- else if (parm == AFSOP_START_AFS) {
- /* afs daemon */
- if (AFS_Running)
- goto out;
- AFS_Running = 1;
- while (afs_initState < AFSOP_START_AFS)
- afs_osi_Sleep(&afs_initState);
-
- afs_initState = AFSOP_START_BKG;
- afs_osi_Wakeup(&afs_initState);
- afs_osi_Invisible();
- afs_Daemon();
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, 0);
-#endif /* AFS_SGI_ENV */
- } else if (parm == AFSOP_START_CS) {
- afs_osi_Invisible();
- afs_CheckServerDaemon();
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, 0);
-#endif /* AFS_SGI_ENV */
- } else if (parm == AFSOP_START_BKG) {
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
- if (afs_initState < AFSOP_GO) {
- afs_initState = AFSOP_GO;
- afs_osi_Wakeup(&afs_initState);
- }
- /* start the bkg daemon */
- afs_osi_Invisible();
-#ifdef AFS_AIX32_ENV
- if (parm2)
- afs_BioDaemon(parm2);
- else
-#endif /* AFS_AIX32_ENV */
- afs_BackgroundDaemon();
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, 0);
-#endif /* AFS_SGI_ENV */
- } else if (parm == AFSOP_START_TRUNCDAEMON) {
- while (afs_initState < AFSOP_GO)
- afs_osi_Sleep(&afs_initState);
- /* start the bkg daemon */
- afs_osi_Invisible();
- afs_CacheTruncateDaemon();
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, 0);
-#endif /* AFS_SGI_ENV */
- }
-#if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
- else if (parm == AFSOP_RXEVENT_DAEMON) {
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
- afs_osi_Invisible();
- afs_rxevent_daemon();
-#ifdef AFS_SGI_ENV
- AFS_GUNLOCK();
- exit(CLD_EXITED, 0);
-#endif /* AFS_SGI_ENV */
- }
-#endif /* AFS_SUN5_ENV || RXK_LISTENER_ENV */
-#endif /* AFS_LINUX24_ENV && !UKERNEL */
- else if (parm == AFSOP_BASIC_INIT) {
- afs_int32 temp;
-
- while (!afs_InitSetup_done)
- afs_osi_Sleep(&afs_InitSetup_done);
-
-#if defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- temp = AFS_MINBUFFERS; /* Should fix this soon */
-#else
- /* number of 2k buffers we could get from all of the buffer space */
- temp = ((afs_bufferpages * NBPG) >> 11);
- temp = temp >> 2; /* don't take more than 25% (our magic parameter) */
- if (temp < AFS_MINBUFFERS)
- temp = AFS_MINBUFFERS; /* though we really should have this many */
-#endif
- DInit(temp);
- afs_rootFid.Fid.Volume = 0;
- code = 0;
- } else if (parm == AFSOP_ADDCELL) {
- /* add a cell. Parameter 2 is 8 hosts (in net order), parm 3 is the null-terminated
- * name. Parameter 4 is the length of the name, including the null. Parm 5 is the
- * home cell flag (0x1 bit) and the nosuid flag (0x2 bit) */
- struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
-
- AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
- code);
- if (!code) {
- if (parm4 > sizeof(tcell->cellName))
- code = EFAULT;
- else {
- AFS_COPYIN((char *)parm3, tcell->cellName, parm4, code);
- if (!code)
- afs_NewCell(tcell->cellName, tcell->hosts, parm5, NULL, 0,
- 0, 0);
- }
- }
- afs_osi_Free(tcell, sizeof(struct afsop_cell));
- } else if (parm == AFSOP_ADDCELL2) {
- struct afsop_cell *tcell = afs_osi_Alloc(sizeof(struct afsop_cell));
- char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ), *lcnamep = 0;
- char *tbuffer1 = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- int cflags = parm4;
-
-#if 0
- /* wait for basic init - XXX can't find any reason we need this? */
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
-#endif
-
- AFS_COPYIN((char *)parm2, (char *)tcell->hosts, sizeof(tcell->hosts),
- code);
- if (!code) {
- AFS_COPYINSTR((char *)parm3, tbuffer1, AFS_SMALLOCSIZ,
- &bufferSize, code);
- if (!code) {
- if (parm4 & 4) {
- AFS_COPYINSTR((char *)parm5, tbuffer, AFS_SMALLOCSIZ,
- &bufferSize, code);
- if (!code) {
- lcnamep = tbuffer;
- cflags |= CLinkedCell;
- }
- }
- if (!code)
- code =
- afs_NewCell(tbuffer1, tcell->hosts, cflags, lcnamep,
- 0, 0, 0);
- }
- }
- afs_osi_Free(tcell, sizeof(struct afsop_cell));
- osi_FreeSmallSpace(tbuffer);
- osi_FreeSmallSpace(tbuffer1);
- } else if (parm == AFSOP_ADDCELLALIAS) {
- /*
- * Call arguments:
- * parm2 is the alias name
- * parm3 is the real cell name
- */
- char *aliasName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- char *cellName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-
- AFS_COPYINSTR((char *)parm2, aliasName, AFS_SMALLOCSIZ, &bufferSize,
- code);
- if (!code)
- AFS_COPYINSTR((char *)parm3, cellName, AFS_SMALLOCSIZ,
- &bufferSize, code);
- if (!code)
- afs_NewCellAlias(aliasName, cellName);
- osi_FreeSmallSpace(aliasName);
- osi_FreeSmallSpace(cellName);
- } else if (parm == AFSOP_SET_THISCELL) {
- /*
- * Call arguments:
- * parm2 is the primary cell name
- */
- char *cell = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-
- AFS_COPYINSTR((char *)parm2, cell, AFS_SMALLOCSIZ, &bufferSize, code);
- if (!code)
- afs_SetPrimaryCell(cell);
- osi_FreeSmallSpace(cell);
- } else if (parm == AFSOP_CACHEINIT) {
- struct afs_cacheParams cparms;
-
- if (afs_CacheInit_Done)
- goto out;
-
- AFS_COPYIN((char *)parm2, (caddr_t) & cparms, sizeof(cparms), code);
- if (code) {
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
- code = -1;
-#endif
- goto out;
- }
- afs_CacheInit_Done = 1;
- {
- struct afs_icl_log *logp;
- /* initialize the ICL system */
- code = afs_icl_CreateLog("cmfx", 60 * 1024, &logp);
- if (code == 0)
- code =
- afs_icl_CreateSetWithFlags("cm", logp, NULL,
- ICL_CRSET_FLAG_DEFAULT_OFF,
- &afs_iclSetp);
- code =
- afs_icl_CreateSet("cmlongterm", logp, NULL,
- &afs_iclLongTermSetp);
- }
- afs_setTime = cparms.setTimeFlag;
-
- code =
- afs_CacheInit(cparms.cacheScaches, cparms.cacheFiles,
- cparms.cacheBlocks, cparms.cacheDcaches,
- cparms.cacheVolumes, cparms.chunkSize,
- cparms.memCacheFlag, cparms.inodes, cparms.users);
-
- } else if (parm == AFSOP_CACHEINODE) {
- ino_t ainode = parm2;
- /* wait for basic init */
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
-
- /* do it by inode */
-#ifdef AFS_SGI62_ENV
- ainode = (ainode << 32) | (parm3 & 0xffffffff);
-#endif
- code = afs_InitCacheFile(NULL, ainode);
- } else if (parm == AFSOP_ROOTVOLUME) {
- /* wait for basic init */
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
-
- if (parm2) {
- AFS_COPYINSTR((char *)parm2, afs_rootVolumeName,
- sizeof(afs_rootVolumeName), &bufferSize, code);
- afs_rootVolumeName[sizeof(afs_rootVolumeName) - 1] = 0;
- } else
- code = 0;
- } else if (parm == AFSOP_CACHEFILE || parm == AFSOP_CACHEINFO
- || parm == AFSOP_VOLUMEINFO || parm == AFSOP_AFSLOG
- || parm == AFSOP_CELLINFO) {
- char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-
- code = 0;
- AFS_COPYINSTR((char *)parm2, tbuffer, AFS_SMALLOCSIZ, &bufferSize,
- code);
- if (code) {
- osi_FreeSmallSpace(tbuffer);
- goto out;
- }
- if (!code) {
- tbuffer[AFS_SMALLOCSIZ - 1] = '\0'; /* null-terminate the name */
- /* We have the cache dir copied in. Call the cache init routine */
- if (parm == AFSOP_CACHEFILE)
- code = afs_InitCacheFile(tbuffer, 0);
- else if (parm == AFSOP_CACHEINFO)
- code = afs_InitCacheInfo(tbuffer);
- else if (parm == AFSOP_VOLUMEINFO)
- code = afs_InitVolumeInfo(tbuffer);
- else if (parm == AFSOP_CELLINFO)
- code = afs_InitCellInfo(tbuffer);
- }
- osi_FreeSmallSpace(tbuffer);
- } else if (parm == AFSOP_GO) {
- /* the generic initialization calls come here. One parameter: should we do the
- * set-time operation on this workstation */
- if (afs_Go_Done)
- goto out;
- afs_Go_Done = 1;
- while (afs_initState < AFSOP_GO)
- afs_osi_Sleep(&afs_initState);
- afs_initState = 101;
- afs_setTime = parm2;
- afs_osi_Wakeup(&afs_initState);
-#if (!defined(AFS_NONFSTRANS) && !defined(AFS_DEC_ENV)) || defined(AFS_AIX_IAUTH_ENV)
- afs_nfsclient_init();
-#endif
- printf("found %d non-empty cache files (%d%%).\n",
- afs_stats_cmperf.cacheFilesReused,
- (100 * afs_stats_cmperf.cacheFilesReused) /
- (afs_stats_cmperf.cacheNumEntries ? afs_stats_cmperf.
- cacheNumEntries : 1));
- } else if (parm == AFSOP_ADVISEADDR) {
- /* pass in the host address to the rx package */
- afs_int32 count = parm2;
- afs_int32 *buffer =
- afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- afs_int32 *maskbuffer =
- afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- afs_int32 *mtubuffer =
- afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- int i;
- int code;
-
- if (count > AFS_MAX_INTERFACE_ADDR) {
- code = ENOMEM;
- count = AFS_MAX_INTERFACE_ADDR;
- }
-
- AFS_COPYIN((char *)parm3, (char *)buffer, count * sizeof(afs_int32),
- code);
- if (parm4)
- AFS_COPYIN((char *)parm4, (char *)maskbuffer,
- count * sizeof(afs_int32), code);
- if (parm5)
- AFS_COPYIN((char *)parm5, (char *)mtubuffer,
- count * sizeof(afs_int32), code);
-
- afs_cb_interface.numberOfInterfaces = count;
- for (i = 0; i < count; i++) {
- afs_cb_interface.addr_in[i] = buffer[i];
-#ifdef AFS_USERSPACE_IP_ADDR
- /* AFS_USERSPACE_IP_ADDR means we have no way of finding the
- * machines IP addresses when in the kernel (the in_ifaddr
- * struct is not available), so we pass the info in at
- * startup. We also pass in the subnetmask and mtu size. The
- * subnetmask is used when setting the rank:
- * afsi_SetServerIPRank(); and the mtu size is used when
- * finding the best mtu size. rxi_FindIfnet() is replaced
- * with rxi_Findcbi().
- */
- afs_cb_interface.subnetmask[i] =
- (parm4 ? maskbuffer[i] : 0xffffffff);
- afs_cb_interface.mtu[i] = (parm5 ? mtubuffer[i] : htonl(1500));
-#endif
- }
- afs_uuid_create(&afs_cb_interface.uuid);
- rxi_setaddr(buffer[0]);
- afs_osi_Free(buffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- afs_osi_Free(maskbuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- afs_osi_Free(mtubuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
- }
-#ifdef AFS_SGI53_ENV
- else if (parm == AFSOP_NFSSTATICADDR) {
- extern int (*nfs_rfsdisptab_v2) ();
- nfs_rfsdisptab_v2 = (int (*)())parm2;
- } else if (parm == AFSOP_NFSSTATICADDR2) {
- extern int (*nfs_rfsdisptab_v2) ();
-#ifdef _K64U64
- nfs_rfsdisptab_v2 = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
-#else /* _K64U64 */
- nfs_rfsdisptab_v2 = (int (*)())(parm3 & 0xffffffff);
-#endif /* _K64U64 */
- }
-#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
- else if (parm == AFSOP_SBLOCKSTATICADDR2) {
- extern int (*afs_sblockp) ();
- extern void (*afs_sbunlockp) ();
-#ifdef _K64U64
- afs_sblockp = (int (*)())((parm2 << 32) | (parm3 & 0xffffffff));
- afs_sbunlockp = (void (*)())((parm4 << 32) | (parm5 & 0xffffffff));
-#else
- afs_sblockp = (int (*)())(parm3 & 0xffffffff);
- afs_sbunlockp = (void (*)())(parm5 & 0xffffffff);
-#endif /* _K64U64 */
- }
-#endif /* AFS_SGI62_ENV && !AFS_SGI65_ENV */
-#endif /* AFS_SGI53_ENV */
- else if (parm == AFSOP_SHUTDOWN) {
- afs_cold_shutdown = 0;
- if (parm == 1)
- afs_cold_shutdown = 1;
-#ifndef AFS_DARWIN_ENV
- if (afs_globalVFS != 0) {
- afs_warn("AFS isn't unmounted yet! Call aborted\n");
- code = EACCES;
- } else
-#endif
- afs_shutdown();
- } else if (parm == AFSOP_AFS_VFSMOUNT) {
-#ifdef AFS_HPUX_ENV
- vfsmount(parm2, parm3, parm4, parm5);
-#else /* defined(AFS_HPUX_ENV) */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(EINVAL);
-#else
- code = EINVAL;
-#endif
-#endif /* defined(AFS_HPUX_ENV) */
- } else if (parm == AFSOP_CLOSEWAIT) {
- afs_SynchronousCloses = 'S';
- } else if (parm == AFSOP_GETMTU) {
- afs_uint32 mtu = 0;
-#if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
-#ifdef AFS_USERSPACE_IP_ADDR
- afs_int32 i;
- i = rxi_Findcbi(parm2);
- mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
-#else /* AFS_USERSPACE_IP_ADDR */
- struct ifnet *tifnp;
-
- tifnp = rxi_FindIfnet(parm2, NULL); /* make iterative */
- mtu = (tifnp ? tifnp->if_mtu : htonl(1500));
-#endif /* else AFS_USERSPACE_IP_ADDR */
-#endif /* !AFS_SUN5_ENV */
- if (!code)
- AFS_COPYOUT((caddr_t) & mtu, (caddr_t) parm3, sizeof(afs_int32),
- code);
-#ifdef AFS_AIX32_ENV
-/* this is disabled for now because I can't figure out how to get access
- * to these kernel variables. It's only for supporting user-mode rx
- * programs -- it makes a huge difference on the 220's in my testbed,
- * though I don't know why. The bosserver does this with /etc/no, so it's
- * being handled a different way for the servers right now. */
-/* {
- static adjusted = 0;
- extern u_long sb_max_dflt;
- if (!adjusted) {
- adjusted = 1;
- if (sb_max_dflt < 131072) sb_max_dflt = 131072;
- if (sb_max < 131072) sb_max = 131072;
- }
- } */
-#endif /* AFS_AIX32_ENV */
- } else if (parm == AFSOP_GETMASK) { /* parm2 == addr in net order */
- afs_uint32 mask = 0;
-#if !defined(AFS_SUN5_ENV)
-#ifdef AFS_USERSPACE_IP_ADDR
- afs_int32 i;
- i = rxi_Findcbi(parm2);
- if (i != -1) {
- mask = afs_cb_interface.subnetmask[i];
- } else {
- code = -1;
- }
-#else /* AFS_USERSPACE_IP_ADDR */
- struct ifnet *tifnp;
-
- tifnp = rxi_FindIfnet(parm2, &mask); /* make iterative */
- if (!tifnp)
- code = -1;
-#endif /* else AFS_USERSPACE_IP_ADDR */
-#endif /* !AFS_SUN5_ENV */
- if (!code)
- AFS_COPYOUT((caddr_t) & mask, (caddr_t) parm3, sizeof(afs_int32),
- code);
- }
-#ifdef AFS_AFSDB_ENV
- else if (parm == AFSOP_AFSDB_HANDLER) {
- int sizeArg = (int)parm4;
- int kmsgLen = sizeArg & 0xffff;
- int cellLen = (sizeArg & 0xffff0000) >> 16;
- afs_int32 *kmsg = afs_osi_Alloc(kmsgLen);
- char *cellname = afs_osi_Alloc(cellLen);
-
-#ifndef UKERNEL
- afs_osi_MaskSignals();
-#endif
- AFS_COPYIN((afs_int32 *) parm2, cellname, cellLen, code);
- AFS_COPYIN((afs_int32 *) parm3, kmsg, kmsgLen, code);
- if (!code) {
- code = afs_AFSDBHandler(cellname, cellLen, kmsg);
- if (*cellname == 1)
- *cellname = 0;
- if (code == -2) { /* Shutting down? */
- *cellname = 1;
- code = 0;
- }
- }
- if (!code)
- AFS_COPYOUT(cellname, (char *)parm2, cellLen, code);
- afs_osi_Free(kmsg, kmsgLen);
- afs_osi_Free(cellname, cellLen);
- }
-#endif
- else if (parm == AFSOP_SET_DYNROOT) {
- code = afs_SetDynrootEnable(parm2);
- } else if (parm == AFSOP_SET_FAKESTAT) {
- afs_fakestat_enable = parm2;
- code = 0;
- } else if (parm == AFSOP_SET_BACKUPTREE) {
- afs_bkvolpref = parm2;
- } else
- code = EINVAL;
-
- out:
- AFS_GUNLOCK();
-#ifdef AFS_LINUX20_ENV
- return -code;
-#else
- return code;
-#endif
-}
-
-#ifdef AFS_AIX32_ENV
-
-#include "sys/lockl.h"
-
-/*
- * syscall - this is the VRMIX system call entry point.
- *
- * NOTE:
- * THIS SHOULD BE CHANGED TO afs_syscall(), but requires
- * all the user-level calls to `syscall' to change.
- */
-syscall(syscall, p1, p2, p3, p4, p5, p6)
-{
- register rval1 = 0, code;
- register monster;
- int retval = 0;
-#ifndef AFS_AIX41_ENV
- extern lock_t kernel_lock;
- monster = lockl(&kernel_lock, LOCK_SHORT);
-#endif /* !AFS_AIX41_ENV */
-
- AFS_STATCNT(syscall);
- setuerror(0);
- switch (syscall) {
- case AFSCALL_CALL:
- rval1 = afs_syscall_call(p1, p2, p3, p4, p5, p6);
- break;
-
- case AFSCALL_SETPAG:
- AFS_GLOCK();
- rval1 = afs_setpag();
- AFS_GUNLOCK();
- break;
-
- case AFSCALL_PIOCTL:
- AFS_GLOCK();
- rval1 = afs_syscall_pioctl(p1, p2, p3, p4);
- AFS_GUNLOCK();
- break;
-
- case AFSCALL_ICREATE:
- rval1 = afs_syscall_icreate(p1, p2, p3, p4, p5, p6);
- break;
-
- case AFSCALL_IOPEN:
- rval1 = afs_syscall_iopen(p1, p2, p3);
- break;
-
- case AFSCALL_IDEC:
- rval1 = afs_syscall_iincdec(p1, p2, p3, -1);
- break;
-
- case AFSCALL_IINC:
- rval1 = afs_syscall_iincdec(p1, p2, p3, 1);
- break;
-
- case AFSCALL_ICL:
- AFS_GLOCK();
- code = Afscall_icl(p1, p2, p3, p4, p5, &retval);
- AFS_GUNLOCK();
- if (!code)
- rval1 = retval;
- if (!rval1)
- rval1 = code;
- break;
-
- default:
- rval1 = EINVAL;
- setuerror(EINVAL);
- break;
- }
-
- out:
-#ifndef AFS_AIX41_ENV
- if (monster != LOCK_NEST)
- unlockl(&kernel_lock);
-#endif /* !AFS_AIX41_ENV */
- return getuerror()? -1 : rval1;
-}
-
-/*
- * lsetpag - interface to afs_setpag().
- */
-lsetpag()
-{
-
- AFS_STATCNT(lsetpag);
- return syscall(AFSCALL_SETPAG, 0, 0, 0, 0, 0);
-}
-
-/*
- * lpioctl - interface to pioctl()
- */
-lpioctl(path, cmd, cmarg, follow)
- char *path, *cmarg;
-{
-
- AFS_STATCNT(lpioctl);
- return syscall(AFSCALL_PIOCTL, path, cmd, cmarg, follow);
-}
-
-#else /* !AFS_AIX32_ENV */
-
-#if defined(AFS_SGI_ENV)
-struct afsargs {
- sysarg_t syscall;
- sysarg_t parm1;
- sysarg_t parm2;
- sysarg_t parm3;
- sysarg_t parm4;
- sysarg_t parm5;
-};
-
-
-int
-Afs_syscall(struct afsargs *uap, rval_t * rvp)
-{
- int error;
- long retval;
-
- AFS_STATCNT(afs_syscall);
- switch (uap->syscall) {
- case AFSCALL_ICL:
- retval = 0;
- AFS_GLOCK();
- error =
- Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5, &retval);
- AFS_GUNLOCK();
- rvp->r_val1 = retval;
- break;
-#ifdef AFS_SGI_XFS_IOPS_ENV
- case AFSCALL_IDEC64:
- error =
- afs_syscall_idec64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5);
- break;
- case AFSCALL_IINC64:
- error =
- afs_syscall_iinc64(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5);
- break;
- case AFSCALL_ILISTINODE64:
- error =
- afs_syscall_ilistinode64(uap->parm1, uap->parm2, uap->parm3,
- uap->parm4, uap->parm5);
- break;
- case AFSCALL_ICREATENAME64:
- error =
- afs_syscall_icreatename64(uap->parm1, uap->parm2, uap->parm3,
- uap->parm4, uap->parm5);
- break;
-#endif
-#ifdef AFS_SGI_VNODE_GLUE
- case AFSCALL_INIT_KERNEL_CONFIG:
- error = afs_init_kernel_config(uap->parm1);
- break;
-#endif
- default:
- error =
- afs_syscall_call(uap->syscall, uap->parm1, uap->parm2, uap->parm3,
- uap->parm4, uap->parm5);
- }
- return error;
-}
-
-#else /* AFS_SGI_ENV */
-
-struct iparam {
- long param1;
- long param2;
- long param3;
- long param4;
-};
-
-struct iparam32 {
- int param1;
- int param2;
- int param3;
- int param4;
-};
-
-
-static void
-iparam32_to_iparam(const struct iparam32 *src, struct iparam *dst)
-{
- dst->param1 = src->param1;
- dst->param2 = src->param2;
- dst->param3 = src->param3;
- dst->param4 = src->param4;
-}
-
-/*
- * If you need to change copyin_iparam(), you may also need to change
- * copyin_afs_ioctl().
- */
-
-static int
-copyin_iparam(caddr_t cmarg, struct iparam *dst)
-{
- int code;
-
-#if defined(AFS_HPUX_64BIT_ENV)
- struct iparam32 dst32;
-
- if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- iparam32_to_iparam(&dst32, dst);
- return code;
- }
-#endif /* AFS_HPUX_64BIT_ENV */
-
-#if defined(AFS_SUN57_64BIT_ENV)
- struct iparam32 dst32;
-
- if (get_udatamodel() == DATAMODEL_ILP32) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- iparam32_to_iparam(&dst32, dst);
- return code;
- }
-#endif /* AFS_SUN57_64BIT_ENV */
-
-#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) && !defined(AFS_AMD64_LINUX20_ENV)
- struct iparam32 dst32;
-
-#ifdef AFS_SPARC64_LINUX24_ENV
- if (current->thread.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_SPARC64_LINUX20_ENV)
- if (current->tss.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_AMD64_LINUX20_ENV)
- if (current->thread.flags & THREAD_IA32)
-#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
-#else
-#error Not done for this linux version
-#endif
- {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- iparam32_to_iparam(&dst32, dst);
- return code;
- }
-#endif /* AFS_LINUX_64BIT_KERNEL */
-
- AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
- return code;
-}
-
-/* Main entry of all afs system calls */
-#ifdef AFS_SUN5_ENV
-extern int afs_sinited;
-
-/** The 32 bit OS expects the members of this structure to be 32 bit
- * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
- * to accomodate both, *long* is used instead of afs_int32
- */
-
-#ifdef AFS_SUN57_ENV
-struct afssysa {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6;
-};
-#else
-struct afssysa {
- afs_int32 syscall;
- afs_int32 parm1;
- afs_int32 parm2;
- afs_int32 parm3;
- afs_int32 parm4;
- afs_int32 parm5;
- afs_int32 parm6;
-};
-#endif
-
-Afs_syscall(register struct afssysa *uap, rval_t * rvp)
-{
- int *retval = &rvp->r_val1;
-#else /* AFS_SUN5_ENV */
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-int
-afs3_syscall(p, args, retval)
-#ifdef AFS_FBSD50_ENV
- struct thread *p;
-#else
- struct proc *p;
-#endif
- void *args;
- int *retval;
-{
- register struct a {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6;
- } *uap = (struct a *)args;
-#else /* AFS_OSF_ENV */
-#ifdef AFS_LINUX20_ENV
-struct afssysargs {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6; /* not actually used - should be removed */
-};
-/* Linux system calls only set up for 5 arguments. */
-asmlinkage long
-afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4)
-{
- struct afssysargs args, *uap = &args;
- long linux_ret = 0;
- long *retval = &linux_ret;
- long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */
-#ifdef AFS_SPARC64_LINUX24_ENV
- afs_int32 eparm32[4];
-#endif
- /* eparm is also used by AFSCALL_CALL in afsd.c */
-#else
-#if defined(UKERNEL)
-Afs_syscall()
-{
- register struct a {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6;
- } *uap = (struct a *)u.u_ap;
-#else /* UKERNEL */
-int
-#if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
-afs_syscall()
-#else
-Afs_syscall()
-#endif /* SUN && !SUN5 */
-{
- register struct a {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6;
- } *uap = (struct a *)u.u_ap;
-#endif /* UKERNEL */
-#if defined(AFS_DEC_ENV)
- int *retval = &u.u_r.r_val1;
-#elif defined(AFS_HPUX_ENV)
- long *retval = &u.u_rval1;
-#else
- int *retval = &u.u_rval1;
-#endif
-#endif /* AFS_LINUX20_ENV */
-#endif /* AFS_OSF_ENV */
-#endif /* AFS_SUN5_ENV */
- register int code = 0;
-
- AFS_STATCNT(afs_syscall);
-#ifdef AFS_SUN5_ENV
- rvp->r_vals = 0;
- if (!afs_sinited) {
- return (ENODEV);
- }
-#endif
-#ifdef AFS_LINUX20_ENV
- lock_kernel();
- /* setup uap for use below - pull out the magic decoder ring to know
- * which syscalls have folded argument lists.
- */
- uap->syscall = syscall;
- uap->parm1 = parm1;
- uap->parm2 = parm2;
- uap->parm3 = parm3;
- if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) {
-#ifdef AFS_SPARC64_LINUX24_ENV
-/* from arch/sparc64/kernel/sys_sparc32.c */
-#define AA(__x) \
-({ unsigned long __ret; \
- __asm__ ("srl %0, 0, %0" \
- : "=r" (__ret) \
- : "0" (__x)); \
- __ret; \
-})
-
-
- if (current->thread.flags & SPARC_FLAG_32BIT) {
- AFS_COPYIN((char *)parm4, (char *)eparm32, sizeof(eparm32), code);
- eparm[0] = AA(eparm32[0]);
- eparm[1] = AA(eparm32[1]);
- eparm[2] = AA(eparm32[2]);
-#undef AA
- } else
-#endif
- AFS_COPYIN((char *)parm4, (char *)eparm, sizeof(eparm), code);
- uap->parm4 = eparm[0];
- uap->parm5 = eparm[1];
- uap->parm6 = eparm[2];
- } else {
- uap->parm4 = parm4;
- uap->parm5 = 0;
- uap->parm6 = 0;
- }
-#endif
-
-#if defined(AFS_HPUX_ENV)
- /*
- * There used to be code here (duplicated from osi_Init()) for
- * initializing the semaphore used by AFS_GLOCK(). Was the
- * duplication to handle the case of a dynamically loaded kernel
- * module?
- */
- osi_InitGlock();
-#endif
- if (uap->syscall == AFSCALL_CALL) {
-#ifdef AFS_SUN5_ENV
- code =
- afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5, uap->parm6, rvp, CRED());
-#else
- code =
- afs_syscall_call(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5, uap->parm6);
-#endif
- } else if (uap->syscall == AFSCALL_SETPAG) {
-#ifdef AFS_SUN5_ENV
- register proc_t *procp;
-
- procp = ttoproc(curthread);
- AFS_GLOCK();
- code = afs_setpag(&procp->p_cred);
- AFS_GUNLOCK();
-#else
- AFS_GLOCK();
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- code = afs_setpag(p, args, retval);
-#else /* AFS_OSF_ENV */
- code = afs_setpag();
-#endif
- AFS_GUNLOCK();
-#endif
- } else if (uap->syscall == AFSCALL_PIOCTL) {
- AFS_GLOCK();
-#if defined(AFS_SUN5_ENV)
- code =
- afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- rvp, CRED());
-#elif defined(AFS_FBSD50_ENV)
- code =
- afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- p->td_ucred);
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- code =
- afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- p->p_cred->pc_ucred);
-#else
- code =
- afs_syscall_pioctl(uap->parm1, uap->parm2, uap->parm3,
- uap->parm4);
-#endif
- AFS_GUNLOCK();
- } else if (uap->syscall == AFSCALL_ICREATE) {
- struct iparam iparams;
-
- code = copyin_iparam((char *)uap->parm3, &iparams);
- if (code) {
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- } else
-#ifdef AFS_SUN5_ENV
- code =
- afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
- iparams.param2, iparams.param3,
- iparams.param4, rvp, CRED());
-#else
- code =
- afs_syscall_icreate(uap->parm1, uap->parm2, iparams.param1,
- iparams.param2,
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- iparams.param3, iparams.param4, retval);
-#else
- iparams.param3, iparams.param4);
-#endif
-#endif /* AFS_SUN5_ENV */
- } else if (uap->syscall == AFSCALL_IOPEN) {
-#ifdef AFS_SUN5_ENV
- code =
- afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, rvp,
- CRED());
-#else
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3, retval);
-#else
- code = afs_syscall_iopen(uap->parm1, uap->parm2, uap->parm3);
-#endif
-#endif /* AFS_SUN5_ENV */
- } else if (uap->syscall == AFSCALL_IDEC) {
-#ifdef AFS_SUN5_ENV
- code =
- afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1, rvp,
- CRED());
-#else
- code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, -1);
-#endif /* AFS_SUN5_ENV */
- } else if (uap->syscall == AFSCALL_IINC) {
-#ifdef AFS_SUN5_ENV
- code =
- afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1, rvp,
- CRED());
-#else
- code = afs_syscall_iincdec(uap->parm1, uap->parm2, uap->parm3, 1);
-#endif /* AFS_SUN5_ENV */
- } else if (uap->syscall == AFSCALL_ICL) {
- AFS_GLOCK();
- code =
- Afscall_icl(uap->parm1, uap->parm2, uap->parm3, uap->parm4,
- uap->parm5, retval);
- AFS_GUNLOCK();
-#ifdef AFS_LINUX20_ENV
- if (!code) {
- /* ICL commands can return values. */
- code = -linux_ret; /* Gets negated again at exit below */
- }
-#else
- if (code) {
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- }
-#endif /* !AFS_LINUX20_ENV */
- } else {
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(EINVAL);
-#else
- code = EINVAL;
-#endif
- }
-
-#ifdef AFS_LINUX20_ENV
- code = -code;
- unlock_kernel();
-#endif
- return code;
-}
-#endif /* AFS_SGI_ENV */
-#endif /* !AFS_AIX32_ENV */
-
-/*
- * Initstate in the range 0 < x < 100 are early initialization states.
- * Initstate of 100 means a AFSOP_START operation has been done. After this,
- * the cache may be initialized.
- * Initstate of 101 means a AFSOP_GO operation has been done. This operation
- * is done after all the cache initialization has been done.
- * Initstate of 200 means that the volume has been looked up once, possibly
- * incorrectly.
- * Initstate of 300 means that the volume has been *successfully* looked up.
- */
-int
-afs_CheckInit(void)
-{
- register int code = 0;
-
- AFS_STATCNT(afs_CheckInit);
- if (afs_initState <= 100)
- code = ENXIO; /* never finished init phase */
- else if (afs_initState == 101) { /* init done, wait for afs_daemon */
- while (afs_initState < 200)
- afs_osi_Sleep(&afs_initState);
- } else if (afs_initState == 200)
- code = ETIMEDOUT; /* didn't find root volume */
- return code;
-}
-
-int afs_shuttingdown = 0;
-void
-afs_shutdown(void)
-{
- extern short afs_brsDaemons;
- extern afs_int32 afs_CheckServerDaemonStarted;
- extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
- extern struct osi_file *afs_cacheInodep;
-
- AFS_STATCNT(afs_shutdown);
- if (afs_shuttingdown)
- return;
- afs_shuttingdown = 1;
- if (afs_cold_shutdown)
- afs_warn("COLD ");
- else
- afs_warn("WARM ");
- afs_warn("shutting down of: CB... ");
-
- afs_termState = AFSOP_STOP_RXCALLBACK;
- rx_WakeupServerProcs();
- /* shutdown_rxkernel(); */
- while (afs_termState == AFSOP_STOP_RXCALLBACK)
- afs_osi_Sleep(&afs_termState);
-
- afs_warn("afs... ");
- while (afs_termState == AFSOP_STOP_AFS) {
- afs_osi_CancelWait(&AFS_WaitHandler);
- afs_osi_Sleep(&afs_termState);
- }
- if (afs_CheckServerDaemonStarted) {
- while (afs_termState == AFSOP_STOP_CS) {
- afs_osi_CancelWait(&AFS_CSWaitHandler);
- afs_osi_Sleep(&afs_termState);
- }
- }
- afs_warn("BkG... ");
- /* Wake-up afs_brsDaemons so that we don't have to wait for a bkg job! */
- while (afs_termState == AFSOP_STOP_BKG) {
- afs_osi_Wakeup(&afs_brsDaemons);
- afs_osi_Sleep(&afs_termState);
- }
- afs_warn("CTrunc... ");
- /* Cancel cache truncate daemon. */
- while (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
- afs_osi_Wakeup((char *)&afs_CacheTruncateDaemon);
- afs_osi_Sleep(&afs_termState);
- }
-#ifdef AFS_AFSDB_ENV
- afs_warn("AFSDB... ");
- afs_StopAFSDB();
- while (afs_termState == AFSOP_STOP_AFSDB)
- afs_osi_Sleep(&afs_termState);
-#endif
-#if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
- afs_warn("RxEvent... ");
- /* cancel rx event daemon */
- while (afs_termState == AFSOP_STOP_RXEVENT)
- afs_osi_Sleep(&afs_termState);
-#if defined(RXK_LISTENER_ENV)
-#ifndef UKERNEL
- afs_warn("UnmaskRxkSignals... ");
- afs_osi_UnmaskRxkSignals();
-#endif
- /* cancel rx listener */
- afs_warn("RxListener... ");
- osi_StopListener(); /* This closes rx_socket. */
- while (afs_termState == AFSOP_STOP_RXK_LISTENER) {
- afs_warn("Sleep... ");
- afs_osi_Sleep(&afs_termState);
- }
-#endif
-#else
- afs_termState = AFSOP_STOP_COMPLETE;
-#endif
- afs_warn("\n");
-
- /* Close file only after daemons which can write to it are stopped. */
- if (afs_cacheInodep) { /* memcache won't set this */
- osi_UFSClose(afs_cacheInodep); /* Since we always leave it open */
- afs_cacheInodep = 0;
- }
- return; /* Just kill daemons for now */
-#ifdef notdef
- shutdown_CB();
- shutdown_AFS();
- shutdown_rxkernel();
- shutdown_rxevent();
- shutdown_rx();
- afs_shutdown_BKG();
- shutdown_bufferpackage();
- shutdown_daemons();
- shutdown_cache();
- shutdown_osi();
- shutdown_osinet();
- shutdown_osifile();
- shutdown_vnodeops();
- shutdown_vfsops();
- shutdown_exporter();
- shutdown_memcache();
-#if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
-#if !defined(AFS_DEC_ENV) && !defined(AFS_OSF_ENV)
- /* this routine does not exist in Ultrix systems... 93.01.19 */
- shutdown_nfsclnt();
-#endif /* AFS_DEC_ENV */
-#endif
- shutdown_afstest();
- /* The following hold the cm stats */
-/*
- memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));
- memset(&afs_stats_cmperf, 0, sizeof(struct afs_stats_CMPerf));
- memset(&afs_stats_cmfullperf, 0, sizeof(struct afs_stats_CMFullPerf));
-*/
- afs_warn(" ALL allocated tables\n");
- afs_shuttingdown = 0;
-#endif
-}
-
-void
-shutdown_afstest(void)
-{
- AFS_STATCNT(shutdown_afstest);
- afs_initState = afs_termState = afs_setTime = 0;
- AFS_Running = afs_CB_Running = 0;
- afs_CacheInit_Done = afs_Go_Done = 0;
- if (afs_cold_shutdown) {
- *afs_rootVolumeName = 0;
- }
-}
-
-
-/* In case there is a bunch of dynamically build bkg daemons to free */
-void
-afs_shutdown_BKG(void)
-{
- AFS_STATCNT(shutdown_BKG);
-}
-
-
-#if defined(AFS_ALPHA_ENV) || defined(AFS_SGI61_ENV)
-/* For SGI 6.2, this can is changed to 1 if it's a 32 bit kernel. */
-#if defined(AFS_SGI62_ENV) && defined(KERNEL) && !defined(_K64U64)
-int afs_icl_sizeofLong = 1;
-#else
-int afs_icl_sizeofLong = 2;
-#endif /* SGI62 */
-#else
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
-int afs_icl_sizeofLong = 2;
-#else
-int afs_icl_sizeofLong = 1;
-#endif
-#endif
-
-int afs_icl_inited = 0;
-
-/* init function, called once, under afs_icl_lock */
-int
-afs_icl_Init(void)
-{
- afs_icl_inited = 1;
- return 0;
-}
-
-extern struct afs_icl_log *afs_icl_FindLog();
-extern struct afs_icl_set *afs_icl_FindSet();
-
-
-static int
-Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval)
-{
- afs_int32 *lp, elts, flags;
- register afs_int32 code;
- struct afs_icl_log *logp;
- struct afs_icl_set *setp;
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- size_t temp;
-#else /* AFS_SGI61_ENV */
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- afs_uint64 temp;
-#else
- afs_uint32 temp;
-#endif
-#endif /* AFS_SGI61_ENV */
- char tname[65];
- afs_int32 startCookie;
- afs_int32 allocated;
- struct afs_icl_log *tlp;
-
-#ifdef AFS_SUN5_ENV
- if (!afs_suser(CRED())) { /* only root can run this code */
- return (EACCES);
- }
-#else
- if (!afs_suser()) { /* only root can run this code */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(EACCES);
- return EACCES;
-#else
- return EPERM;
-#endif
- }
-#endif
- switch (opcode) {
- case ICL_OP_COPYOUTCLR: /* copy out data then clear */
- case ICL_OP_COPYOUT: /* copy ouy data */
- /* copyout: p1=logname, p2=&buffer, p3=size(words), p4=&cookie
- * return flags<<24 + nwords.
- * updates cookie to updated start (not end) if we had to
- * skip some records.
- */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- AFS_COPYIN((char *)p4, (char *)&startCookie, sizeof(afs_int32), code);
- if (code)
- return code;
- logp = afs_icl_FindLog(tname);
- if (!logp)
- return ENOENT;
-#define BUFFERSIZE AFS_LRALLOCSIZ
- lp = (afs_int32 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- elts = BUFFERSIZE / sizeof(afs_int32);
- if (p3 < elts)
- elts = p3;
- flags = (opcode == ICL_OP_COPYOUT) ? 0 : ICL_COPYOUTF_CLRAFTERREAD;
- code =
- afs_icl_CopyOut(logp, lp, &elts, (afs_uint32 *) & startCookie,
- &flags);
- if (code) {
- osi_FreeLargeSpace((struct osi_buffer *)lp);
- break;
- }
- AFS_COPYOUT((char *)lp, (char *)p2, elts * sizeof(afs_int32), code);
- if (code)
- goto done;
- AFS_COPYOUT((char *)&startCookie, (char *)p4, sizeof(afs_int32),
- code);
- if (code)
- goto done;
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- if (!(IS64U))
- *retval = ((long)((flags << 24) | (elts & 0xffffff))) << 32;
- else
-#endif
- *retval = (flags << 24) | (elts & 0xffffff);
- done:
- afs_icl_LogRele(logp);
- osi_FreeLargeSpace((struct osi_buffer *)lp);
- break;
-
- case ICL_OP_ENUMLOGS: /* enumerate logs */
- /* enumerate logs: p1=index, p2=&name, p3=sizeof(name), p4=&size.
- * return 0 for success, otherwise error.
- */
- for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
- if (p1-- == 0)
- break;
- }
- if (!tlp)
- return ENOENT; /* past the end of file */
- temp = strlen(tlp->name) + 1;
- if (temp > p3)
- return EINVAL;
- AFS_COPYOUT(tlp->name, (char *)p2, temp, code);
- if (!code) /* copy out size of log */
- AFS_COPYOUT((char *)&tlp->logSize, (char *)p4, sizeof(afs_int32),
- code);
- break;
-
- case ICL_OP_ENUMLOGSBYSET: /* enumerate logs by set name */
- /* enumerate logs: p1=setname, p2=index, p3=&name, p4=sizeof(name).
- * return 0 for success, otherwise error.
- */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- setp = afs_icl_FindSet(tname);
- if (!setp)
- return ENOENT;
- if (p2 > ICL_LOGSPERSET)
- return EINVAL;
- if (!(tlp = setp->logs[p2]))
- return EBADF;
- temp = strlen(tlp->name) + 1;
- if (temp > p4)
- return EINVAL;
- AFS_COPYOUT(tlp->name, (char *)p3, temp, code);
- break;
-
- case ICL_OP_CLRLOG: /* clear specified log */
- /* zero out the specified log: p1=logname */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- logp = afs_icl_FindLog(tname);
- if (!logp)
- return ENOENT;
- code = afs_icl_ZeroLog(logp);
- afs_icl_LogRele(logp);
- break;
-
- case ICL_OP_CLRSET: /* clear specified set */
- /* zero out the specified set: p1=setname */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- setp = afs_icl_FindSet(tname);
- if (!setp)
- return ENOENT;
- code = afs_icl_ZeroSet(setp);
- afs_icl_SetRele(setp);
- break;
-
- case ICL_OP_CLRALL: /* clear all logs */
- /* zero out all logs -- no args */
- code = 0;
- ObtainWriteLock(&afs_icl_lock, 178);
- for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp) {
- tlp->refCount++; /* hold this guy */
- ReleaseWriteLock(&afs_icl_lock);
- /* don't clear persistent logs */
- if ((tlp->states & ICL_LOGF_PERSISTENT) == 0)
- code = afs_icl_ZeroLog(tlp);
- ObtainWriteLock(&afs_icl_lock, 179);
- if (--tlp->refCount == 0)
- afs_icl_ZapLog(tlp);
- if (code)
- break;
- }
- ReleaseWriteLock(&afs_icl_lock);
- break;
-
- case ICL_OP_ENUMSETS: /* enumerate all sets */
- /* enumerate sets: p1=index, p2=&name, p3=sizeof(name), p4=&states.
- * return 0 for success, otherwise error.
- */
- for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
- if (p1-- == 0)
- break;
- }
- if (!setp)
- return ENOENT; /* past the end of file */
- temp = strlen(setp->name) + 1;
- if (temp > p3)
- return EINVAL;
- AFS_COPYOUT(setp->name, (char *)p2, temp, code);
- if (!code) /* copy out size of log */
- AFS_COPYOUT((char *)&setp->states, (char *)p4, sizeof(afs_int32),
- code);
- break;
-
- case ICL_OP_SETSTAT: /* set status on a set */
- /* activate the specified set: p1=setname, p2=op */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- setp = afs_icl_FindSet(tname);
- if (!setp)
- return ENOENT;
- code = afs_icl_SetSetStat(setp, p2);
- afs_icl_SetRele(setp);
- break;
-
- case ICL_OP_SETSTATALL: /* set status on all sets */
- /* activate the specified set: p1=op */
- code = 0;
- ObtainWriteLock(&afs_icl_lock, 180);
- for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
- setp->refCount++; /* hold this guy */
- ReleaseWriteLock(&afs_icl_lock);
- /* don't set states on persistent sets */
- if ((setp->states & ICL_SETF_PERSISTENT) == 0)
- code = afs_icl_SetSetStat(setp, p1);
- ObtainWriteLock(&afs_icl_lock, 181);
- if (--setp->refCount == 0)
- afs_icl_ZapSet(setp);
- if (code)
- break;
- }
- ReleaseWriteLock(&afs_icl_lock);
- break;
-
- case ICL_OP_SETLOGSIZE: /* set size of log */
- /* set the size of the specified log: p1=logname, p2=size (in words) */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- logp = afs_icl_FindLog(tname);
- if (!logp)
- return ENOENT;
- code = afs_icl_LogSetSize(logp, p2);
- afs_icl_LogRele(logp);
- break;
-
- case ICL_OP_GETLOGINFO: /* get size of log */
- /* zero out the specified log: p1=logname, p2=&logSize, p3=&allocated */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- logp = afs_icl_FindLog(tname);
- if (!logp)
- return ENOENT;
- allocated = !!logp->datap;
- AFS_COPYOUT((char *)&logp->logSize, (char *)p2, sizeof(afs_int32),
- code);
- if (!code)
- AFS_COPYOUT((char *)&allocated, (char *)p3, sizeof(afs_int32),
- code);
- afs_icl_LogRele(logp);
- break;
-
- case ICL_OP_GETSETINFO: /* get state of set */
- /* zero out the specified set: p1=setname, p2=&state */
- AFS_COPYINSTR((char *)p1, tname, sizeof(tname), &temp, code);
- if (code)
- return code;
- setp = afs_icl_FindSet(tname);
- if (!setp)
- return ENOENT;
- AFS_COPYOUT((char *)&setp->states, (char *)p2, sizeof(afs_int32),
- code);
- afs_icl_SetRele(setp);
- break;
-
- default:
- code = EINVAL;
- }
-
- return code;
-}
-
-
-afs_lock_t afs_icl_lock;
-
-/* exported routine: a 4 parameter event */
-int
-afs_icl_Event4(register struct afs_icl_set *setp, afs_int32 eventID,
- afs_int32 lAndT, long p1, long p2, long p3, long p4)
-{
- afs_int32 mask;
- register int i;
- register afs_int32 tmask;
- int ix;
-
- /* If things aren't init'ed yet (or the set is inactive), don't panic */
- if (!ICL_SETACTIVE(setp))
- return 0;
-
- AFS_ASSERT_GLOCK();
- mask = lAndT >> 24 & 0xff; /* mask of which logs to log to */
- ix = ICL_EVENTBYTE(eventID);
- ObtainReadLock(&setp->lock);
- if (setp->eventFlags[ix] & ICL_EVENTMASK(eventID)) {
- for (i = 0, tmask = 1; i < ICL_LOGSPERSET; i++, tmask <<= 1) {
- if (mask & tmask) {
- afs_icl_AppendRecord(setp->logs[i], eventID, lAndT & 0xffffff,
- p1, p2, p3, p4);
- }
- mask &= ~tmask;
- if (mask == 0)
- break; /* break early */
- }
- }
- ReleaseReadLock(&setp->lock);
- return 0;
-}
-
-/* Next 4 routines should be implemented via var-args or something.
- * Whole purpose is to avoid compiler warnings about parameter # mismatches.
- * Otherwise, could call afs_icl_Event4 directly.
- */
-int
-afs_icl_Event3(register struct afs_icl_set *setp, afs_int32 eventID,
- afs_int32 lAndT, long p1, long p2, long p3)
-{
- return afs_icl_Event4(setp, eventID, lAndT, p1, p2, p3, (long)0);
-}
-
-int
-afs_icl_Event2(register struct afs_icl_set *setp, afs_int32 eventID,
- afs_int32 lAndT, long p1, long p2)
-{
- return afs_icl_Event4(setp, eventID, lAndT, p1, p2, (long)0, (long)0);
-}
-
-int
-afs_icl_Event1(register struct afs_icl_set *setp, afs_int32 eventID,
- afs_int32 lAndT, long p1)
-{
- return afs_icl_Event4(setp, eventID, lAndT, p1, (long)0, (long)0,
- (long)0);
-}
-
-int
-afs_icl_Event0(register struct afs_icl_set *setp, afs_int32 eventID,
- afs_int32 lAndT)
-{
- return afs_icl_Event4(setp, eventID, lAndT, (long)0, (long)0, (long)0,
- (long)0);
-}
-
-struct afs_icl_log *afs_icl_allLogs = 0;
-
-/* function to purge records from the start of the log, until there
- * is at least minSpace long's worth of space available without
- * making the head and the tail point to the same word.
- *
- * Log must be write-locked.
- */
-static void
-afs_icl_GetLogSpace(register struct afs_icl_log *logp, afs_int32 minSpace)
-{
- register unsigned int tsize;
-
- while (logp->logSize - logp->logElements <= minSpace) {
- /* eat a record */
- tsize = ((logp->datap[logp->firstUsed]) >> 24) & 0xff;
- logp->logElements -= tsize;
- logp->firstUsed += tsize;
- if (logp->firstUsed >= logp->logSize)
- logp->firstUsed -= logp->logSize;
- logp->baseCookie += tsize;
- }
-}
-
-/* append string astr to buffer, including terminating null char.
- *
- * log must be write-locked.
- */
-#define ICL_CHARSPERLONG 4
-static void
-afs_icl_AppendString(struct afs_icl_log *logp, char *astr)
-{
- char *op; /* ptr to char to write */
- int tc;
- register int bib; /* bytes in buffer */
-
- bib = 0;
- op = (char *)&(logp->datap[logp->firstFree]);
- while (1) {
- tc = *astr++;
- *op++ = tc;
- if (++bib >= ICL_CHARSPERLONG) {
- /* new word */
- bib = 0;
- if (++(logp->firstFree) >= logp->logSize) {
- logp->firstFree = 0;
- op = (char *)&(logp->datap[0]);
- }
- logp->logElements++;
- }
- if (tc == 0)
- break;
- }
- if (bib > 0) {
- /* if we've used this word at all, allocate it */
- if (++(logp->firstFree) >= logp->logSize) {
- logp->firstFree = 0;
- }
- logp->logElements++;
- }
-}
-
-/* add a long to the log, ignoring overflow (checked already) */
-#define ICL_APPENDINT32(lp, x) \
- MACRO_BEGIN \
- (lp)->datap[(lp)->firstFree] = (x); \
- if (++((lp)->firstFree) >= (lp)->logSize) { \
- (lp)->firstFree = 0; \
- } \
- (lp)->logElements++; \
- MACRO_END
-
-#if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
-#define ICL_APPENDLONG(lp, x) \
- MACRO_BEGIN \
- ICL_APPENDINT32((lp), ((x) >> 32) & 0xffffffffL); \
- ICL_APPENDINT32((lp), (x) & 0xffffffffL); \
- MACRO_END
-
-#else /* AFS_ALPHA_ENV */
-#define ICL_APPENDLONG(lp, x) ICL_APPENDINT32((lp), (x))
-#endif /* AFS_ALPHA_ENV */
-
-/* routine to tell whether we're dealing with the address or the
- * object itself
- */
-int
-afs_icl_UseAddr(int type)
-{
- if (type == ICL_TYPE_HYPER || type == ICL_TYPE_STRING
- || type == ICL_TYPE_FID || type == ICL_TYPE_INT64)
- return 1;
- else
- return 0;
-}
-
-/* Function to append a record to the log. Written for speed
- * since we know that we're going to have to make this work fast
- * pretty soon, anyway. The log must be unlocked.
- */
-
-void
-afs_icl_AppendRecord(register struct afs_icl_log *logp, afs_int32 op,
- afs_int32 types, long p1, long p2, long p3, long p4)
-{
- int rsize; /* record size in longs */
- register int tsize; /* temp size */
- osi_timeval_t tv;
- int t1, t2, t3, t4;
-
- t4 = types & 0x3f; /* decode types */
- types >>= 6;
- t3 = types & 0x3f;
- types >>= 6;
- t2 = types & 0x3f;
- types >>= 6;
- t1 = types & 0x3f;
-
- osi_GetTime(&tv); /* It panics for solaris if inside */
- ObtainWriteLock(&logp->lock, 182);
- if (!logp->datap) {
- ReleaseWriteLock(&logp->lock);
- return;
- }
-
- /* get timestamp as # of microseconds since some time that doesn't
- * change that often. This algorithm ticks over every 20 minutes
- * or so (1000 seconds). Write a timestamp record if it has.
- */
- if (tv.tv_sec - logp->lastTS > 1024) {
- /* the timer has wrapped -- write a timestamp record */
- if (logp->logSize - logp->logElements <= 5)
- afs_icl_GetLogSpace(logp, 5);
-
- ICL_APPENDINT32(logp,
- (afs_int32) (5 << 24) + (ICL_TYPE_UNIXDATE << 18));
- ICL_APPENDINT32(logp, (afs_int32) ICL_INFO_TIMESTAMP);
- ICL_APPENDINT32(logp, (afs_int32) 0); /* use thread ID zero for clocks */
- ICL_APPENDINT32(logp,
- (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 +
- tv.tv_usec);
- ICL_APPENDINT32(logp, (afs_int32) tv.tv_sec);
-
- logp->lastTS = tv.tv_sec;
- }
-
- rsize = 4; /* base case */
- if (t1) {
- /* compute size of parameter p1. Only tricky case is string.
- * In that case, we have to call strlen to get the string length.
- */
- ICL_SIZEHACK(t1, p1);
- }
- if (t2) {
- /* compute size of parameter p2. Only tricky case is string.
- * In that case, we have to call strlen to get the string length.
- */
- ICL_SIZEHACK(t2, p2);
- }
- if (t3) {
- /* compute size of parameter p3. Only tricky case is string.
- * In that case, we have to call strlen to get the string length.
- */
- ICL_SIZEHACK(t3, p3);
- }
- if (t4) {
- /* compute size of parameter p4. Only tricky case is string.
- * In that case, we have to call strlen to get the string length.
- */
- ICL_SIZEHACK(t4, p4);
- }
-
- /* At this point, we've computed all of the parameter sizes, and
- * have in rsize the size of the entire record we want to append.
- * Next, we check that we actually have room in the log to do this
- * work, and then we do the append.
- */
- if (rsize > 255) {
- ReleaseWriteLock(&logp->lock);
- return; /* log record too big to express */
- }
-
- if (logp->logSize - logp->logElements <= rsize)
- afs_icl_GetLogSpace(logp, rsize);
-
- ICL_APPENDINT32(logp,
- (afs_int32) (rsize << 24) + (t1 << 18) + (t2 << 12) +
- (t3 << 6) + t4);
- ICL_APPENDINT32(logp, (afs_int32) op);
- ICL_APPENDINT32(logp, (afs_int32) osi_ThreadUnique());
- ICL_APPENDINT32(logp,
- (afs_int32) (tv.tv_sec & 0x3ff) * 1000000 + tv.tv_usec);
-
- if (t1) {
- /* marshall parameter 1 now */
- if (t1 == ICL_TYPE_STRING) {
- afs_icl_AppendString(logp, (char *)p1);
- } else if (t1 == ICL_TYPE_HYPER) {
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p1)->high);
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p1)->low);
- } else if (t1 == ICL_TYPE_INT64) {
-#ifdef AFSLITTLE_ENDIAN
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) p1);
- ICL_APPENDINT32(logp, (afs_int32) 0);
-#endif /* AFS_64BIT_CLIENT */
-#else /* AFSLITTLE_ENDIAN */
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) 0);
- ICL_APPENDINT32(logp, (afs_int32) p1);
-#endif /* AFS_64BIT_CLIENT */
-#endif /* AFSLITTLE_ENDIAN */
- } else if (t1 == ICL_TYPE_FID) {
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[2]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p1)[3]);
- }
-#if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
- else if (t1 == ICL_TYPE_INT32)
- ICL_APPENDINT32(logp, (afs_int32) p1);
-#endif /* AFS_ALPHA_ENV */
- else
- ICL_APPENDLONG(logp, p1);
- }
- if (t2) {
- /* marshall parameter 2 now */
- if (t2 == ICL_TYPE_STRING)
- afs_icl_AppendString(logp, (char *)p2);
- else if (t2 == ICL_TYPE_HYPER) {
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p2)->high);
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p2)->low);
- } else if (t2 == ICL_TYPE_INT64) {
-#ifdef AFSLITTLE_ENDIAN
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) p2);
- ICL_APPENDINT32(logp, (afs_int32) 0);
-#endif /* AFS_64BIT_CLIENT */
-#else /* AFSLITTLE_ENDIAN */
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) 0);
- ICL_APPENDINT32(logp, (afs_int32) p2);
-#endif /* AFS_64BIT_CLIENT */
-#endif /* AFSLITTLE_ENDIAN */
- } else if (t2 == ICL_TYPE_FID) {
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[2]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p2)[3]);
- }
-#if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
- else if (t2 == ICL_TYPE_INT32)
- ICL_APPENDINT32(logp, (afs_int32) p2);
-#endif /* AFS_ALPHA_ENV */
- else
- ICL_APPENDLONG(logp, p2);
- }
- if (t3) {
- /* marshall parameter 3 now */
- if (t3 == ICL_TYPE_STRING)
- afs_icl_AppendString(logp, (char *)p3);
- else if (t3 == ICL_TYPE_HYPER) {
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p3)->high);
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p3)->low);
- } else if (t3 == ICL_TYPE_INT64) {
-#ifdef AFSLITTLE_ENDIAN
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) p3);
- ICL_APPENDINT32(logp, (afs_int32) 0);
-#endif /* AFS_64BIT_CLIENT */
-#else /* AFSLITTLE_ENDIAN */
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) 0);
- ICL_APPENDINT32(logp, (afs_int32) p3);
-#endif /* AFS_64BIT_CLIENT */
-#endif /* AFSLITTLE_ENDIAN */
- } else if (t3 == ICL_TYPE_FID) {
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[2]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p3)[3]);
- }
-#if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
- else if (t3 == ICL_TYPE_INT32)
- ICL_APPENDINT32(logp, (afs_int32) p3);
-#endif /* AFS_ALPHA_ENV */
- else
- ICL_APPENDLONG(logp, p3);
- }
- if (t4) {
- /* marshall parameter 4 now */
- if (t4 == ICL_TYPE_STRING)
- afs_icl_AppendString(logp, (char *)p4);
- else if (t4 == ICL_TYPE_HYPER) {
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p4)->high);
- ICL_APPENDINT32(logp,
- (afs_int32) ((struct afs_hyper_t *)p4)->low);
- } else if (t4 == ICL_TYPE_INT64) {
-#ifdef AFSLITTLE_ENDIAN
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) p4);
- ICL_APPENDINT32(logp, (afs_int32) 0);
-#endif /* AFS_64BIT_CLIENT */
-#else /* AFSLITTLE_ENDIAN */
-#ifdef AFS_64BIT_CLIENT
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
-#else /* AFS_64BIT_CLIENT */
- ICL_APPENDINT32(logp, (afs_int32) 0);
- ICL_APPENDINT32(logp, (afs_int32) p4);
-#endif /* AFS_64BIT_CLIENT */
-#endif /* AFSLITTLE_ENDIAN */
- } else if (t4 == ICL_TYPE_FID) {
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[0]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[1]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[2]);
- ICL_APPENDINT32(logp, (afs_int32) ((afs_int32 *) p4)[3]);
- }
-#if defined(AFS_ALPHA_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
- else if (t4 == ICL_TYPE_INT32)
- ICL_APPENDINT32(logp, (afs_int32) p4);
-#endif /* AFS_ALPHA_ENV */
- else
- ICL_APPENDLONG(logp, p4);
- }
- ReleaseWriteLock(&logp->lock);
-}
-
-/* create a log with size logSize; return it in *outLogpp and tag
- * it with name "name."
- */
-int
-afs_icl_CreateLog(char *name, afs_int32 logSize,
- struct afs_icl_log **outLogpp)
-{
- return afs_icl_CreateLogWithFlags(name, logSize, /*flags */ 0, outLogpp);
-}
-
-/* create a log with size logSize; return it in *outLogpp and tag
- * it with name "name." 'flags' can be set to make the log unclearable.
- */
-int
-afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize, afs_uint32 flags,
- struct afs_icl_log **outLogpp)
-{
- register struct afs_icl_log *logp;
-
- /* add into global list under lock */
- ObtainWriteLock(&afs_icl_lock, 183);
- if (!afs_icl_inited)
- afs_icl_Init();
-
- for (logp = afs_icl_allLogs; logp; logp = logp->nextp) {
- if (strcmp(logp->name, name) == 0) {
- /* found it already created, just return it */
- logp->refCount++;
- *outLogpp = logp;
- if (flags & ICL_CRLOG_FLAG_PERSISTENT) {
- ObtainWriteLock(&logp->lock, 184);
- logp->states |= ICL_LOGF_PERSISTENT;
- ReleaseWriteLock(&logp->lock);
- }
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
- }
- }
-
- logp = (struct afs_icl_log *)
- osi_AllocSmallSpace(sizeof(struct afs_icl_log));
- memset((caddr_t) logp, 0, sizeof(*logp));
-
- logp->refCount = 1;
- logp->name = osi_AllocSmallSpace(strlen(name) + 1);
- strcpy(logp->name, name);
- LOCK_INIT(&logp->lock, "logp lock");
- logp->logSize = logSize;
- logp->datap = NULL; /* don't allocate it until we need it */
-
- if (flags & ICL_CRLOG_FLAG_PERSISTENT)
- logp->states |= ICL_LOGF_PERSISTENT;
-
- logp->nextp = afs_icl_allLogs;
- afs_icl_allLogs = logp;
- ReleaseWriteLock(&afs_icl_lock);
-
- *outLogpp = logp;
- return 0;
-}
-
-/* called with a log, a pointer to a buffer, the size of the buffer
- * (in *bufSizep), the starting cookie (in *cookiep, use 0 at the start)
- * and returns data in the provided buffer, and returns output flags
- * in *flagsp. The flag ICL_COPYOUTF_MISSEDSOME is set if we can't
- * find the record with cookie value cookie.
- */
-int
-afs_icl_CopyOut(register struct afs_icl_log *logp, afs_int32 * bufferp,
- afs_int32 * bufSizep, afs_uint32 * cookiep,
- afs_int32 * flagsp)
-{
- afs_int32 nwords; /* number of words to copy out */
- afs_uint32 startCookie; /* first cookie to use */
- afs_int32 outWords; /* words we've copied out */
- afs_int32 inWords; /* max words to copy out */
- afs_int32 code; /* return code */
- afs_int32 ix; /* index we're copying from */
- afs_int32 outFlags; /* return flags */
- afs_int32 inFlags; /* flags passed in */
- afs_int32 end;
-
- inWords = *bufSizep; /* max to copy out */
- outWords = 0; /* amount copied out */
- startCookie = *cookiep;
- outFlags = 0;
- inFlags = *flagsp;
- code = 0;
-
- ObtainWriteLock(&logp->lock, 185);
- if (!logp->datap) {
- ReleaseWriteLock(&logp->lock);
- goto done;
- }
-
- /* first, compute the index of the start cookie we've been passed */
- while (1) {
- /* (re-)compute where we should start */
- if (startCookie < logp->baseCookie) {
- if (startCookie) /* missed some output */
- outFlags |= ICL_COPYOUTF_MISSEDSOME;
- /* skip to the first available record */
- startCookie = logp->baseCookie;
- *cookiep = startCookie;
- }
-
- /* compute where we find the first element to copy out */
- ix = logp->firstUsed + startCookie - logp->baseCookie;
- if (ix >= logp->logSize)
- ix -= logp->logSize;
-
- /* if have some data now, break out and process it */
- if (startCookie - logp->baseCookie < logp->logElements)
- break;
-
- /* At end of log, so clear it if we need to */
- if (inFlags & ICL_COPYOUTF_CLRAFTERREAD) {
- logp->firstUsed = logp->firstFree = 0;
- logp->logElements = 0;
- }
- /* otherwise, either wait for the data to arrive, or return */
- if (!(inFlags & ICL_COPYOUTF_WAITIO)) {
- ReleaseWriteLock(&logp->lock);
- code = 0;
- goto done;
- }
- logp->states |= ICL_LOGF_WAITING;
- ReleaseWriteLock(&logp->lock);
- afs_osi_Sleep(&logp->lock);
- ObtainWriteLock(&logp->lock, 186);
- }
- /* copy out data from ix to logSize or firstFree, depending
- * upon whether firstUsed <= firstFree (no wrap) or otherwise.
- * be careful not to copy out more than nwords.
- */
- if (ix >= logp->firstUsed) {
- if (logp->firstUsed <= logp->firstFree)
- /* no wrapping */
- end = logp->firstFree; /* first element not to copy */
- else
- end = logp->logSize;
- nwords = inWords; /* don't copy more than this */
- if (end - ix < nwords)
- nwords = end - ix;
- if (nwords > 0) {
- memcpy((char *)bufferp, (char *)&logp->datap[ix],
- sizeof(afs_int32) * nwords);
- outWords += nwords;
- inWords -= nwords;
- bufferp += nwords;
- }
- /* if we're going to copy more out below, we'll start here */
- ix = 0;
- }
- /* now, if active part of the log has wrapped, there's more stuff
- * starting at the head of the log. Copy out more from there.
- */
- if (logp->firstUsed > logp->firstFree && ix < logp->firstFree
- && inWords > 0) {
- /* (more to) copy out from the wrapped section at the
- * start of the log. May get here even if didn't copy any
- * above, if the cookie points directly into the wrapped section.
- */
- nwords = inWords;
- if (logp->firstFree - ix < nwords)
- nwords = logp->firstFree - ix;
- memcpy((char *)bufferp, (char *)&logp->datap[ix],
- sizeof(afs_int32) * nwords);
- outWords += nwords;
- inWords -= nwords;
- bufferp += nwords;
- }
-
- ReleaseWriteLock(&logp->lock);
-
- done:
- if (code == 0) {
- *bufSizep = outWords;
- *flagsp = outFlags;
- }
- return code;
-}
-
-/* return basic parameter information about a log */
-int
-afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
- afs_int32 * curSizep)
-{
- ObtainReadLock(&logp->lock);
- *maxSizep = logp->logSize;
- *curSizep = logp->logElements;
- ReleaseReadLock(&logp->lock);
- return 0;
-}
-
-
-/* hold and release logs */
-int
-afs_icl_LogHold(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&afs_icl_lock, 187);
- logp->refCount++;
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
-}
-
-/* hold and release logs, called with lock already held */
-int
-afs_icl_LogHoldNL(register struct afs_icl_log *logp)
-{
- logp->refCount++;
- return 0;
-}
-
-/* keep track of how many sets believe the log itself is allocated */
-int
-afs_icl_LogUse(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&logp->lock, 188);
- if (logp->setCount == 0) {
- /* this is the first set actually using the log -- allocate it */
- if (logp->logSize == 0) {
- /* we weren't passed in a hint and it wasn't set */
- logp->logSize = ICL_DEFAULT_LOGSIZE;
- }
- logp->datap =
- (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logp->logSize);
-#ifdef KERNEL_HAVE_PIN
- pin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
-#endif
- }
- logp->setCount++;
- ReleaseWriteLock(&logp->lock);
- return 0;
-}
-
-/* decrement the number of real users of the log, free if possible */
-int
-afs_icl_LogFreeUse(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&logp->lock, 189);
- if (--logp->setCount == 0) {
- /* no more users -- free it (but keep log structure around) */
- afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
-#ifdef KERNEL_HAVE_PIN
- unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
-#endif
- logp->firstUsed = logp->firstFree = 0;
- logp->logElements = 0;
- logp->datap = NULL;
- }
- ReleaseWriteLock(&logp->lock);
- return 0;
-}
-
-/* set the size of the log to 'logSize' */
-int
-afs_icl_LogSetSize(register struct afs_icl_log *logp, afs_int32 logSize)
-{
- ObtainWriteLock(&logp->lock, 190);
- if (!logp->datap) {
- /* nothing to worry about since it's not allocated */
- logp->logSize = logSize;
- } else {
- /* reset log */
- logp->firstUsed = logp->firstFree = 0;
- logp->logElements = 0;
-
- /* free and allocate a new one */
- afs_osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
-#ifdef KERNEL_HAVE_PIN
- unpin((char *)logp->datap, sizeof(afs_int32) * logp->logSize);
-#endif
- logp->datap =
- (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * logSize);
-#ifdef KERNEL_HAVE_PIN
- pin((char *)logp->datap, sizeof(afs_int32) * logSize);
-#endif
- logp->logSize = logSize;
- }
- ReleaseWriteLock(&logp->lock);
-
- return 0;
-}
-
-/* free a log. Called with afs_icl_lock locked. */
-int
-afs_icl_ZapLog(register struct afs_icl_log *logp)
-{
- register struct afs_icl_log **lpp, *tp;
-
- for (lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
- if (tp == logp) {
- /* found the dude we want to remove */
- *lpp = logp->nextp;
- osi_FreeSmallSpace(logp->name);
- osi_FreeSmallSpace(logp->datap);
- osi_FreeSmallSpace(logp);
- break; /* won't find it twice */
- }
- }
- return 0;
-}
-
-/* do the release, watching for deleted entries */
-int
-afs_icl_LogRele(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&afs_icl_lock, 191);
- if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
- afs_icl_ZapLog(logp); /* destroys logp's lock! */
- }
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
-}
-
-/* do the release, watching for deleted entries, log already held */
-int
-afs_icl_LogReleNL(register struct afs_icl_log *logp)
-{
- if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
- afs_icl_ZapLog(logp); /* destroys logp's lock! */
- }
- return 0;
-}
-
-/* zero out the log */
-int
-afs_icl_ZeroLog(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&logp->lock, 192);
- logp->firstUsed = logp->firstFree = 0;
- logp->logElements = 0;
- logp->baseCookie = 0;
- ReleaseWriteLock(&logp->lock);
- return 0;
-}
-
-/* free a log entry, and drop its reference count */
-int
-afs_icl_LogFree(register struct afs_icl_log *logp)
-{
- ObtainWriteLock(&logp->lock, 193);
- logp->states |= ICL_LOGF_DELETED;
- ReleaseWriteLock(&logp->lock);
- afs_icl_LogRele(logp);
- return 0;
-}
-
-/* find a log by name, returning it held */
-struct afs_icl_log *
-afs_icl_FindLog(char *name)
-{
- register struct afs_icl_log *tp;
- ObtainWriteLock(&afs_icl_lock, 194);
- for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
- if (strcmp(tp->name, name) == 0) {
- /* this is the dude we want */
- tp->refCount++;
- break;
- }
- }
- ReleaseWriteLock(&afs_icl_lock);
- return tp;
-}
-
-int
-afs_icl_EnumerateLogs(int (*aproc)
- (char *name, char *arock, struct afs_icl_log * tp),
- char *arock)
-{
- register struct afs_icl_log *tp;
- register afs_int32 code;
-
- code = 0;
- ObtainWriteLock(&afs_icl_lock, 195);
- for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
- tp->refCount++; /* hold this guy */
- ReleaseWriteLock(&afs_icl_lock);
- ObtainReadLock(&tp->lock);
- code = (*aproc) (tp->name, arock, tp);
- ReleaseReadLock(&tp->lock);
- ObtainWriteLock(&afs_icl_lock, 196);
- if (--tp->refCount == 0)
- afs_icl_ZapLog(tp);
- if (code)
- break;
- }
- ReleaseWriteLock(&afs_icl_lock);
- return code;
-}
-
-struct afs_icl_set *afs_icl_allSets = 0;
-
-int
-afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
- struct afs_icl_log *fatalLogp,
- struct afs_icl_set **outSetpp)
-{
- return afs_icl_CreateSetWithFlags(name, baseLogp, fatalLogp,
- /*flags */ 0, outSetpp);
-}
-
-/* create a set, given pointers to base and fatal logs, if any.
- * Logs are unlocked, but referenced, and *outSetpp is returned
- * referenced. Function bumps reference count on logs, since it
- * addds references from the new afs_icl_set. When the set is destroyed,
- * those references will be released.
- */
-int
-afs_icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
- struct afs_icl_log *fatalLogp, afs_uint32 flags,
- struct afs_icl_set **outSetpp)
-{
- register struct afs_icl_set *setp;
- register int i;
- afs_int32 states = ICL_DEFAULT_SET_STATES;
-
- ObtainWriteLock(&afs_icl_lock, 197);
- if (!afs_icl_inited)
- afs_icl_Init();
-
- for (setp = afs_icl_allSets; setp; setp = setp->nextp) {
- if (strcmp(setp->name, name) == 0) {
- setp->refCount++;
- *outSetpp = setp;
- if (flags & ICL_CRSET_FLAG_PERSISTENT) {
- ObtainWriteLock(&setp->lock, 198);
- setp->states |= ICL_SETF_PERSISTENT;
- ReleaseWriteLock(&setp->lock);
- }
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
- }
- }
-
- /* determine initial state */
- if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
- states = ICL_SETF_ACTIVE;
- else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
- states = ICL_SETF_FREED;
- if (flags & ICL_CRSET_FLAG_PERSISTENT)
- states |= ICL_SETF_PERSISTENT;
-
- setp = (struct afs_icl_set *)afs_osi_Alloc(sizeof(struct afs_icl_set));
- memset((caddr_t) setp, 0, sizeof(*setp));
- setp->refCount = 1;
- if (states & ICL_SETF_FREED)
- states &= ~ICL_SETF_ACTIVE; /* if freed, can't be active */
- setp->states = states;
-
- LOCK_INIT(&setp->lock, "setp lock");
- /* next lock is obtained in wrong order, hierarchy-wise, but
- * it doesn't matter, since no one can find this lock yet, since
- * the afs_icl_lock is still held, and thus the obtain can't block.
- */
- ObtainWriteLock(&setp->lock, 199);
- setp->name = osi_AllocSmallSpace(strlen(name) + 1);
- strcpy(setp->name, name);
- setp->nevents = ICL_DEFAULTEVENTS;
- setp->eventFlags = afs_osi_Alloc(ICL_DEFAULTEVENTS);
-#ifdef KERNEL_HAVE_PIN
- pin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
-#endif
- for (i = 0; i < ICL_DEFAULTEVENTS; i++)
- setp->eventFlags[i] = 0xff; /* default to enabled */
-
- /* update this global info under the afs_icl_lock */
- setp->nextp = afs_icl_allSets;
- afs_icl_allSets = setp;
- ReleaseWriteLock(&afs_icl_lock);
-
- /* set's basic lock is still held, so we can finish init */
- if (baseLogp) {
- setp->logs[0] = baseLogp;
- afs_icl_LogHold(baseLogp);
- if (!(setp->states & ICL_SETF_FREED))
- afs_icl_LogUse(baseLogp); /* log is actually being used */
- }
- if (fatalLogp) {
- setp->logs[1] = fatalLogp;
- afs_icl_LogHold(fatalLogp);
- if (!(setp->states & ICL_SETF_FREED))
- afs_icl_LogUse(fatalLogp); /* log is actually being used */
- }
- ReleaseWriteLock(&setp->lock);
-
- *outSetpp = setp;
- return 0;
-}
-
-/* function to change event enabling information for a particular set */
-int
-afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
-{
- char *tp;
-
- ObtainWriteLock(&setp->lock, 200);
- if (!ICL_EVENTOK(setp, eventID)) {
- ReleaseWriteLock(&setp->lock);
- return -1;
- }
- tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
- if (setValue)
- *tp |= ICL_EVENTMASK(eventID);
- else
- *tp &= ~(ICL_EVENTMASK(eventID));
- ReleaseWriteLock(&setp->lock);
- return 0;
-}
-
-/* return indication of whether a particular event ID is enabled
- * for tracing. If *getValuep is set to 0, the event is disabled,
- * otherwise it is enabled. All events start out enabled by default.
- */
-int
-afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
-{
- ObtainReadLock(&setp->lock);
- if (!ICL_EVENTOK(setp, eventID)) {
- ReleaseWriteLock(&setp->lock);
- return -1;
- }
- if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
- *getValuep = 1;
- else
- *getValuep = 0;
- ReleaseReadLock(&setp->lock);
- return 0;
-}
-
-/* hold and release event sets */
-int
-afs_icl_SetHold(register struct afs_icl_set *setp)
-{
- ObtainWriteLock(&afs_icl_lock, 201);
- setp->refCount++;
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
-}
-
-/* free a set. Called with afs_icl_lock locked */
-int
-afs_icl_ZapSet(register struct afs_icl_set *setp)
-{
- register struct afs_icl_set **lpp, *tp;
- int i;
- register struct afs_icl_log *tlp;
-
- for (lpp = &afs_icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
- if (tp == setp) {
- /* found the dude we want to remove */
- *lpp = setp->nextp;
- osi_FreeSmallSpace(setp->name);
- afs_osi_Free(setp->eventFlags, ICL_DEFAULTEVENTS);
-#ifdef KERNEL_HAVE_PIN
- unpin((char *)setp->eventFlags, ICL_DEFAULTEVENTS);
-#endif
- for (i = 0; i < ICL_LOGSPERSET; i++) {
- if ((tlp = setp->logs[i]))
- afs_icl_LogReleNL(tlp);
- }
- osi_FreeSmallSpace(setp);
- break; /* won't find it twice */
- }
- }
- return 0;
-}
-
-/* do the release, watching for deleted entries */
-int
-afs_icl_SetRele(register struct afs_icl_set *setp)
-{
- ObtainWriteLock(&afs_icl_lock, 202);
- if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
- afs_icl_ZapSet(setp); /* destroys setp's lock! */
- }
- ReleaseWriteLock(&afs_icl_lock);
- return 0;
-}
-
-/* free a set entry, dropping its reference count */
-int
-afs_icl_SetFree(register struct afs_icl_set *setp)
-{
- ObtainWriteLock(&setp->lock, 203);
- setp->states |= ICL_SETF_DELETED;
- ReleaseWriteLock(&setp->lock);
- afs_icl_SetRele(setp);
- return 0;
-}
-
-/* find a set by name, returning it held */
-struct afs_icl_set *
-afs_icl_FindSet(char *name)
-{
- register struct afs_icl_set *tp;
- ObtainWriteLock(&afs_icl_lock, 204);
- for (tp = afs_icl_allSets; tp; tp = tp->nextp) {
- if (strcmp(tp->name, name) == 0) {
- /* this is the dude we want */
- tp->refCount++;
- break;
- }
- }
- ReleaseWriteLock(&afs_icl_lock);
- return tp;
-}
-
-/* zero out all the logs in the set */
-int
-afs_icl_ZeroSet(struct afs_icl_set *setp)
-{
- register int i;
- int code = 0;
- int tcode;
- struct afs_icl_log *logp;
-
- ObtainReadLock(&setp->lock);
- for (i = 0; i < ICL_LOGSPERSET; i++) {
- logp = setp->logs[i];
- if (logp) {
- afs_icl_LogHold(logp);
- tcode = afs_icl_ZeroLog(logp);
- if (tcode != 0)
- code = tcode; /* save the last bad one */
- afs_icl_LogRele(logp);
- }
- }
- ReleaseReadLock(&setp->lock);
- return code;
-}
-
-int
-afs_icl_EnumerateSets(int (*aproc)
- (char *name, char *arock, struct afs_icl_log * tp),
- char *arock)
-{
- register struct afs_icl_set *tp, *np;
- register afs_int32 code;
-
- code = 0;
- ObtainWriteLock(&afs_icl_lock, 205);
- for (tp = afs_icl_allSets; tp; tp = np) {
- tp->refCount++; /* hold this guy */
- ReleaseWriteLock(&afs_icl_lock);
- code = (*aproc) (tp->name, arock, tp);
- ObtainWriteLock(&afs_icl_lock, 206);
- np = tp->nextp; /* tp may disappear next, but not np */
- if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
- afs_icl_ZapSet(tp);
- if (code)
- break;
- }
- ReleaseWriteLock(&afs_icl_lock);
- return code;
-}
-
-int
-afs_icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
-{
- register int i;
- int code = -1;
-
- ObtainWriteLock(&setp->lock, 207);
- for (i = 0; i < ICL_LOGSPERSET; i++) {
- if (!setp->logs[i]) {
- setp->logs[i] = newlogp;
- code = i;
- afs_icl_LogHold(newlogp);
- if (!(setp->states & ICL_SETF_FREED)) {
- /* bump up the number of sets using the log */
- afs_icl_LogUse(newlogp);
- }
- break;
- }
- }
- ReleaseWriteLock(&setp->lock);
- return code;
-}
-
-int
-afs_icl_SetSetStat(struct afs_icl_set *setp, int op)
-{
- int i;
- afs_int32 code;
- struct afs_icl_log *logp;
-
- ObtainWriteLock(&setp->lock, 208);
- switch (op) {
- case ICL_OP_SS_ACTIVATE: /* activate a log */
- /*
- * If we are not already active, see if we have released
- * our demand that the log be allocated (FREED set). If
- * we have, reassert our desire.
- */
- if (!(setp->states & ICL_SETF_ACTIVE)) {
- if (setp->states & ICL_SETF_FREED) {
- /* have to reassert desire for logs */
- for (i = 0; i < ICL_LOGSPERSET; i++) {
- logp = setp->logs[i];
- if (logp) {
- afs_icl_LogHold(logp);
- afs_icl_LogUse(logp);
- afs_icl_LogRele(logp);
- }
- }
- setp->states &= ~ICL_SETF_FREED;
- }
- setp->states |= ICL_SETF_ACTIVE;
- }
- code = 0;
- break;
-
- case ICL_OP_SS_DEACTIVATE: /* deactivate a log */
- /* this doesn't require anything beyond clearing the ACTIVE flag */
- setp->states &= ~ICL_SETF_ACTIVE;
- code = 0;
- break;
-
- case ICL_OP_SS_FREE: /* deassert design for log */
- /*
- * if we are already in this state, do nothing; otherwise
- * deassert desire for log
- */
- if (setp->states & ICL_SETF_ACTIVE)
- code = EINVAL;
- else {
- if (!(setp->states & ICL_SETF_FREED)) {
- for (i = 0; i < ICL_LOGSPERSET; i++) {
- logp = setp->logs[i];
- if (logp) {
- afs_icl_LogHold(logp);
- afs_icl_LogFreeUse(logp);
- afs_icl_LogRele(logp);
- }
- }
- setp->states |= ICL_SETF_FREED;
- }
- code = 0;
- }
- break;
-
- default:
- code = EINVAL;
- }
- ReleaseWriteLock(&setp->lock);
- return code;
-}
+++ /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
- */
-
-/*
- * afs_callback.c:
- * Exported routines (and their private support) to implement
- * the callback RPC interface.
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_callback.c,v 1.26 2004/04/16 04:57:01 kolya Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_stats.h" /*Cache Manager stats */
-#include "afs/afs_args.h"
-
-afs_int32 afs_allCBs = 0; /*Break callbacks on all objects */
-afs_int32 afs_oddCBs = 0; /*Break callbacks on dirs */
-afs_int32 afs_evenCBs = 0; /*Break callbacks received on files */
-afs_int32 afs_allZaps = 0; /*Objects entries deleted */
-afs_int32 afs_oddZaps = 0; /*Dir cache entries deleted */
-afs_int32 afs_evenZaps = 0; /*File cache entries deleted */
-afs_int32 afs_connectBacks = 0;
-
-/*
- * Some debugging aids.
- */
-static struct ltable {
- char *name;
- char *addr;
-} ltable[] = {
- {
- "afs_xvcache", (char *)&afs_xvcache}, {
- "afs_xdcache", (char *)&afs_xdcache}, {
- "afs_xserver", (char *)&afs_xserver}, {
- "afs_xvcb", (char *)&afs_xvcb}, {
- "afs_xbrs", (char *)&afs_xbrs}, {
- "afs_xcell", (char *)&afs_xcell}, {
- "afs_xconn", (char *)&afs_xconn}, {
- "afs_xuser", (char *)&afs_xuser}, {
- "afs_xvolume", (char *)&afs_xvolume}, {
- "puttofile", (char *)&afs_puttofileLock}, {
- "afs_ftf", (char *)&afs_ftf}, {
- "afs_xcbhash", (char *)&afs_xcbhash}, {
- "afs_xaxs", (char *)&afs_xaxs}, {
- "afs_xinterface", (char *)&afs_xinterface},
-#ifndef UKERNEL
- {
- "afs_xosi", (char *)&afs_xosi},
-#endif
- {
- "afs_xsrvAddr", (char *)&afs_xsrvAddr}
-};
-unsigned long lastCallBack_vnode;
-unsigned int lastCallBack_dv;
-osi_timeval_t lastCallBack_time;
-
-/* these are for storing alternate interface addresses */
-struct interfaceAddr afs_cb_interface;
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetCE
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement pulling out the contents of the i'th cache entry.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_index : Index of desired cache entry.
- * a_result : Ptr to a buffer for the given cache entry.
- *
- * Returns:
- * 0 if everything went fine,
- * 1 if we were given a bad index.
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBCacheEntry *a_result)
-{
-
- register int i; /*Loop variable */
- register struct vcache *tvc; /*Ptr to current cache entry */
- int code; /*Return code */
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
-
- AFS_STATCNT(SRXAFSCB_GetCE);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (a_index == 0)
- goto searchDone;
- a_index--;
- } /*Zip through current hash chain */
- } /*Zip through hash chains */
-
- searchDone:
- if (tvc == NULL) {
- /*Past EOF */
- code = 1;
- goto fcnDone;
- }
-
- /*
- * Copy out the located entry.
- */
- a_result->addr = afs_data_pointer_to_int32(tvc);
- a_result->cell = tvc->fid.Cell;
- a_result->netFid.Volume = tvc->fid.Fid.Volume;
- a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
- a_result->netFid.Unique = tvc->fid.Fid.Unique;
- a_result->lock.waitStates = tvc->lock.wait_states;
- a_result->lock.exclLocked = tvc->lock.excl_locked;
- a_result->lock.readersReading = tvc->lock.readers_reading;
- a_result->lock.numWaiting = tvc->lock.num_waiting;
-#if defined(INSTRUMENT_LOCKS)
- a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
- a_result->lock.pid_writer = tvc->lock.pid_writer;
- a_result->lock.src_indicator = tvc->lock.src_indicator;
-#else
- /* On osf20 , the vcache does not maintain these three fields */
- a_result->lock.pid_last_reader = 0;
- a_result->lock.pid_writer = 0;
- a_result->lock.src_indicator = 0;
-#endif /* AFS_OSF20_ENV */
-#ifdef AFS_64BIT_CLIENT
- a_result->Length = (afs_int32) tvc->m.Length & 0xffffffff;
-#else /* AFS_64BIT_CLIENT */
- a_result->Length = tvc->m.Length;
-#endif /* AFS_64BIT_CLIENT */
- a_result->DataVersion = hgetlo(tvc->m.DataVersion);
- a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
- a_result->cbExpires = tvc->cbExpires;
- a_result->refCount = VREFCOUNT(tvc);
- a_result->opens = tvc->opens;
- a_result->writers = tvc->execsOrWriters;
- a_result->mvstat = tvc->mvstat;
- a_result->states = tvc->states;
- code = 0;
-
- /*
- * Return our results.
- */
- fcnDone:
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (code);
-
-} /*SRXAFSCB_GetCE */
-
-int
-SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBCacheEntry64 *a_result)
-{
- register int i; /*Loop variable */
- register struct vcache *tvc; /*Ptr to current cache entry */
- int code; /*Return code */
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
-
- AFS_STATCNT(SRXAFSCB_GetCE64);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (a_index == 0)
- goto searchDone;
- a_index--;
- } /*Zip through current hash chain */
- } /*Zip through hash chains */
-
- searchDone:
- if (tvc == NULL) {
- /*Past EOF */
- code = 1;
- goto fcnDone;
- }
-
- /*
- * Copy out the located entry.
- */
- a_result->addr = afs_data_pointer_to_int32(tvc);
- a_result->cell = tvc->fid.Cell;
- a_result->netFid.Volume = tvc->fid.Fid.Volume;
- a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
- a_result->netFid.Unique = tvc->fid.Fid.Unique;
- a_result->lock.waitStates = tvc->lock.wait_states;
- a_result->lock.exclLocked = tvc->lock.excl_locked;
- a_result->lock.readersReading = tvc->lock.readers_reading;
- a_result->lock.numWaiting = tvc->lock.num_waiting;
-#if defined(INSTRUMENT_LOCKS)
- a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
- a_result->lock.pid_writer = tvc->lock.pid_writer;
- a_result->lock.src_indicator = tvc->lock.src_indicator;
-#else
- /* On osf20 , the vcache does not maintain these three fields */
- a_result->lock.pid_last_reader = 0;
- a_result->lock.pid_writer = 0;
- a_result->lock.src_indicator = 0;
-#endif /* AFS_OSF20_ENV */
-#ifdef AFS_64BIT_ENV
- a_result->Length = tvc->m.Length;
-#else /* AFS_64BIT_ENV */
-#ifdef AFS_64BIT_CLIENT
- a_result->Length = tvc->m.Length;
-#else /* AFS_64BIT_CLIENT */
- a_result->Length.high = 0;
- a_result->Length.low = tvc->m.Length;
-#endif /* AFS_64BIT_CLIENT */
-#endif /* AFS_64BIT_ENV */
- a_result->DataVersion = hgetlo(tvc->m.DataVersion);
- a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
- a_result->cbExpires = tvc->cbExpires;
- a_result->refCount = VREFCOUNT(tvc);
- a_result->opens = tvc->opens;
- a_result->writers = tvc->execsOrWriters;
- a_result->mvstat = tvc->mvstat;
- a_result->states = tvc->states;
- code = 0;
-
- /*
- * Return our results.
- */
- fcnDone:
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (code);
-
-} /*SRXAFSCB_GetCE64 */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetLock
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement pulling out the contents of a lock in the lock
- * table.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_index : Index of desired lock.
- * a_result : Ptr to a buffer for the given lock.
- *
- * Returns:
- * 0 if everything went fine,
- * 1 if we were given a bad index.
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBLock *a_result)
-{
- struct ltable *tl; /*Ptr to lock table entry */
- int nentries; /*Num entries in table */
- int code; /*Return code */
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
-
- AFS_STATCNT(SRXAFSCB_GetLock);
- nentries = sizeof(ltable) / sizeof(struct ltable);
- if (a_index < 0 || a_index >= nentries) {
- /*
- * Past EOF
- */
- code = 1;
- } else {
- /*
- * Found it - copy out its contents.
- */
- tl = <able[a_index];
- strcpy(a_result->name, tl->name);
- a_result->lock.waitStates =
- ((struct afs_lock *)(tl->addr))->wait_states;
- a_result->lock.exclLocked =
- ((struct afs_lock *)(tl->addr))->excl_locked;
- a_result->lock.readersReading =
- ((struct afs_lock *)(tl->addr))->readers_reading;
- a_result->lock.numWaiting =
- ((struct afs_lock *)(tl->addr))->num_waiting;
-#ifdef INSTRUMENT_LOCKS
- a_result->lock.pid_last_reader =
- ((struct afs_lock *)(tl->addr))->pid_last_reader;
- a_result->lock.pid_writer =
- ((struct afs_lock *)(tl->addr))->pid_writer;
- a_result->lock.src_indicator =
- ((struct afs_lock *)(tl->addr))->src_indicator;
-#else
- a_result->lock.pid_last_reader = 0;
- a_result->lock.pid_writer = 0;
- a_result->lock.src_indicator = 0;
-#endif
- code = 0;
- }
-
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (code);
-
-} /*SRXAFSCB_GetLock */
-
-
-/*------------------------------------------------------------------------
- * static ClearCallBack
- *
- * Description:
- * Clear out callback information for the specified file, or
- * even a whole volume. Used to worry about callback was from
- * within the particular cell or not. Now we don't bother with
- * that anymore; it's not worth the time.
- *
- * Arguments:
- * a_conn : Ptr to Rx connection involved.
- * a_fid : Ptr to AFS fid being cleared.
- *
- * Returns:
- * 0 (always)
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
-
-Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
-
- *------------------------------------------------------------------------*/
-
-static int
-ClearCallBack(register struct rx_connection *a_conn,
- register struct AFSFid *a_fid)
-{
- register struct vcache *tvc;
- register int i;
- struct VenusFid localFid;
- struct volume *tv;
-
- AFS_STATCNT(ClearCallBack);
-
- AFS_ASSERT_GLOCK();
-
- /*
- * XXXX Don't hold any server locks here because of callback protocol XXX
- */
- localFid.Cell = 0;
- localFid.Fid.Volume = a_fid->Volume;
- localFid.Fid.Vnode = a_fid->Vnode;
- localFid.Fid.Unique = a_fid->Unique;
-
- /*
- * Volume ID of zero means don't do anything.
- */
- if (a_fid->Volume != 0) {
- if (a_fid->Vnode == 0) {
- /*
- * Clear callback for the whole volume. Zip through the
- * hash chain, nullifying entries whose volume ID matches.
- */
- for (i = 0; i < VCSIZE; i++)
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->fid.Fid.Volume == a_fid->Volume) {
- tvc->callback = NULL;
- tvc->quick.stamp = 0;
- if (!localFid.Cell)
- localFid.Cell = tvc->fid.Cell;
- tvc->h1.dchint = NULL; /* invalidate hints */
- ObtainWriteLock(&afs_xcbhash, 449);
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CUnique | CBulkFetching);
- afs_allCBs++;
- if (tvc->fid.Fid.Vnode & 1)
- afs_oddCBs++;
- else
- afs_evenCBs++;
- ReleaseWriteLock(&afs_xcbhash);
- if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
- tvc->states, ICL_TYPE_INT32,
- a_fid->Volume);
- } else if ((tvc->states & CMValid)
- && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
- tvc->states &= ~CMValid;
- if (!localFid.Cell)
- localFid.Cell = tvc->mvid->Cell;
- }
- }
-
- /*
- * XXXX Don't hold any locks here XXXX
- */
- tv = afs_FindVolume(&localFid, 0);
- if (tv) {
- afs_ResetVolumeInfo(tv);
- afs_PutVolume(tv, 0);
- /* invalidate mtpoint? */
- }
- } /*Clear callbacks for whole volume */
- else {
- /*
- * Clear callbacks just for the one file.
- */
- afs_allCBs++;
- if (a_fid->Vnode & 1)
- afs_oddCBs++; /*Could do this on volume basis, too */
- else
- afs_evenCBs++; /*A particular fid was specified */
- i = VCHash(&localFid);
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->fid.Fid.Vnode == a_fid->Vnode
- && tvc->fid.Fid.Volume == a_fid->Volume
- && tvc->fid.Fid.Unique == a_fid->Unique) {
- tvc->callback = NULL;
- tvc->quick.stamp = 0;
- tvc->h1.dchint = NULL; /* invalidate hints */
- ObtainWriteLock(&afs_xcbhash, 450);
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CUnique | CBulkFetching);
- ReleaseWriteLock(&afs_xcbhash);
- if (a_fid->Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
- tvc->states, ICL_TYPE_LONG, 0);
-#ifdef CBDEBUG
- lastCallBack_vnode = afid->Vnode;
- lastCallBack_dv = tvc->mstat.DataVersion.low;
- osi_GetuTime(&lastCallBack_time);
-#endif /* CBDEBUG */
- }
- } /*Walk through hash table */
- } /*Clear callbacks for one file */
- }
-
- /*Fid has non-zero volume ID */
- /*
- * Always return a predictable value.
- */
- return (0);
-
-} /*ClearCallBack */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_CallBack
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement passing in callback information.
- * table.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_fids : Ptr to array of fids involved.
- * a_callbacks : Ptr to matching callback info for the fids.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
- struct AFSCBs *a_callbacks)
-{
- register int i; /*Loop variable */
- struct AFSFid *tfid; /*Ptr to current fid */
- register struct rx_connection *tconn; /*Call's connection */
- int code = 0;
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
-
- AFS_STATCNT(SRXAFSCB_CallBack);
- if (!(tconn = rx_ConnectionOf(a_call)))
- return (0);
- tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
-
- /*
- * For now, we ignore callbacks, since the File Server only *breaks*
- * callbacks at present.
- */
- for (i = 0; i < a_fids->AFSCBFids_len; i++)
- ClearCallBack(tconn, &tfid[i]);
-
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (0);
-
-} /*SRXAFSCB_CallBack */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_Probe
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement ``probing'' the Cache Manager, just making sure it's
- * still there.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_Probe(struct rx_call *a_call)
-{
- int code = 0;
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_Probe);
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (0);
-
-} /*SRXAFSCB_Probe */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_InitCallBackState
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement clearing all callbacks from this host.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_InitCallBackState(struct rx_call *a_call)
-{
- register int i;
- register struct vcache *tvc;
- register struct rx_connection *tconn;
- register struct rx_peer *peer;
- struct server *ts;
- int code = 0;
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
- AFS_STATCNT(SRXAFSCB_InitCallBackState);
-
- /*
- * Find the address of the host making this call
- */
- if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
-
- afs_allCBs++;
- afs_oddCBs++; /*Including any missed via create race */
- afs_evenCBs++; /*Including any missed via create race */
-
- ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
- 0);
- if (ts) {
- for (i = 0; i < VCSIZE; i++)
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->callback == ts) {
- ObtainWriteLock(&afs_xcbhash, 451);
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->states &= ~(CStatd | CUnique | CBulkFetching);
- ReleaseWriteLock(&afs_xcbhash);
- }
- }
- }
-
-
-
- /* find any volumes residing on this server and flush their state */
- {
- register struct volume *tv;
- register int j;
-
- for (i = 0; i < NVOLS; i++)
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- for (j = 0; j < MAXHOSTS; j++)
- if (tv->serverHost[j] == ts)
- afs_ResetVolumeInfo(tv);
- }
- }
- osi_dnlc_purge(); /* may be a little bit extreme */
- }
-
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (0);
-
-} /*SRXAFSCB_InitCallBackState */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_XStatsVersion
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement pulling out the xstat version number for the Cache
- * Manager.
- *
- * Arguments:
- * a_versionP : Ptr to the version number variable to set.
- *
- * Returns:
- * 0 (always)
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
-{
- int code = 0;
-
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
-
- *a_versionP = AFSCB_XSTAT_VERSION;
-
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (0);
-} /*SRXAFSCB_XStatsVersion */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetXStats
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement getting the given data collection from the extended
- * Cache Manager statistics.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_clientVersionNum : Client version number.
- * a_opCode : Desired operation.
- * a_serverVersionNumP : Ptr to version number to set.
- * a_timeP : Ptr to time value (seconds) to set.
- * a_dataArray : Ptr to variable array structure to return
- * stuff in.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
- afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
- afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
-{
- register int code; /*Return value */
- afs_int32 *dataBuffP; /*Ptr to data to be returned */
- afs_int32 dataBytes; /*Bytes in data buffer */
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
-
- /*
- * Record the time of day and the server version number.
- */
- *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
- *a_timeP = osi_Time();
-
- /*
- * Stuff the appropriate data in there (assume victory)
- */
- code = 0;
-
-#ifdef AFS_NOSTATS
- /*
- * We're not keeping stats, so just return successfully with
- * no data.
- */
- a_dataP->AFSCB_CollData_len = 0;
- a_dataP->AFSCB_CollData_val = NULL;
-#else
- switch (a_collectionNumber) {
- case AFSCB_XSTATSCOLL_CALL_INFO:
- /*
- * Pass back all the call-count-related data.
- *
- * >>> We are forced to allocate a separate area in which to
- * >>> put this stuff in by the RPC stub generator, since it
- * >>> will be freed at the tail end of the server stub code.
- */
- dataBytes = sizeof(struct afs_CMStats);
- dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
- memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
- a_dataP->AFSCB_CollData_len = dataBytes >> 2;
- a_dataP->AFSCB_CollData_val = dataBuffP;
- break;
-
- case AFSCB_XSTATSCOLL_PERF_INFO:
- /*
- * Update and then pass back all the performance-related data.
- * Note: the only performance fields that need to be computed
- * at this time are the number of accesses for this collection
- * and the current server record info.
- *
- * >>> We are forced to allocate a separate area in which to
- * >>> put this stuff in by the RPC stub generator, since it
- * >>> will be freed at the tail end of the server stub code.
- */
- afs_stats_cmperf.numPerfCalls++;
- afs_CountServers();
- dataBytes = sizeof(afs_stats_cmperf);
- dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
- memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
- a_dataP->AFSCB_CollData_len = dataBytes >> 2;
- a_dataP->AFSCB_CollData_val = dataBuffP;
- break;
-
- case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
- /*
- * Pass back the full range of performance and statistical
- * data available. We have to bring the normal performance
- * data collection up to date, then copy that data into
- * the full collection.
- *
- * >>> We are forced to allocate a separate area in which to
- * >>> put this stuff in by the RPC stub generator, since it
- * >>> will be freed at the tail end of the server stub code.
- */
- afs_stats_cmperf.numPerfCalls++;
- afs_CountServers();
- memcpy((char *)(&(afs_stats_cmfullperf.perf)),
- (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
- afs_stats_cmfullperf.numFullPerfCalls++;
-
- dataBytes = sizeof(afs_stats_cmfullperf);
- dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
- memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
- a_dataP->AFSCB_CollData_len = dataBytes >> 2;
- a_dataP->AFSCB_CollData_val = dataBuffP;
- break;
-
- default:
- /*
- * Illegal collection number.
- */
- a_dataP->AFSCB_CollData_len = 0;
- a_dataP->AFSCB_CollData_val = NULL;
- code = 1;
- } /*Switch on collection number */
-#endif /* AFS_NOSTATS */
-
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return (code);
-
-} /*SRXAFSCB_GetXStats */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED afs_RXCallBackServer
- *
- * Description:
- * Body of the thread supporting callback services.
- *
- * Arguments:
- * None.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-afs_RXCallBackServer(void)
-{
- AFS_STATCNT(afs_RXCallBackServer);
-
- while (1) {
- if (afs_server)
- break;
- afs_osi_Sleep(&afs_server);
- }
-
- /*
- * Donate this process to Rx.
- */
- rx_ServerProc();
- return (0);
-
-} /*afs_RXCallBackServer */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED shutdown_CB
- *
- * Description:
- * Zero out important Cache Manager data structures.
- *
- * Arguments:
- * None.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-shutdown_CB(void)
-{
- AFS_STATCNT(shutdown_CB);
-
- if (afs_cold_shutdown) {
- afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
- afs_evenZaps = afs_connectBacks = 0;
- }
-
- return (0);
-
-} /*shutdown_CB */
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_InitCallBackState2
- *
- * Description:
- * This routine was used in the AFS 3.5 beta release, but not anymore.
- * It has since been replaced by SRXAFSCB_InitCallBackState3.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- *
- * Returns:
- * RXGEN_OPCODE (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * None
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
- struct interfaceAddr *addr)
-{
- return RXGEN_OPCODE;
-}
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_WhoAreYou
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * obtain a unique identifier for the client. The server uses
- * this identifier to figure out whether or not two RX connections
- * are from the same client, and to find out which addresses go
- * with which clients.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * addr: Ptr to return the list of interfaces for this client.
- *
- * Returns:
- * 0 (Always)
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
-{
- int i;
- int code = 0;
-
- RX_AFS_GLOCK();
-
- AFS_STATCNT(SRXAFSCB_WhoAreYou);
-
- memset(addr, 0, sizeof(*addr));
-
- ObtainReadLock(&afs_xinterface);
-
- /* return all network interface addresses */
- addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
- addr->uuid = afs_cb_interface.uuid;
- for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
- addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
- addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
- addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
- }
-
- ReleaseReadLock(&afs_xinterface);
-
- RX_AFS_GUNLOCK();
-
- return code;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_InitCallBackState3
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement clearing all callbacks from this host.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- *
- * Returns:
- * 0 (always).
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
-{
- int code;
-
- /*
- * TBD: Lookup the server by the UUID instead of its IP address.
- */
- code = SRXAFSCB_InitCallBackState(a_call);
-
- return code;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_ProbeUuid
- *
- * Description:
- * Routine called by the server-side callback RPC interface to
- * implement ``probing'' the Cache Manager, just making sure it's
- * still there is still the same client it used to be.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_uuid : Ptr to UUID that must match the client's UUID.
- *
- * Returns:
- * 0 if a_uuid matches the UUID for this client
- * Non-zero otherwize
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
-{
- int code = 0;
- XSTATS_DECLS;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_Probe);
-
- XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
- if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
- code = 1; /* failure */
- XSTATS_END_TIME;
-
- RX_AFS_GUNLOCK();
-
- return code;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetServerPrefs
- *
- * Description:
- * Routine to list server preferences used by this client.
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_index : Input server index
- * a_srvr_addr : Output server address in host byte order
- * (0xffffffff on last server)
- * a_srvr_rank : Output server rank
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
- afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
-{
- int i, j;
- struct srvAddr *sa;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_GetServerPrefs);
-
- ObtainReadLock(&afs_xserver);
-
- /* Search the hash table for the server with this index */
- *a_srvr_addr = 0xffffffff;
- *a_srvr_rank = 0xffffffff;
- for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
- for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
- if (i == a_index) {
- *a_srvr_addr = ntohl(sa->sa_ip);
- *a_srvr_rank = sa->sa_iprank;
- }
- }
- }
-
- ReleaseReadLock(&afs_xserver);
-
- RX_AFS_GUNLOCK();
-
- return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetCellServDB
- *
- * Description:
- * Routine to list cells configured for this client
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_index : Input cell index
- * a_name : Output cell name ("" on last cell)
- * a_hosts : Output cell database servers in host byte order.
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
- char **a_name, serverList * a_hosts)
-{
- afs_int32 i, j = 0;
- struct cell *tcell;
- char *t_name, *p_name = NULL;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_GetCellServDB);
-
- tcell = afs_GetCellByIndex(a_index, READ_LOCK);
-
- if (!tcell) {
- i = 0;
- a_hosts->serverList_val = 0;
- a_hosts->serverList_len = 0;
- } else {
- p_name = tcell->cellName;
- for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
- i = strlen(p_name);
- a_hosts->serverList_val =
- (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
- a_hosts->serverList_len = j;
- for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
- a_hosts->serverList_val[j] =
- ntohl(tcell->cellHosts[j]->addr->sa_ip);
- afs_PutCell(tcell, READ_LOCK);
- }
-
- t_name = (char *)afs_osi_Alloc(i + 1);
- if (t_name == NULL) {
- afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
- RX_AFS_GUNLOCK();
- return ENOMEM;
- }
-
- t_name[i] = '\0';
- if (p_name)
- memcpy(t_name, p_name, i);
-
- RX_AFS_GUNLOCK();
-
- *a_name = t_name;
- return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetLocalCell
- *
- * Description:
- * Routine to return name of client's local cell
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_name : Output cell name
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
-{
- int plen;
- struct cell *tcell;
- char *t_name, *p_name = NULL;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_GetLocalCell);
-
- /* Search the list for the primary cell. Cell number 1 is only
- * the primary cell is when no other cell is explicitly marked as
- * the primary cell. */
- tcell = afs_GetPrimaryCell(READ_LOCK);
- if (tcell)
- p_name = tcell->cellName;
- if (p_name)
- plen = strlen(p_name);
- else
- plen = 0;
- t_name = (char *)afs_osi_Alloc(plen + 1);
- if (t_name == NULL) {
- if (tcell)
- afs_PutCell(tcell, READ_LOCK);
- RX_AFS_GUNLOCK();
- return ENOMEM;
- }
-
- t_name[plen] = '\0';
- if (p_name)
- memcpy(t_name, p_name, plen);
-
- RX_AFS_GUNLOCK();
-
- *a_name = t_name;
- if (tcell)
- afs_PutCell(tcell, READ_LOCK);
- return 0;
-}
-
-
-/*
- * afs_MarshallCacheConfig - marshall client cache configuration
- *
- * PARAMETERS
- *
- * IN callerVersion - the rpc stat version of the caller.
- *
- * IN config - client cache configuration.
- *
- * OUT ptr - buffer where configuration is marshalled.
- *
- * RETURN CODES
- *
- * Returns void.
- */
-static void
-afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
- afs_uint32 * ptr)
-{
- AFS_STATCNT(afs_MarshallCacheConfig);
- /*
- * We currently only support version 1.
- */
- *(ptr++) = config->nChunkFiles;
- *(ptr++) = config->nStatCaches;
- *(ptr++) = config->nDataCaches;
- *(ptr++) = config->nVolumeCaches;
- *(ptr++) = config->firstChunkSize;
- *(ptr++) = config->otherChunkSize;
- *(ptr++) = config->cacheSize;
- *(ptr++) = config->setTime;
- *(ptr++) = config->memCache;
-}
-
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetCacheConfig
- *
- * Description:
- * Routine to return parameters used to initialize client cache.
- * Client may request any format version. Server may not return
- * format version greater than version requested by client.
- *
- * Arguments:
- * a_call: Ptr to Rx call on which this request came in.
- * callerVersion: Data format version desired by the client.
- * serverVersion: Data format version of output data.
- * configCount: Number bytes allocated for output data.
- * config: Client cache configuration.
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
- afs_uint32 * serverVersion, afs_uint32 * configCount,
- cacheConfig * config)
-{
- afs_uint32 *t_config;
- size_t allocsize;
- cm_initparams_v1 cm_config;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_GetCacheConfig);
-
- /*
- * Currently only support version 1
- */
- allocsize = sizeof(cm_initparams_v1);
- t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
- if (t_config == NULL) {
- RX_AFS_GUNLOCK();
- return ENOMEM;
- }
-
- cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
- cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
- cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
- cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
- cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
- cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
- cm_config.cacheSize = cm_initParams.cmi_cacheSize;
- cm_config.setTime = cm_initParams.cmi_setTime;
- cm_config.memCache = cm_initParams.cmi_memCache;
-
- afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
-
- *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
- *configCount = allocsize;
- config->cacheConfig_val = t_config;
- config->cacheConfig_len = allocsize / sizeof(afs_uint32);
-
- RX_AFS_GUNLOCK();
-
- return 0;
-}
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_FetchData
- *
- * Description:
- * Routine to do third party move from a remioserver to the original
- * issuer of an ArchiveData request. Presently supported only by the
- * "fs" command, not by the AFS client.
- *
- * Arguments:
- * rxcall: Ptr to Rx call on which this request came in.
- * Fid: pointer to AFSFid structure.
- * Fd: File descriptor inside fs command.
- * Position: Offset in the file.
- * Length: Data length to transfer.
- * TotalLength: Pointer to total file length field
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- *------------------------------------------------------------------------*/
-int
-SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
- afs_int64 Position, afs_int64 Length,
- afs_int64 * TotalLength)
-{
- return ENOSYS;
-}
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_StoreData
- *
- * Description:
- * Routine to do third party move from a remioserver to the original
- * issuer of a RetrieveData request. Presently supported only by the
- * "fs" command, not by the AFS client.
- *
- * Arguments:
- * rxcall: Ptr to Rx call on which this request came in.
- * Fid: pointer to AFSFid structure.
- * Fd: File descriptor inside fs command.
- * Position: Offset in the file.
- * Length: Data length to transfer.
- * TotalLength: Pointer to total file length field
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-int
-SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
- afs_int64 Position, afs_int64 Length,
- afs_int64 * TotalLength)
-{
- return ENOSYS;
-}
-
-/*------------------------------------------------------------------------
- * EXPORTED SRXAFSCB_GetCellByNum
- *
- * Description:
- * Routine to get information about a cell specified by its
- * cell number (returned by GetCE/GetCE64).
- *
- * Arguments:
- * a_call : Ptr to Rx call on which this request came in.
- * a_cellnum : Input cell number
- * a_name : Output cell name (one zero byte when no such cell).
- * a_hosts : Output cell database servers in host byte order.
- *
- * Returns:
- * 0 on success
- *
- * Environment:
- * Nothing interesting.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-int
-SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
- char **a_name, serverList * a_hosts)
-{
- afs_int32 i, sn;
- struct cell *tcell;
-
- RX_AFS_GLOCK();
- AFS_STATCNT(SRXAFSCB_GetCellByNum);
-
- a_hosts->serverList_val = 0;
- a_hosts->serverList_len = 0;
-
- tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
- if (!tcell) {
- *a_name = afs_strdup("");
- RX_AFS_GUNLOCK();
- return 0;
- }
-
- ObtainReadLock(&tcell->lock);
- *a_name = afs_strdup(tcell->cellName);
-
- for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
- a_hosts->serverList_len = sn;
- a_hosts->serverList_val =
- (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
-
- for (i = 0; i < sn; i++)
- a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
- ReleaseReadLock(&tcell->lock);
- afs_PutCell(tcell, READ_LOCK);
-
- RX_AFS_GUNLOCK();
- return 0;
-}
-
-int
-SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
- struct interfaceAddr *addr,
- Capabilities * capabilities)
-{
- int i;
- int code = 0;
- afs_int32 *dataBuffP;
- afs_int32 dataBytes;
-
- RX_AFS_GLOCK();
-
- AFS_STATCNT(SRXAFSCB_WhoAreYou);
-
- ObtainReadLock(&afs_xinterface);
-
- /* return all network interface addresses */
- addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
- addr->uuid = afs_cb_interface.uuid;
- for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
- addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
- addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
- addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
- }
-
- ReleaseReadLock(&afs_xinterface);
-
- RX_AFS_GUNLOCK();
-
- dataBytes = 1 * sizeof(afs_int32);
- dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
- dataBuffP[0] = CAPABILITY_ERRORTRANS;
- capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
- capabilities->Capabilities_val = dataBuffP;
-
- return code;
-}
+++ /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
- */
-
-/*
- * This package is used to actively manage the expiration of callbacks,
- * so that the rest of the cache manager doesn't need to compute
- * whether a callback has expired or not, but can tell with one simple
- * check, that is, whether the CStatd bit is on or off.
- *
- * The base of the hash table moves periodically (every 128 seconds)
- * QueueCallback rarely touches the first 3 slots in the hash table
- * (only when called from CheckCallbacks) since MinTimeOut in
- * viced/callback.c is currently 7 minutes.
- * Therefore, CheckCallbacks should be able to run concurrently with
- * QueueCallback, given the proper locking, of course.
- *
- * Note:
- * 1. CheckCallbacks and BumpBase never run simultaneously. This is because
- * they are only called from afs_Daemon. Therefore, base and basetime will
- * always be consistent during CheckCallbacks.
- * 2. cbHashT [base] rarely (if ever) gets stuff queued in it. The only way
- * that could happen is CheckCallbacks might fencepost and move something in
- * place, or BumpBase might push some stuff up.
- * 3. Hash chains aren't particularly sorted.
- * 4. The file server keeps its callback state around for 3 minutes
- * longer than it promises the cache manager in order to account for
- * clock skew, network delay, and other bogeymen.
- *
- * For now I just use one large lock, which is fine on a uniprocessor,
- * since it's not held during any RPCs or low-priority I/O operations.
- * To make this code MP-fast, you need no more locks than processors,
- * but probably more than one. In measurements on MP-safe implementations,
- * I have never seen any contention over the xcbhash lock.
- *
- * Incompatible operations:
- * Enqueue and "dequeue of first vcache" in same slot
- * dequeue and "dequeue of preceding vcache" in same slot
- * dequeue and "dequeue of successive vcache" in same slot
- * BumpBase pushing a list and enqueue in the new base slot
- * Two enqueues in same slot
- * more...
- *
- * Certain invariants exist:
- * 1 Callback expiration times granted by a file server will never
- * decrease for a particular vnode UNLESS a CallBack RPC is invoked
- * by the server in the interim.
- * 2 A vcache will always expire no sooner than the slot in which it is
- * currently enqueued. Callback times granted by the server may
- * increase, in which case the vcache will be updated in-place. As a
- * result, it may expire later than the slot in which it is enqueued.
- * Not to worry, the CheckCallbacks code will move it if neccessary.
- * This approach means that busy vnodes won't be continually moved
- * around within the expiry queue: they are only moved when they
- * finally advance to the lead bucket.
- * 3 Anything which has a callback on it must be in the expiry
- * queue. In AFS 3.3, that means everything but symlinks (which
- * are immutable), including contents of Read-Only volumes
- * (which have callbacks by virtue of the whole-volume callback)
- *
- * QueueCallback only checks that its vcache is in the list
- * somewhere, counting on invariant #1 to guarantee that the vcache
- * won't be in a slot later than QueueCallback would otherwise place
- * it. Therefore, whenever we turn off the CStatd bit on the vcache, we
- * *must* remove the vcache from the expiry queue. Otherwise, we
- * might have missed a CallBack RPC, and a subsequent callback might be
- * granted with a shorter expiration time.
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_cbqueue.c,v 1.9 2003/07/15 23:14:11 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_cbqueue.h"
-#include "afs/afs.h"
-#include "afs/lock.h"
-#include "afs/afs_stats.h"
-
-static unsigned int base = 0;
-static unsigned int basetime = 0;
-static struct vcache *debugvc; /* used only for post-mortem debugging */
-struct bucket {
- struct afs_q head;
- /* struct afs_lock lock; only if you want lots of locks... */
-};
-static struct bucket cbHashT[CBHTSIZE];
-struct afs_lock afs_xcbhash;
-
-/* afs_QueueCallback
- * Takes a write-locked vcache pointer and a callback expiration time
- * as returned by the file server (ie, in units of 128 seconds from "now").
- *
- * Uses the time as an index into a hash table, and inserts the vcache
- * structure into the overflow chain.
- *
- * If the vcache is already on some hash chain, leave it there.
- * CheckCallbacks will get to it eventually. In the meantime, it
- * might get flushed, or it might already be on the right hash chain,
- * so why bother messing with it now?
- *
- * NOTE: The caller must hold a write lock on afs_xcbhash
- */
-
-void
-afs_QueueCallback(struct vcache *avc, unsigned int atime, struct volume *avp)
-{
- if (avp && (avp->expireTime < avc->cbExpires))
- avp->expireTime = avc->cbExpires;
- if (!(avc->callsort.next)) {
- atime = (atime + base) % CBHTSIZE;
- QAdd(&(cbHashT[atime].head), &(avc->callsort));
- }
-
- return;
-} /* afs_QueueCallback */
-
-/* afs_DequeueCallback
- * Takes a write-locked vcache pointer and removes it from the callback
- * hash table, without knowing beforehand which slot it was in.
- *
- * for now, just get a lock on everything when doing the dequeue, don't
- * worry about getting a lock on the individual slot.
- *
- * the only other places that do anything like dequeues are CheckCallbacks
- * and BumpBase.
- *
- * NOTE: The caller must hold a write lock on afs_xcbhash
- */
-void
-afs_DequeueCallback(struct vcache *avc)
-{
-
- debugvc = avc;
- if (avc->callsort.prev) {
- QRemove(&(avc->callsort));
- avc->callsort.prev = avc->callsort.next = NULL;
- } else; /* must have got dequeued in a race */
- afs_symhint_inval(avc);
-
- return;
-} /* afs_DequeueCallback */
-
-/* afs_CheckCallbacks
- * called periodically to determine which callbacks are likely to
- * expire in the next n second interval. Preemptively marks them as
- * expired. Rehashes items which are now in the wrong hash bucket.
- * Preemptively renew recently-accessed items. Only removes things
- * from the first and second bucket (as long as secs < 128), and
- * inserts things into other, later buckets. either need to advance
- * to the second bucket if secs spans two intervals, or else be
- * certain to call afs_CheckCallbacks immediately after calling
- * BumpBase (allows a little more slop but it's ok because file server
- * keeps 3 minutes of slop time)
- *
- * There is a little race between CheckCallbacks and any code which
- * updates cbExpires, always just prior to calling QueueCallback. We
- * don't lock the vcache struct here (can't, or we'd risk deadlock),
- * so GetVCache (for example) may update cbExpires before or after #1
- * below. If before, CheckCallbacks moves this entry to its proper
- * slot. If after, GetVCache blocks in the call to QueueCallbacks,
- * this code dequeues the vcache, and then QueueCallbacks re-enqueues it.
- *
- * XXX to avoid the race, make QueueCallback take the "real" time
- * and update cbExpires under the xcbhash lock.
- *
- * NB #1: There's a little optimization here: if I go to invalidate a
- * RO vcache or volume, first check to see if the server is down. If
- * it _is_, don't invalidate it, cuz we might just as well keep using
- * it. Possibly, we could do the same thing for items in RW volumes,
- * but that bears some drinking about.
- *
- * Don't really need to invalidate the hints, we could just wait to see if
- * the dv has changed after a subsequent FetchStatus, but this is safer.
- */
-
-/* Sanity check on the callback queue. Allow for slop in the computation. */
-#ifdef AFS_OSF_ENV
-#define CBQ_LIMIT (afs_maxvcount + 10)
-#else
-#define CBQ_LIMIT (afs_cacheStats + afs_stats_cmperf.vcacheXAllocs + 10)
-#endif
-
-void
-afs_CheckCallbacks(unsigned int secs)
-{
- struct vcache *tvc;
- register struct afs_q *tq;
- struct afs_q *uq;
- afs_uint32 now;
- struct volume *tvp;
- register int safety;
-
- ObtainWriteLock(&afs_xcbhash, 85); /* pretty likely I'm going to remove something */
- now = osi_Time();
- for (safety = 0, tq = cbHashT[base].head.prev;
- (safety <= CBQ_LIMIT) && (tq != &(cbHashT[base].head));
- tq = uq, safety++) {
-
- uq = QPrev(tq);
- tvc = CBQTOV(tq);
- if (tvc->cbExpires < now + secs) { /* race #1 here */
- /* Get the volume, and if its callback expiration time is more than secs
- * seconds into the future, update this vcache entry and requeue it below
- */
- if ((tvc->states & CRO)
- && (tvp = afs_FindVolume(&(tvc->fid), READ_LOCK))) {
- if (tvp->expireTime > now + secs) {
- tvc->cbExpires = tvp->expireTime; /* XXX race here */
- } else {
- int i;
- for (i = 0; i < MAXHOSTS && tvp->serverHost[i]; i++) {
- if (!(tvp->serverHost[i]->flags & SRVR_ISDOWN)) {
- /* What about locking xvcache or vrefcount++ or
- * write locking tvc? */
- QRemove(tq);
- tq->prev = tq->next = NULL;
- tvc->states &= ~(CStatd | CMValid | CUnique);
- if ((tvc->fid.Fid.Vnode & 1)
- || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- tvc->quick.stamp = 0;
- tvc->h1.dchint = NULL; /*invalidate em */
- afs_ResetVolumeInfo(tvp);
- break;
- }
- }
- }
- afs_PutVolume(tvp, READ_LOCK);
- } else {
- /* Do I need to worry about things like execsorwriters?
- * What about locking xvcache or vrefcount++ or write locking tvc?
- */
- QRemove(tq);
- tq->prev = tq->next = NULL;
- tvc->states &= ~(CStatd | CMValid | CUnique);
- if ((tvc->fid.Fid.Vnode & 1) || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- }
- }
-
- if ((tvc->cbExpires > basetime) && CBHash(tvc->cbExpires - basetime)) {
- /* it's been renewed on us. Have to be careful not to put it back
- * into this slot, or we may never get out of here.
- */
- int slot;
- slot = (CBHash(tvc->cbExpires - basetime) + base) % CBHTSIZE;
- if (slot != base) {
- if (QPrev(tq))
- QRemove(&(tvc->callsort));
- QAdd(&(cbHashT[slot].head), &(tvc->callsort));
- /* XXX remember to update volume expiration time */
- /* -- not needed for correctness, though */
- }
- }
- }
-
- if (safety > CBQ_LIMIT) {
- afs_stats_cmperf.cbloops++;
- if (afs_paniconwarn)
- osi_Panic("CheckCallbacks");
-
- afs_warn
- ("AFS Internal Error (minor): please contact AFS Product Support.\n");
- ReleaseWriteLock(&afs_xcbhash);
- afs_FlushCBs();
- return;
- } else
- ReleaseWriteLock(&afs_xcbhash);
-
-
-/* XXX future optimization:
- if this item has been recently accessed, queue up a stat for it.
- {
- struct dcache * adc;
-
- ObtainReadLock(&afs_xdcache);
- if ((adc = tvc->quick.dc) && (adc->stamp == tvc->quick.stamp)
- && (afs_indexTimes[adc->index] > afs_indexCounter - 20)) {
- queue up the stat request
- }
- ReleaseReadLock(&afs_xdcache);
- }
- */
-
- return;
-} /* afs_CheckCallback */
-
-/* afs_FlushCBs
- * to be used only in dire circumstances, this drops all callbacks on
- * the floor, without giving them back to the server. It's ok, the server can
- * deal with it, but it is a little bit rude.
- */
-void
-afs_FlushCBs(void)
-{
- register int i;
- register struct vcache *tvc;
-
- ObtainWriteLock(&afs_xcbhash, 86); /* pretty likely I'm going to remove something */
-
- for (i = 0; i < VCSIZE; i++) /* reset all the vnodes */
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- tvc->callback = 0;
- tvc->quick.stamp = 0;
- tvc->h1.dchint = NULL; /* invalidate hints */
- tvc->states &= ~(CStatd);
- if ((tvc->fid.Fid.Vnode & 1) || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- tvc->callsort.prev = tvc->callsort.next = NULL;
- }
-
- afs_InitCBQueue(0);
-
- ReleaseWriteLock(&afs_xcbhash);
-}
-
-/* afs_FlushServerCBs
- * to be used only in dire circumstances, this drops all callbacks on
- * the floor for a specific server, without giving them back to the server.
- * It's ok, the server can deal with it, but it is a little bit rude.
- */
-void
-afs_FlushServerCBs(struct server *srvp)
-{
- register int i;
- register struct vcache *tvc;
-
- ObtainWriteLock(&afs_xcbhash, 86); /* pretty likely I'm going to remove something */
-
- for (i = 0; i < VCSIZE; i++) { /* reset all the vnodes */
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->callback == srvp) {
- tvc->callback = 0;
- tvc->quick.stamp = 0;
- tvc->h1.dchint = NULL; /* invalidate hints */
- tvc->states &= ~(CStatd);
- if ((tvc->fid.Fid.Vnode & 1) || (vType(tvc) == VDIR)) {
- osi_dnlc_purgedp(tvc);
- }
- afs_DequeueCallback(tvc);
- }
- }
- }
-
- ReleaseWriteLock(&afs_xcbhash);
-}
-
-/* afs_InitCBQueue
- * called to initialize static and global variables associated with
- * the Callback expiration management mechanism.
- */
-void
-afs_InitCBQueue(int doLockInit)
-{
- register int i;
-
- memset((char *)cbHashT, 0, CBHTSIZE * sizeof(struct bucket));
- for (i = 0; i < CBHTSIZE; i++) {
- QInit(&(cbHashT[i].head));
- /* Lock_Init(&(cbHashT[i].lock)); only if you want lots of locks, which
- * don't seem too useful at present. */
- }
- base = 0;
- basetime = osi_Time();
- if (doLockInit)
- Lock_Init(&afs_xcbhash);
-}
-
-/* Because there are no real-time guarantees, and especially because a
- * thread may wait on a lock indefinitely, this routine has to be
- * careful that it doesn't get permanently out-of-date. Important
- * assumption: this routine is only called from afs_Daemon, so there
- * can't be more than one instance of this running at any one time.
- * Presumes that basetime is never 0, and is always sane.
- *
- * Before calling this routine, be sure that the first slot is pretty
- * empty. This -20 is because the granularity of the checks in
- * afs_Daemon is pretty large, so I'd rather err on the side of safety
- * sometimes. The fact that I only bump basetime by CBHTSLOTLEN-1
- * instead of the whole CBHTSLOTLEN is also for "safety".
- * Conceptually, it makes this clock run just a little faster than the
- * clock governing which slot a callback gets hashed into. Both of these
- * things make CheckCallbacks work a little harder than it would have to
- * if I wanted to cut things finer.
- * Everything from the old first slot is carried over into the new first
- * slot. Thus, if there were some things that ought to have been invalidated,
- * but weren't (say, if the server was down), they will be examined at every
- * opportunity thereafter.
- */
-int
-afs_BumpBase(void)
-{
- afs_uint32 now;
- int didbump;
- u_int oldbase;
-
- ObtainWriteLock(&afs_xcbhash, 87);
- didbump = 0;
- now = osi_Time();
- while (basetime + (CBHTSLOTLEN - 20) <= now) {
- oldbase = base;
- basetime += CBHTSLOTLEN - 1;
- base = (base + 1) % CBHTSIZE;
- didbump++;
- if (!QEmpty(&(cbHashT[oldbase].head))) {
- QCat(&(cbHashT[oldbase].head), &(cbHashT[base].head));
- }
- }
- ReleaseWriteLock(&afs_xcbhash);
-
- return didbump;
-}
+++ /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
- */
-
-/*
- * This package is used to actively manage the expiration of callbacks,
- * so that the rest of the cache manager doesn't need to compute
- * whether a callback has expired or not, but can tell with one simple
- * check, that is, whether the CStatd bit is on or off.
- */
-
-/* how many seconds in a slot */
-#define CBHTSLOTLEN 128
-/* how many slots in the table */
-#define CBHTSIZE 128
-/* 7 is LOG2(slotlen) */
-#define CBHash(t) ((t)>>7)
-
-#define CBQTOV(e) ((struct vcache *)(((char *) (e)) - (((char *)(&(((struct vcache *)(e))->callsort))) - ((char *)(e)))))
+++ /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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_cell.c,v 1.30 2004/05/08 04:22:19 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/afs_osi.h"
-
-/* Local variables. */
-afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
-
-/*
- * AFSDB implementation:
- *
- * afs_StopAFSDB: terminate the AFSDB handler, used on shutdown
- * afs_AFSDBHandler: entry point for user-space AFSDB request handler
- * afs_GetCellHostsAFSDB: query the AFSDB handler and wait for response
- * afs_LookupAFSDB: look up AFSDB for given cell name and create locally
- */
-
-#ifdef AFS_AFSDB_ENV
-static afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
-static char afsdb_handler_running; /* Protected by GLOCK */
-static char afsdb_handler_shutdown; /* Protected by GLOCK */
-
-static struct {
- afs_rwlock_t lock;
- char pending;
- char complete;
- char *cellname;
- afs_int32 *cellhosts;
- int *timeout;
- char **realname;
-} afsdb_req;
-
-void
-afs_StopAFSDB()
-{
- if (afsdb_handler_running) {
- afs_osi_Wakeup(&afsdb_req);
- } else {
- afsdb_handler_shutdown = 1;
- afs_termState = AFSOP_STOP_RXEVENT;
- }
-}
-
-int
-afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
-{
- if (afsdb_handler_shutdown)
- return -2;
- afsdb_handler_running = 1;
-
- ObtainSharedLock(&afsdb_req.lock, 683);
- if (afsdb_req.pending) {
- int i, hostCount;
-
- UpgradeSToWLock(&afsdb_req.lock, 684);
- hostCount = kernelMsg[0];
- *afsdb_req.timeout = kernelMsg[1];
- if (*afsdb_req.timeout)
- *afsdb_req.timeout += osi_Time();
- *afsdb_req.realname = afs_strdup(acellName);
-
- for (i = 0; i < MAXCELLHOSTS; i++) {
- if (i >= hostCount)
- afsdb_req.cellhosts[i] = 0;
- else
- afsdb_req.cellhosts[i] = kernelMsg[2 + i];
- }
-
- /* Request completed, wake up the relevant thread */
- afsdb_req.pending = 0;
- afsdb_req.complete = 1;
- afs_osi_Wakeup(&afsdb_req);
- ConvertWToSLock(&afsdb_req.lock);
- }
- ConvertSToRLock(&afsdb_req.lock);
-
- /* Wait for a request */
- while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
- ReleaseReadLock(&afsdb_req.lock);
- afs_osi_Sleep(&afsdb_req);
- ObtainReadLock(&afsdb_req.lock);
- }
-
- /* Check if we're shutting down */
- if (afs_termState == AFSOP_STOP_AFSDB) {
- ReleaseReadLock(&afsdb_req.lock);
-
- /* Inform anyone waiting for us that we're going away */
- afsdb_handler_shutdown = 1;
- afsdb_handler_running = 0;
- afs_osi_Wakeup(&afsdb_req);
-
- afs_termState = AFSOP_STOP_RXEVENT;
- afs_osi_Wakeup(&afs_termState);
- return -2;
- }
-
- /* Return the lookup request to userspace */
- strncpy(acellName, afsdb_req.cellname, acellNameLen);
- ReleaseReadLock(&afsdb_req.lock);
- return 0;
-}
-
-static int
-afs_GetCellHostsAFSDB(char *acellName, afs_int32 * acellHosts, int *timeout,
- char **realName)
-{
- AFS_ASSERT_GLOCK();
- if (!afsdb_handler_running)
- return ENOENT;
-
- ObtainWriteLock(&afsdb_client_lock, 685);
- ObtainWriteLock(&afsdb_req.lock, 686);
-
- *acellHosts = 0;
- afsdb_req.cellname = acellName;
- afsdb_req.cellhosts = acellHosts;
- afsdb_req.timeout = timeout;
- afsdb_req.realname = realName;
-
- afsdb_req.complete = 0;
- afsdb_req.pending = 1;
- afs_osi_Wakeup(&afsdb_req);
- ConvertWToRLock(&afsdb_req.lock);
-
- while (afsdb_handler_running && !afsdb_req.complete) {
- ReleaseReadLock(&afsdb_req.lock);
- afs_osi_Sleep(&afsdb_req);
- ObtainReadLock(&afsdb_req.lock);
- };
- ReleaseReadLock(&afsdb_req.lock);
- ReleaseWriteLock(&afsdb_client_lock);
-
- if (*acellHosts)
- return 0;
- else
- return ENOENT;
-}
-#endif
-
-void
-afs_LookupAFSDB(char *acellName)
-{
-#ifdef AFS_AFSDB_ENV
- afs_int32 cellHosts[MAXCELLHOSTS];
- char *realName = NULL;
- int code, timeout;
-
- code = afs_GetCellHostsAFSDB(acellName, cellHosts, &timeout, &realName);
- if (code)
- goto done;
- code = afs_NewCell(realName, cellHosts, CNoSUID, NULL, 0, 0, timeout);
- if (code && code != EEXIST)
- goto done;
-
- /* If we found an alias, create it */
- if (afs_strcasecmp(acellName, realName))
- afs_NewCellAlias(acellName, realName);
-
- done:
- if (realName)
- afs_osi_FreeStr(realName);
-#endif
-}
-
-/*
- * Cell name-to-ID mapping
- *
- * afs_cellname_new: create a new cell name, optional cell number
- * afs_cellname_lookup_id: look up a cell name
- * afs_cellname_lookup_name: look up a cell number
- * afs_cellname_ref: note that this cell name was referenced somewhere
- * afs_cellname_init: load the list of cells from given inode
- * afs_cellname_write: write in-kernel list of cells to disk
- */
-
-struct cell_name *afs_cellname_head; /* Export for kdump */
-static ino_t afs_cellname_inode;
-static int afs_cellname_inode_set;
-static int afs_cellname_dirty;
-static afs_int32 afs_cellnum_next;
-
-static struct cell_name *
-afs_cellname_new(char *name, afs_int32 cellnum)
-{
- struct cell_name *cn;
-
- if (cellnum == 0)
- cellnum = afs_cellnum_next;
-
- cn = (struct cell_name *)afs_osi_Alloc(sizeof(*cn));
- cn->next = afs_cellname_head;
- cn->cellnum = cellnum;
- cn->cellname = afs_strdup(name);
- cn->used = 0;
- afs_cellname_head = cn;
-
- if (cellnum >= afs_cellnum_next)
- afs_cellnum_next = cellnum + 1;
-
- return cn;
-}
-
-static struct cell_name *
-afs_cellname_lookup_id(afs_int32 cellnum)
-{
- struct cell_name *cn;
-
- for (cn = afs_cellname_head; cn; cn = cn->next)
- if (cn->cellnum == cellnum)
- return cn;
-
- return NULL;
-}
-
-static struct cell_name *
-afs_cellname_lookup_name(char *name)
-{
- struct cell_name *cn;
-
- for (cn = afs_cellname_head; cn; cn = cn->next)
- if (strcmp(cn->cellname, name) == 0)
- return cn;
-
- return NULL;
-}
-
-static void
-afs_cellname_ref(struct cell_name *cn)
-{
- if (!cn->used) {
- cn->used = 1;
- afs_cellname_dirty = 1;
- }
-}
-
-int
-afs_cellname_init(ino_t inode, int lookupcode)
-{
- struct osi_file *tfile;
- int cc, off = 0;
-
- ObtainWriteLock(&afs_xcell, 692);
-
- afs_cellnum_next = 1;
- afs_cellname_dirty = 0;
-
- if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
- ReleaseWriteLock(&afs_xcell);
- return 0;
- }
- if (lookupcode) {
- ReleaseWriteLock(&afs_xcell);
- return lookupcode;
- }
-
- tfile = osi_UFSOpen(inode);
- if (!tfile) {
- ReleaseWriteLock(&afs_xcell);
- return EIO;
- }
-
- afs_cellname_inode = inode;
- afs_cellname_inode_set = 1;
-
- while (1) {
- afs_int32 cellnum, clen, magic;
- struct cell_name *cn;
- char *cellname;
-
- cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
- if (cc != sizeof(magic))
- break;
- if (magic != AFS_CELLINFO_MAGIC)
- break;
- off += cc;
-
- cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
- if (cc != sizeof(cellnum))
- break;
- off += cc;
-
- cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
- if (cc != sizeof(clen))
- break;
- off += cc;
-
- cellname = afs_osi_Alloc(clen + 1);
- if (!cellname)
- break;
-
- cc = afs_osi_Read(tfile, off, cellname, clen);
- if (cc != clen) {
- afs_osi_Free(cellname, clen + 1);
- break;
- }
- off += cc;
- cellname[clen] = '\0';
-
- if (afs_cellname_lookup_name(cellname)
- || afs_cellname_lookup_id(cellnum)) {
- afs_osi_Free(cellname, clen + 1);
- break;
- }
-
- cn = afs_cellname_new(cellname, cellnum);
- afs_osi_Free(cellname, clen + 1);
- }
-
- osi_UFSClose(tfile);
- ReleaseWriteLock(&afs_xcell);
- return 0;
-}
-
-int
-afs_cellname_write(void)
-{
- struct osi_file *tfile;
- struct cell_name *cn;
- int off;
-
- if (!afs_cellname_dirty || !afs_cellname_inode_set)
- return 0;
- if (afs_initState != 300)
- return 0;
-
- ObtainWriteLock(&afs_xcell, 693);
- afs_cellname_dirty = 0;
- off = 0;
- tfile = osi_UFSOpen(afs_cellname_inode);
- if (!tfile) {
- ReleaseWriteLock(&afs_xcell);
- return EIO;
- }
-
- for (cn = afs_cellname_head; cn; cn = cn->next) {
- afs_int32 magic, cellnum, clen;
- int cc;
-
- if (!cn->used)
- continue;
-
- magic = AFS_CELLINFO_MAGIC;
- cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
- if (cc != sizeof(magic))
- break;
- off += cc;
-
- cellnum = cn->cellnum;
- cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
- if (cc != sizeof(cellnum))
- break;
- off += cc;
-
- clen = strlen(cn->cellname);
- cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
- if (cc != sizeof(clen))
- break;
- off += cc;
-
- cc = afs_osi_Write(tfile, off, cn->cellname, clen);
- if (cc != clen)
- break;
- off += clen;
- }
-
- osi_UFSClose(tfile);
- ReleaseWriteLock(&afs_xcell);
- return 0;
-}
-
-/*
- * Cell alias implementation
- *
- * afs_FindCellAlias: look up cell alias by alias name
- * afs_GetCellAlias: get cell alias by index (starting at 0)
- * afs_PutCellAlias: put back a cell alias returned by Find or Get
- * afs_NewCellAlias: create new cell alias entry
- */
-
-struct cell_alias *afs_cellalias_head; /* Export for kdump */
-static afs_int32 afs_cellalias_index;
-static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
-
-static struct cell_alias *
-afs_FindCellAlias(char *alias)
-{
- struct cell_alias *tc;
-
- for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
- if (!strcmp(alias, tc->alias))
- break;
- return tc;
-}
-
-struct cell_alias *
-afs_GetCellAlias(int index)
-{
- struct cell_alias *tc;
-
- ObtainReadLock(&afs_xcell);
- for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
- if (tc->index == index)
- break;
- ReleaseReadLock(&afs_xcell);
-
- return tc;
-}
-
-void
-afs_PutCellAlias(struct cell_alias *a)
-{
- return;
-}
-
-afs_int32
-afs_NewCellAlias(char *alias, char *cell)
-{
- struct cell_alias *tc;
-
- ObtainSharedLock(&afs_xcell, 681);
- if (afs_CellOrAliasExists_nl(alias)) {
- ReleaseSharedLock(&afs_xcell);
- return EEXIST;
- }
-
- UpgradeSToWLock(&afs_xcell, 682);
- tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias));
- tc->alias = afs_strdup(alias);
- tc->cell = afs_strdup(cell);
- tc->next = afs_cellalias_head;
- tc->index = afs_cellalias_index++;
- afs_cellalias_head = tc;
- ReleaseWriteLock(&afs_xcell);
-
- afs_DynrootInvalidate();
- return 0;
-}
-
-/*
- * Actual cell list implementation
- *
- * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
- * afs_RefreshCell: look up cell information in AFSDB if timeout expired
- *
- * afs_TraverseCells: execute a callback for each existing cell
- * afs_TraverseCells_nl: same as above except without locking afs_xcell
- * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
- *
- * afs_FindCellByName: return a cell with a given name, if it exists
- * afs_FindCellByName_nl: same as above, without locking afs_xcell
- * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
- * afs_GetCell: return a cell with a given cell number
- * afs_GetCellStale: same as GetCell, but does not try to refresh the data
- * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
- *
- * afs_GetPrimaryCell: return the primary cell, if any
- * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
- * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
- * afs_SetPrimaryCell: set the primary cell name to the given cell name
- *
- * afs_NewCell: create or update a cell entry
- */
-
-struct afs_q CellLRU; /* Export for kdump */
-static char *afs_thiscell;
-afs_int32 afs_cellindex; /* Export for kdump */
-
-static void
-afs_UpdateCellLRU(struct cell *c)
-{
- ObtainWriteLock(&afs_xcell, 100);
- QRemove(&c->lruq);
- QAdd(&CellLRU, &c->lruq);
- ReleaseWriteLock(&afs_xcell);
-}
-
-static void
-afs_RefreshCell(struct cell *ac)
-{
- if (ac->states & CNoAFSDB)
- return;
- if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
- afs_LookupAFSDB(ac->cellName);
-}
-
-static void *
-afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
-{
- struct afs_q *cq, *tq;
- struct cell *tc;
- void *ret = NULL;
-
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq);
-
- /* This is assuming that a NULL return is acceptable. */
- if (cq) {
- tq = QNext(cq);
- } else {
- return NULL;
- }
-
- ret = cb(tc, arg);
- if (ret)
- break;
- }
-
- return ret;
-}
-
-void *
-afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
-{
- void *ret;
-
- ObtainReadLock(&afs_xcell);
- ret = afs_TraverseCells_nl(cb, arg);
- ReleaseReadLock(&afs_xcell);
-
- return ret;
-}
-
-static void *
-afs_choose_cell_by_name(struct cell *cell, void *arg)
-{
- if (!arg) {
- /* Safety net */
- return cell;
- } else {
- return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
- }
-}
-
-static void *
-afs_choose_cell_by_num(struct cell *cell, void *arg)
-{
- return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
-}
-
-static void *
-afs_choose_cell_by_index(struct cell *cell, void *arg)
-{
- return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
-}
-
-static struct cell *
-afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
-{
- return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
-}
-
-static struct cell *
-afs_FindCellByName(char *acellName, afs_int32 locktype)
-{
- return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
-}
-
-struct cell *
-afs_GetCellByName(char *acellName, afs_int32 locktype)
-{
- struct cell *tc;
-
- tc = afs_FindCellByName(acellName, locktype);
- if (!tc) {
- afs_LookupAFSDB(acellName);
- tc = afs_FindCellByName(acellName, locktype);
- }
- if (tc) {
- afs_cellname_ref(tc->cnamep);
- afs_UpdateCellLRU(tc);
- afs_RefreshCell(tc);
- }
-
- return tc;
-}
-
-struct cell *
-afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
-{
- struct cell *tc;
- struct cell_name *cn;
-
- tc = afs_GetCellStale(cellnum, locktype);
- if (tc) {
- afs_RefreshCell(tc);
- } else {
- ObtainReadLock(&afs_xcell);
- cn = afs_cellname_lookup_id(cellnum);
- ReleaseReadLock(&afs_xcell);
- if (cn)
- tc = afs_GetCellByName(cn->cellname, locktype);
- }
- return tc;
-}
-
-struct cell *
-afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
-{
- struct cell *tc;
-
- tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
- if (tc) {
- afs_cellname_ref(tc->cnamep);
- afs_UpdateCellLRU(tc);
- }
- return tc;
-}
-
-struct cell *
-afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
-{
- struct cell *tc;
-
- tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
- if (tc)
- afs_UpdateCellLRU(tc);
- return tc;
-}
-
-struct cell *
-afs_GetPrimaryCell(afs_int32 locktype)
-{
- return afs_GetCellByName(afs_thiscell, locktype);
-}
-
-int
-afs_IsPrimaryCell(struct cell *cell)
-{
- /* Simple safe checking */
- if (!cell) {
- return 0;
- } else if (!afs_thiscell) {
- /* This is simply a safety net to avoid seg faults especially when
- * using a user-space library. afs_SetPrimaryCell() should be set
- * prior to this call. */
- afs_SetPrimaryCell(cell->cellName);
- return 1;
- } else {
- return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
- }
-}
-
-int
-afs_IsPrimaryCellNum(afs_int32 cellnum)
-{
- struct cell *tc;
- int primary = 0;
-
- tc = afs_GetCellStale(cellnum, READ_LOCK);
- if (tc) {
- primary = afs_IsPrimaryCell(tc);
- afs_PutCell(tc, READ_LOCK);
- }
-
- return primary;
-}
-
-afs_int32
-afs_SetPrimaryCell(char *acellName)
-{
- ObtainWriteLock(&afs_xcell, 691);
- if (afs_thiscell)
- afs_osi_FreeStr(afs_thiscell);
- afs_thiscell = afs_strdup(acellName);
- ReleaseWriteLock(&afs_xcell);
- return 0;
-}
-
-afs_int32
-afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
- char *linkedcname, u_short fsport, u_short vlport, int timeout)
-{
- struct cell *tc, *tcl = 0;
- afs_int32 i, newc = 0, code = 0;
-
- AFS_STATCNT(afs_NewCell);
-
- ObtainWriteLock(&afs_xcell, 103);
-
- tc = afs_FindCellByName_nl(acellName, READ_LOCK);
- if (tc) {
- aflags &= ~CNoSUID;
- } else {
- tc = (struct cell *)afs_osi_Alloc(sizeof(struct cell));
- memset((char *)tc, 0, sizeof(*tc));
- tc->cellName = afs_strdup(acellName);
- tc->fsport = AFS_FSPORT;
- tc->vlport = AFS_VLPORT;
- RWLOCK_INIT(&tc->lock, "cell lock");
- newc = 1;
- if (afs_thiscell && !strcmp(acellName, afs_thiscell))
- aflags &= ~CNoSUID;
- }
- ObtainWriteLock(&tc->lock, 688);
-
- /* If the cell we've found has the correct name but no timeout,
- * and we're called with a non-zero timeout, bail out: never
- * override static configuration entries with AFSDB ones.
- * One exception: if the original cell entry had no servers,
- * it must get servers from AFSDB.
- */
- if (timeout && !tc->timeout && tc->cellHosts[0]) {
- code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
- goto bad;
- }
-
- /* we don't want to keep pinging old vlservers which were down,
- * since they don't matter any more. It's easier to do this than
- * to remove the server from its various hash tables. */
- for (i = 0; i < MAXCELLHOSTS; i++) {
- if (!tc->cellHosts[i])
- break;
- tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
- tc->cellHosts[i]->flags |= SRVR_ISGONE;
- }
-
- if (fsport)
- tc->fsport = fsport;
- if (vlport)
- tc->vlport = vlport;
-
- if (aflags & CLinkedCell) {
- if (!linkedcname) {
- code = EINVAL;
- goto bad;
- }
- tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
- if (!tcl) {
- code = ENOENT;
- goto bad;
- }
- if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
- tcl->lcellp->lcellp = (struct cell *)0;
- tcl->lcellp->states &= ~CLinkedCell;
- }
- tc->lcellp = tcl;
- tcl->lcellp = tc;
- }
- tc->states |= aflags;
- tc->timeout = timeout;
-
- memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
- for (i = 0; i < MAXCELLHOSTS; i++) {
- struct server *ts;
- afs_uint32 temp = acellHosts[i];
- if (!temp)
- break;
- ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
- ts->cell = tc;
- ts->flags &= ~SRVR_ISGONE;
- tc->cellHosts[i] = ts;
- afs_PutServer(ts, WRITE_LOCK);
- }
- afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
-
- if (newc) {
- struct cell_name *cn;
-
- cn = afs_cellname_lookup_name(acellName);
- if (!cn)
- cn = afs_cellname_new(acellName, 0);
-
- tc->cnamep = cn;
- tc->cellNum = cn->cellnum;
- tc->cellIndex = afs_cellindex++;
- afs_stats_cmperf.numCellsVisible++;
- QAdd(&CellLRU, &tc->lruq);
- }
-
- ReleaseWriteLock(&tc->lock);
- ReleaseWriteLock(&afs_xcell);
- afs_PutCell(tc, 0);
- afs_DynrootInvalidate();
- return 0;
-
- bad:
- if (newc) {
- afs_osi_FreeStr(tc->cellName);
- afs_osi_Free(tc, sizeof(struct cell));
- }
- ReleaseWriteLock(&tc->lock);
- ReleaseWriteLock(&afs_xcell);
- return code;
-}
-
-/*
- * Miscellaneous stuff
- *
- * afs_CellInit: perform whatever initialization is necessary
- * shutdown_cell: called on shutdown, should deallocate memory, etc
- * afs_RemoveCellEntry: remove a server from a cell's server list
- * afs_CellOrAliasExists: check if the given name exists as a cell or alias
- * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
- * afs_CellNumValid: check if a cell number is valid (also set the used flag)
- */
-
-void
-afs_CellInit()
-{
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
-#ifdef AFS_AFSDB_ENV
- RWLOCK_INIT(&afsdb_req.lock, "afsdb_req.lock");
-#endif
- QInit(&CellLRU);
-
- afs_cellindex = 0;
- afs_cellalias_index = 0;
-}
-
-void
-shutdown_cell()
-{
- struct afs_q *cq, *tq;
- struct cell *tc;
-
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
-
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq);
- tq = QNext(cq);
- if (tc->cellName)
- afs_osi_FreeStr(tc->cellName);
- afs_osi_Free(tc, sizeof(struct cell));
- }
- QInit(&CellLRU);
-
-{
- struct cell_name *cn = afs_cellname_head;
-
- while (cn) {
- struct cell_name *next = cn->next;
-
- afs_osi_FreeStr(cn->cellname);
- afs_osi_Free(cn, sizeof(struct cell_name));
- cn = next;
- }
-}
-}
-
-void
-afs_RemoveCellEntry(struct server *srvp)
-{
- struct cell *tc;
- afs_int32 j, k;
-
- tc = srvp->cell;
- if (!tc)
- return;
-
- /* Remove the server structure from the cell list - if there */
- ObtainWriteLock(&tc->lock, 200);
- for (j = k = 0; j < MAXCELLHOSTS; j++) {
- if (!tc->cellHosts[j])
- break;
- if (tc->cellHosts[j] != srvp) {
- tc->cellHosts[k++] = tc->cellHosts[j];
- }
- }
- if (k == 0) {
- /* What do we do if we remove the last one? */
- }
- for (; k < MAXCELLHOSTS; k++) {
- tc->cellHosts[k] = 0;
- }
- ReleaseWriteLock(&tc->lock);
-}
-
-static int
-afs_CellOrAliasExists_nl(char *aname)
-{
- struct cell *c;
- struct cell_alias *ca;
-
- c = afs_FindCellByName_nl(aname, READ_LOCK);
- if (c) {
- afs_PutCell(c, READ_LOCK);
- return 1;
- }
-
- ca = afs_FindCellAlias(aname);
- if (ca) {
- afs_PutCellAlias(ca);
- return 1;
- }
-
- return 0;
-}
-
-int
-afs_CellOrAliasExists(char *aname)
-{
- int ret;
-
- ObtainReadLock(&afs_xcell);
- ret = afs_CellOrAliasExists_nl(aname);
- ReleaseReadLock(&afs_xcell);
-
- return ret;
-}
-
-int
-afs_CellNumValid(afs_int32 cellnum)
-{
- struct cell_name *cn;
-
- ObtainReadLock(&afs_xcell);
- cn = afs_cellname_lookup_id(cellnum);
- ReleaseReadLock(&afs_xcell);
- if (cn) {
- cn->used = 1;
- return 1;
- } else {
- 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_chunk.c,v 1.6 2003/07/15 23:14:11 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h"
-
-/*
- * Chunk module.
- */
-
-afs_int32 afs_FirstCSize = AFS_DEFAULTCSIZE;
-afs_int32 afs_OtherCSize = AFS_DEFAULTCSIZE;
-afs_int32 afs_LogChunk = AFS_DEFAULTLSIZE;
-
-#ifdef notdef
-int
-afs_ChunkOffset(offset)
- afs_int32 offset;
-{
-
- AFS_STATCNT(afs_ChunkOffset);
- if (offset < afs_FirstCSize)
- return offset;
- else
- return ((offset - afs_FirstCSize) & (afs_OtherCSize - 1));
-}
-
-
-int
-afs_Chunk(offset)
- afs_int32 offset;
-{
- AFS_STATCNT(afs_Chunk);
- if (offset < afs_FirstCSize)
- return 0;
- else
- return (((offset - afs_FirstCSize) >> afs_LogChunk) + 1);
-}
-
-
-int
-afs_ChunkBase(offset)
- int offset;
-{
- AFS_STATCNT(afs_ChunkBase);
- if (offset < afs_FirstCSize)
- return 0;
- else
- return (((offset - afs_FirstCSize) & ~(afs_OtherCSize - 1)) +
- afs_FirstCSize);
-}
-
-
-int
-afs_ChunkSize(offset)
- afs_int32 offset;
-{
- AFS_STATCNT(afs_ChunkSize);
- if (offset < afs_FirstCSize)
- return afs_FirstCSize;
- else
- return afs_OtherCSize;
-}
-
-
-int
-afs_ChunkToBase(chunk)
- afs_int32 chunk;
-{
- AFS_STATCNT(afs_ChunkToBase);
- if (chunk == 0)
- return 0;
- else
- return (afs_FirstCSize + ((chunk - 1) << afs_LogChunk));
-}
-
-
-int
-afs_ChunkToSize(chunk)
- afs_int32 chunk;
-{
- AFS_STATCNT(afs_ChunkToSize);
- if (chunk == 0)
- return afs_FirstCSize;
- else
- return afs_OtherCSize;
-}
-
-/* sizes are a power of two */
-int
-afs_SetChunkSize(chunk)
- afs_int32 chunk;
-{
- AFS_STATCNT(afs_SetChunkSize);
- afs_LogChunk = chunk;
- afs_FirstCSize = afs_OtherCSize = (1 << chunk);
-}
-
-#endif /* notdef */
+++ /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
- */
-
-#ifndef AFS_CHUNKOPS
-#define AFS_CHUNKOPS 1
-
-/* macros to compute useful numbers from offsets. AFS_CHUNK gives the chunk
- number for a given offset; AFS_CHUNKOFFSET gives the offset into the chunk
- and AFS_CHUNKBASE gives the byte offset of the base of the chunk.
- AFS_CHUNKSIZE gives the size of the chunk containing an offset.
- AFS_CHUNKTOBASE converts a chunk # to a base position.
- Chunks are 0 based and go up by exactly 1, covering the file.
- The other fields are internal and shouldn't be used */
-/* basic parameters */
-#ifdef AFS_NOCHUNKING
-
-#define AFS_OTHERCSIZE 0x10000
-#define AFS_LOGCHUNK 16
-#define AFS_FIRSTCSIZE 0x40000000
-
-#else /* AFS_NOCHUNKING */
-
-#define AFS_OTHERCSIZE (afs_OtherCSize)
-#define AFS_LOGCHUNK (afs_LogChunk)
-#define AFS_FIRSTCSIZE (afs_FirstCSize)
-
-#define AFS_DEFAULTCSIZE 0x10000
-#define AFS_DEFAULTLSIZE 16
-
-#endif /* AFS_NOCHUNKING */
-
-#define AFS_MINCHUNK 13 /* 8k is minimum */
-#define AFS_MAXCHUNK 18 /* 256K is maximum */
-
-#define AFS_CHUNKOFFSET(offset) ((offset < afs_FirstCSize) ? offset : \
- ((offset - afs_FirstCSize) & (afs_OtherCSize - 1)))
-
-#define AFS_CHUNK(offset) ((offset < afs_FirstCSize) ? 0 : \
- (((offset - afs_FirstCSize) >> afs_LogChunk) + 1))
-
-#define AFS_CHUNKBASE(offset) ((offset < afs_FirstCSize) ? 0 : \
- (((offset - afs_FirstCSize) & ~(afs_OtherCSize - 1)) + afs_FirstCSize))
-
-#define AFS_CHUNKSIZE(offset) ((offset < afs_FirstCSize) ? afs_FirstCSize : \
- afs_OtherCSize)
-
-#define AFS_CHUNKTOBASE(chunk) ((chunk == 0) ? 0 : \
- ((afs_size_t) afs_FirstCSize + ((afs_size_t) (chunk - 1) << afs_LogChunk)))
-
-#define AFS_CHUNKTOSIZE(chunk) ((chunk == 0) ? afs_FirstCSize : afs_OtherCSize)
-
-/* sizes are a power of two */
-#define AFS_SETCHUNKSIZE(chunk) { afs_LogChunk = chunk; \
- afs_FirstCSize = afs_OtherCSize = (1 << chunk); }
-
-/*
- * Functions exported by a cache type
- */
-
-struct afs_cacheOps {
-#if defined(AFS_SUN57_64BIT_ENV) || defined(AFS_SGI62_ENV)
- void *(*open) (ino_t ainode);
-#else
- void *(*open) (afs_int32 ainode);
-#endif
- int (*truncate) (struct osi_file * fp, afs_int32 len);
- int (*fread) (struct osi_file * fp, int offset, void *buf, afs_int32 len);
- int (*fwrite) (struct osi_file * fp, afs_int32 offset, void *buf,
- afs_int32 len);
- int (*close) (struct osi_file * fp);
- int (*vread) (register struct vcache * avc, struct uio * auio,
- struct AFS_UCRED * acred, daddr_t albn, struct buf ** abpp,
- int noLock);
- int (*vwrite) (register struct vcache * avc, struct uio * auio, int aio,
- struct AFS_UCRED * acred, int noLock);
- int (*FetchProc) (register struct rx_call * acall,
- struct osi_file * afile, afs_size_t abase,
- struct dcache * adc, struct vcache * avc,
- afs_size_t * abytesToXferP, afs_size_t * abytesXferredP,
- afs_int32 lengthFound);
- int (*StoreProc) (register struct rx_call * acall,
- struct osi_file * afile, register afs_int32 alen,
- struct vcache * avc, int *shouldWake,
- afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP);
- struct dcache *(*GetDSlot) (register afs_int32 aslot,
- register struct dcache * tmpdc);
- struct volume *(*GetVolSlot) (void);
- int (*HandleLink) (register struct vcache * avc, struct vrequest * areq);
-};
-
-/* Ideally we should have used consistent naming - like COP_OPEN, COP_TRUNCATE, etc. */
-#define afs_CFileOpen(inode) (void *)(*(afs_cacheType->open))(inode)
-#define afs_CFileTruncate(handle, size) (*(afs_cacheType->truncate))((handle), size)
-#define afs_CFileRead(file, offset, data, size) (*(afs_cacheType->fread))(file, offset, data, size)
-#define afs_CFileWrite(file, offset, data, size) (*(afs_cacheType->fwrite))(file, offset, data, size)
-#define afs_CFileClose(handle) (*(afs_cacheType->close))(handle)
-#define afs_GetDSlot(slot, adc) (*(afs_cacheType->GetDSlot))(slot, adc)
-#define afs_GetVolSlot() (*(afs_cacheType->GetVolSlot))()
-#define afs_HandleLink(avc, areq) (*(afs_cacheType->HandleLink))(avc, areq)
-
-#define afs_CacheFetchProc(call, file, base, adc, avc, toxfer, xfered, length) \
- (*(afs_cacheType->FetchProc))(call, file, (afs_size_t)base, adc, avc, (afs_size_t *)toxfer, (afs_size_t *)xfered, length)
-#define afs_CacheStoreProc(call, file, bytes, avc, wake, toxfer, xfered) \
- (*(afs_cacheType->StoreProc))(call, file, bytes, avc, wake, toxfer, xfered)
-
-#endif /* AFS_CHUNKOPS */
+++ /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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_conn.c,v 1.13 2003/07/15 23:14:11 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* ! AFS_HPUX110_ENV */
-#endif /* !defined(UKERNEL) */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-/* Exported variables */
-afs_rwlock_t afs_xconn; /* allocation lock for new things */
-afs_rwlock_t afs_xinterface; /* for multiple client address */
-afs_int32 cryptall = 0; /* encrypt all communications */
-
-
-unsigned int VNOSERVERS = 0;
-struct conn *
-afs_Conn(register struct VenusFid *afid, register struct vrequest *areq,
- afs_int32 locktype)
-{
- u_short fsport = AFS_FSPORT;
- struct volume *tv;
- struct conn *tconn = NULL;
- struct srvAddr *lowp = NULL;
- struct unixuser *tu;
- int notbusy;
- int i;
- struct srvAddr *sa1p;
-
- AFS_STATCNT(afs_Conn);
- tv = afs_GetVolume(afid, areq, READ_LOCK);
- if (!tv) {
- if (areq) {
- afs_FinalizeReq(areq);
- areq->volumeError = 1;
- }
- return NULL;
- }
-
- if (tv->serverHost[0] && tv->serverHost[0]->cell) {
- fsport = tv->serverHost[0]->cell->fsport;
- } else {
- VNOSERVERS++;
- }
-
- /* First is always lowest rank, if it's up */
- if ((tv->status[0] == not_busy) && tv->serverHost[0]
- && !(tv->serverHost[0]->addr->sa_flags & SRVR_ISDOWN))
- lowp = tv->serverHost[0]->addr;
-
- /* Otherwise we look at all of them. There are seven levels of
- * not_busy. This means we will check a volume seven times before it
- * is marked offline. Ideally, we only need two levels, but this
- * serves a second purpose of waiting some number of seconds before
- * the client decides the volume is offline (ie: a clone could finish
- * in this time).
- */
- for (notbusy = not_busy; (!lowp && (notbusy <= end_not_busy)); notbusy++) {
- for (i = 0; i < MAXHOSTS && tv->serverHost[i]; i++) {
- if (tv->status[i] != notbusy) {
- if (tv->status[i] == rd_busy || tv->status[i] == rdwr_busy) {
- if (!areq->busyCount)
- areq->busyCount++;
- } else if (tv->status[i] == offline) {
- if (!areq->volumeError)
- areq->volumeError = VOLMISSING;
- }
- continue;
- }
- for (sa1p = tv->serverHost[i]->addr; sa1p; sa1p = sa1p->next_sa) {
- if (sa1p->sa_flags & SRVR_ISDOWN)
- continue;
- if (!lowp || (lowp->sa_iprank > sa1p->sa_iprank))
- lowp = sa1p;
- }
- }
- }
- afs_PutVolume(tv, READ_LOCK);
-
- if (lowp) {
- tu = afs_GetUser(areq->uid, afid->Cell, SHARED_LOCK);
- tconn = afs_ConnBySA(lowp, fsport, afid->Cell, tu, 0 /*!force */ ,
- 1 /*create */ , locktype);
-
- afs_PutUser(tu, SHARED_LOCK);
- }
-
- return tconn;
-} /*afs_Conn */
-
-
-struct conn *
-afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
- struct unixuser *tu, int force_if_down, afs_int32 create,
- afs_int32 locktype)
-{
- struct conn *tc = 0;
- struct rx_securityClass *csec; /*Security class object */
- int isec; /*Security index */
- int service;
-
- if (!sap || ((sap->sa_flags & SRVR_ISDOWN) && !force_if_down)) {
- /* sa is known down, and we don't want to force it. */
- return NULL;
- }
-
- ObtainSharedLock(&afs_xconn, 15);
- for (tc = sap->conns; tc; tc = tc->next) {
- if (tc->user == tu && tc->port == aport) {
- break;
- }
- }
-
- if (!tc && !create) {
- ReleaseSharedLock(&afs_xconn);
- return NULL;
- }
-
- if (!tc) {
- /* No such connection structure exists. Create one and splice it in.
- * Make sure the server record has been marked as used (for the purposes
- * of calculating up & down times, it's now considered to be an
- * ``active'' server). Also make sure the server's lastUpdateEvalTime
- * gets set, marking the time of its ``birth''.
- */
- UpgradeSToWLock(&afs_xconn, 37);
- tc = (struct conn *)afs_osi_Alloc(sizeof(struct conn));
- memset((char *)tc, 0, sizeof(struct conn));
-
- tc->user = tu;
- tc->port = aport;
- tc->srvr = sap;
- tc->refCount = 0; /* bumped below */
- tc->forceConnectFS = 1;
- tc->id = (struct rx_connection *)0;
- tc->next = sap->conns;
- sap->conns = tc;
- afs_ActivateServer(sap);
-
- ConvertWToSLock(&afs_xconn);
- }
- tc->refCount++;
-
- if (tu->states & UTokensBad) {
- /* we may still have an authenticated RPC connection here,
- * we'll have to create a new, unauthenticated, connection.
- * Perhaps a better way to do this would be to set
- * conn->forceConnectFS on all conns when the token first goes
- * bad, but that's somewhat trickier, due to locking
- * constraints (though not impossible).
- */
- if (tc->id && (rx_SecurityClassOf(tc->id) != 0)) {
- tc->forceConnectFS = 1; /* force recreation of connection */
- }
- tu->vid = UNDEFVID; /* forcibly disconnect the authentication info */
- }
-
- if (tc->forceConnectFS) {
- UpgradeSToWLock(&afs_xconn, 38);
- csec = (struct rx_securityClass *)0;
- if (tc->id) {
- AFS_GUNLOCK();
- rx_DestroyConnection(tc->id);
- AFS_GLOCK();
- }
- /*
- * Stupid hack to determine if using vldb service or file system
- * service.
- */
- if (aport == sap->server->cell->vlport)
- service = 52;
- else
- service = 1;
- isec = 0;
- if (tu->vid != UNDEFVID) {
- int level;
-
- if (cryptall) {
- level = rxkad_crypt;
- } else {
- level = rxkad_clear;
- }
- isec = 2;
- /* kerberos tickets on channel 2 */
- csec = rxkad_NewClientSecurityObject(level, tu->ct.HandShakeKey,
- /* kvno */
- tu->ct.AuthHandle, tu->stLen,
- tu->stp);
- }
- if (isec == 0)
- csec = rxnull_NewClientSecurityObject();
- AFS_GUNLOCK();
- tc->id = rx_NewConnection(sap->sa_ip, aport, service, csec, isec);
- AFS_GLOCK();
- if (service == 52) {
- rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
- }
-
- tc->forceConnectFS = 0; /* apparently we're appropriately connected now */
- if (csec)
- rxs_Release(csec);
- ConvertWToSLock(&afs_xconn);
- }
-
- ReleaseSharedLock(&afs_xconn);
- return tc;
-}
-
-/*
- * afs_ConnByHost
- *
- * forceConnectFS is set whenever we must recompute the connection. UTokensBad
- * is true only if we know that the tokens are bad. We thus clear this flag
- * when we get a new set of tokens..
- * Having force... true and UTokensBad true simultaneously means that the tokens
- * went bad and we're supposed to create a new, unauthenticated, connection.
- */
-struct conn *
-afs_ConnByHost(struct server *aserver, unsigned short aport, afs_int32 acell,
- struct vrequest *areq, int aforce, afs_int32 locktype)
-{
- struct unixuser *tu;
- struct conn *tc = 0;
- struct srvAddr *sa = 0;
-
- AFS_STATCNT(afs_ConnByHost);
-/*
- 1. look for an existing connection
- 2. create a connection at an address believed to be up
- (if aforce is true, create a connection at the first address)
-*/
-
- tu = afs_GetUser(areq->uid, acell, SHARED_LOCK);
-
- for (sa = aserver->addr; sa; sa = sa->next_sa) {
- tc = afs_ConnBySA(sa, aport, acell, tu, aforce,
- 0 /*don't create one */ ,
- locktype);
- if (tc)
- break;
- }
-
- if (!tc) {
- for (sa = aserver->addr; sa; sa = sa->next_sa) {
- tc = afs_ConnBySA(sa, aport, acell, tu, aforce,
- 1 /*create one */ ,
- locktype);
- if (tc)
- break;
- }
- }
-
- afs_PutUser(tu, SHARED_LOCK);
- return tc;
-
-} /*afs_ConnByHost */
-
-
-struct conn *
-afs_ConnByMHosts(struct server *ahosts[], unsigned short aport,
- afs_int32 acell, register struct vrequest *areq,
- afs_int32 locktype)
-{
- register afs_int32 i;
- register struct conn *tconn;
- register struct server *ts;
-
- /* try to find any connection from the set */
- AFS_STATCNT(afs_ConnByMHosts);
- for (i = 0; i < MAXCELLHOSTS; i++) {
- if ((ts = ahosts[i]) == NULL)
- break;
- tconn = afs_ConnByHost(ts, aport, acell, areq, 0, locktype);
- if (tconn) {
- return tconn;
- }
- }
- return NULL;
-
-} /*afs_ConnByMHosts */
-
-
-void
-afs_PutConn(register struct conn *ac, afs_int32 locktype)
-{
- AFS_STATCNT(afs_PutConn);
- ac->refCount--;
-} /*afs_PutConn */
-
-
-/* for multi homed clients, an RPC may timeout because of a
-client network interface going down. We need to reopen new
-connections in this case
-*/
-void
-ForceNewConnections(struct srvAddr *sap)
-{
- struct conn *tc = 0;
-
- if (!sap)
- return; /* defensive check */
-
- /* if client is not multihomed, do nothing */
- ObtainReadLock(&afs_xinterface);
- if (afs_cb_interface.numberOfInterfaces <= 1) {
- ReleaseReadLock(&afs_xinterface);
- return;
- }
- ReleaseReadLock(&afs_xinterface);
-
- ObtainWriteLock(&afs_xconn, 413);
- for (tc = sap->conns; tc; tc = tc->next)
- tc->forceConnectFS = 1;
- ReleaseWriteLock(&afs_xconn);
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_daemons.c,v 1.28 2004/03/11 19:14:46 rees Exp $");
-
-#ifdef AFS_AIX51_ENV
-#define __FULL_PROTO
-#include <sys/sleep.h>
-#endif
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics gathering code */
-#include "afs/afs_cbqueue.h"
-#ifdef AFS_AIX_ENV
-#include <sys/adspace.h> /* for vm_att(), vm_det() */
-#endif
-
-
-/* background request queue size */
-afs_lock_t afs_xbrs; /* lock for brs */
-static int brsInit = 0;
-short afs_brsWaiters = 0; /* number of users waiting for brs buffers */
-short afs_brsDaemons = 0; /* number of daemons waiting for brs requests */
-struct brequest afs_brs[NBRS]; /* request structures */
-struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
-static int afs_brs_count = 0; /* request counter, to service reqs in order */
-
-static int rxepoch_checked = 0;
-#define afs_CheckRXEpoch() {if (rxepoch_checked == 0 && rxkad_EpochWasSet) { \
- rxepoch_checked = 1; afs_GCUserData(/* force flag */ 1); } }
-
-/* PAG garbage collection */
-/* We induce a compile error if param.h does not define AFS_GCPAGS */
-afs_int32 afs_gcpags = AFS_GCPAGS;
-afs_int32 afs_gcpags_procsize = 0;
-
-afs_int32 afs_CheckServerDaemonStarted = 0;
-#ifdef DEFAULT_PROBE_INTERVAL
-afs_int32 PROBE_INTERVAL = DEFAULT_PROBE_INTERVAL; /* overridding during compile */
-#else
-afs_int32 PROBE_INTERVAL = 180; /* default to 3 min */
-#endif
-
-#define PROBE_WAIT() (1000 * (PROBE_INTERVAL - ((afs_random() & 0x7fffffff) \
- % (PROBE_INTERVAL/2))))
-
-void
-afs_CheckServerDaemon(void)
-{
- afs_int32 now, delay, lastCheck, last10MinCheck;
-
- afs_CheckServerDaemonStarted = 1;
-
- while (afs_initState < 101)
- afs_osi_Sleep(&afs_initState);
- afs_osi_Wait(PROBE_WAIT(), &AFS_CSWaitHandler, 0);
-
- last10MinCheck = lastCheck = osi_Time();
- while (1) {
- if (afs_termState == AFSOP_STOP_CS) {
- afs_termState = AFSOP_STOP_BKG;
- afs_osi_Wakeup(&afs_termState);
- break;
- }
-
- now = osi_Time();
- if (PROBE_INTERVAL + lastCheck <= now) {
- afs_CheckServers(1, NULL); /* check down servers */
- lastCheck = now = osi_Time();
- }
-
- if (600 + last10MinCheck <= now) {
- afs_Trace1(afs_iclSetp, CM_TRACE_PROBEUP, ICL_TYPE_INT32, 600);
- afs_CheckServers(0, NULL);
- last10MinCheck = now = osi_Time();
- }
- /* shutdown check. */
- if (afs_termState == AFSOP_STOP_CS) {
- afs_termState = AFSOP_STOP_BKG;
- afs_osi_Wakeup(&afs_termState);
- break;
- }
-
- /* Compute time to next probe. */
- delay = PROBE_INTERVAL + lastCheck;
- if (delay > 600 + last10MinCheck)
- delay = 600 + last10MinCheck;
- delay -= now;
- if (delay < 1)
- delay = 1;
- afs_osi_Wait(delay * 1000, &AFS_CSWaitHandler, 0);
- }
- afs_CheckServerDaemonStarted = 0;
-}
-
-void
-afs_Daemon(void)
-{
- afs_int32 code;
- struct afs_exporter *exporter;
- afs_int32 now;
- afs_int32 last3MinCheck, last10MinCheck, last60MinCheck, lastNMinCheck;
- afs_int32 last1MinCheck;
- afs_uint32 lastCBSlotBump;
- char cs_warned = 0;
-
- AFS_STATCNT(afs_Daemon);
- last1MinCheck = last3MinCheck = last60MinCheck = last10MinCheck =
- lastNMinCheck = 0;
-
- afs_rootFid.Fid.Volume = 0;
- while (afs_initState < 101)
- afs_osi_Sleep(&afs_initState);
-
- now = osi_Time();
- lastCBSlotBump = now;
-
- /* when a lot of clients are booted simultaneously, they develop
- * annoying synchronous VL server bashing behaviors. So we stagger them.
- */
- last1MinCheck = now + ((afs_random() & 0x7fffffff) % 60); /* an extra 30 */
- last3MinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);
- last60MinCheck = now - 1800 + ((afs_random() & 0x7fffffff) % 3600);
- last10MinCheck = now - 300 + ((afs_random() & 0x7fffffff) % 600);
- lastNMinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);
-
- /* start off with afs_initState >= 101 (basic init done) */
- while (1) {
- afs_CheckCallbacks(20); /* unstat anything which will expire soon */
-
- /* things to do every 20 seconds or less - required by protocol spec */
- if (afs_nfsexporter)
- afs_FlushActiveVcaches(0); /* flush NFS writes */
- afs_FlushVCBs(1); /* flush queued callbacks */
- afs_MaybeWakeupTruncateDaemon(); /* free cache space if have too */
- rx_CheckPackets(); /* Does RX need more packets? */
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- /*
- * Hack: We always want to make sure there are plenty free
- * entries in the small free pool so that we don't have to
- * worry about rx (with disabled interrupts) to have to call
- * malloc). So we do the dummy call below...
- */
- if (((afs_stats_cmperf.SmallBlocksAlloced -
- afs_stats_cmperf.SmallBlocksActive)
- <= AFS_SALLOC_LOW_WATER))
- osi_FreeSmallSpace(osi_AllocSmallSpace(AFS_SMALLOCSIZ));
- if (((afs_stats_cmperf.MediumBlocksAlloced -
- afs_stats_cmperf.MediumBlocksActive)
- <= AFS_MALLOC_LOW_WATER + 50))
- osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER * 2);
-#endif
-
- now = osi_Time();
- if (lastCBSlotBump + CBHTSLOTLEN < now) { /* pretty time-dependant */
- lastCBSlotBump = now;
- if (afs_BumpBase()) {
- afs_CheckCallbacks(20); /* unstat anything which will expire soon */
- }
- }
-
- if (last1MinCheck + 60 < now) {
- /* things to do every minute */
- DFlush(); /* write out dir buffers */
- afs_WriteThroughDSlots(); /* write through cacheinfo entries */
- afs_FlushActiveVcaches(1); /* keep flocks held & flush nfs writes */
-#ifdef AFS_DISCON_ENV
- afs_StoreDirtyVcaches();
-#endif
- afs_CheckRXEpoch();
- last1MinCheck = now;
- }
-
- if (last3MinCheck + 180 < now) {
- afs_CheckTokenCache(); /* check for access cache resets due to expired
- * tickets */
- last3MinCheck = now;
- }
- if (!afs_CheckServerDaemonStarted) {
- /* Do the check here if the correct afsd is not installed. */
- if (!cs_warned) {
- cs_warned = 1;
- printf("Please install afsd with check server daemon.\n");
- }
- if (lastNMinCheck + PROBE_INTERVAL < now) {
- /* only check down servers */
- afs_CheckServers(1, NULL);
- lastNMinCheck = now;
- }
- }
- if (last10MinCheck + 600 < now) {
-#ifdef AFS_USERSPACE_IP_ADDR
- extern int rxi_GetcbiInfo(void);
-#endif
- afs_Trace1(afs_iclSetp, CM_TRACE_PROBEUP, ICL_TYPE_INT32, 600);
-#ifdef AFS_USERSPACE_IP_ADDR
- if (rxi_GetcbiInfo()) { /* addresses changed from last time */
- afs_FlushCBs();
- }
-#else /* AFS_USERSPACE_IP_ADDR */
- if (rxi_GetIFInfo()) { /* addresses changed from last time */
- afs_FlushCBs();
- }
-#endif /* else AFS_USERSPACE_IP_ADDR */
- if (!afs_CheckServerDaemonStarted)
- afs_CheckServers(0, NULL);
- afs_GCUserData(0); /* gc old conns */
- /* This is probably the wrong way of doing GC for the various exporters but it will suffice for a while */
- for (exporter = root_exported; exporter;
- exporter = exporter->exp_next) {
- (void)EXP_GC(exporter, 0); /* Generalize params */
- }
- {
- static int cnt = 0;
- if (++cnt < 12) {
- afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED |
- AFS_VOLCHECK_BUSY);
- } else {
- cnt = 0;
- afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED |
- AFS_VOLCHECK_BUSY |
- AFS_VOLCHECK_MTPTS);
- }
- }
- last10MinCheck = now;
- }
- if (last60MinCheck + 3600 < now) {
- afs_Trace1(afs_iclSetp, CM_TRACE_PROBEVOLUME, ICL_TYPE_INT32,
- 3600);
- afs_CheckRootVolume();
-#if AFS_GCPAGS
- if (afs_gcpags == AFS_GCPAGS_OK) {
- afs_int32 didany;
- afs_GCPAGs(&didany);
- }
-#endif
- last60MinCheck = now;
- }
- if (afs_initState < 300) { /* while things ain't rosy */
- code = afs_CheckRootVolume();
- if (code == 0)
- afs_initState = 300; /* succeeded */
- if (afs_initState < 200)
- afs_initState = 200; /* tried once */
- afs_osi_Wakeup(&afs_initState);
- }
-
- /* 18285 is because we're trying to divide evenly into 128, that is,
- * CBSlotLen, while staying just under 20 seconds. If CBSlotLen
- * changes, should probably change this interval, too.
- * Some of the preceding actions may take quite some time, so we
- * might not want to wait the entire interval */
- now = 18285 - (osi_Time() - now);
- if (now > 0) {
- afs_osi_Wait(now, &AFS_WaitHandler, 0);
- }
-
- if (afs_termState == AFSOP_STOP_AFS) {
- if (afs_CheckServerDaemonStarted)
- afs_termState = AFSOP_STOP_CS;
- else
- afs_termState = AFSOP_STOP_BKG;
- afs_osi_Wakeup(&afs_termState);
- return;
- }
- }
-}
-
-int
-afs_CheckRootVolume(void)
-{
- char rootVolName[32];
- struct volume *tvp = NULL;
- int usingDynroot = afs_GetDynrootEnable();
- int localcell;
-
- AFS_STATCNT(afs_CheckRootVolume);
- if (*afs_rootVolumeName == 0) {
- strcpy(rootVolName, "root.afs");
- } else {
- strcpy(rootVolName, afs_rootVolumeName);
- }
-
- if (!usingDynroot) {
- struct cell *lc = afs_GetPrimaryCell(READ_LOCK);
-
- if (!lc)
- return ENOENT;
- localcell = lc->cellNum;
- afs_PutCell(lc, READ_LOCK);
- }
-
- if (usingDynroot) {
- afs_GetDynrootFid(&afs_rootFid);
- tvp = afs_GetVolume(&afs_rootFid, NULL, READ_LOCK);
- } else {
- tvp = afs_GetVolumeByName(rootVolName, localcell, 1, NULL, READ_LOCK);
- }
- if (!tvp && !usingDynroot) {
- char buf[128];
- int len = strlen(rootVolName);
-
- if ((len < 9) || strcmp(&rootVolName[len - 9], ".readonly")) {
- strcpy(buf, rootVolName);
- afs_strcat(buf, ".readonly");
- tvp = afs_GetVolumeByName(buf, localcell, 1, NULL, READ_LOCK);
- }
- }
- if (tvp) {
- if (!usingDynroot) {
- int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
- afs_rootFid.Cell = localcell;
- if (afs_rootFid.Fid.Volume && afs_rootFid.Fid.Volume != volid
- && afs_globalVp) {
- /* If we had a root fid before and it changed location we reset
- * the afs_globalVp so that it will be reevaluated.
- * Just decrement the reference count. This only occurs during
- * initial cell setup and can panic the machine if we set the
- * count to zero and fs checkv is executed when the current
- * directory is /afs.
- */
- AFS_FAST_RELE(afs_globalVp);
- afs_globalVp = 0;
- }
- afs_rootFid.Fid.Volume = volid;
- afs_rootFid.Fid.Vnode = 1;
- afs_rootFid.Fid.Unique = 1;
- }
- afs_initState = 300; /* won */
- afs_osi_Wakeup(&afs_initState);
- afs_PutVolume(tvp, READ_LOCK);
- }
-#ifdef AFS_DEC_ENV
-/* This is to make sure that we update the root gnode */
-/* every time root volume gets released */
- {
- struct gnode *rootgp;
- struct mount *mp;
- int code;
-
- /* Only do this if afs_globalVFS is properly set due to race conditions
- * this routine could be called before the gfs_mount is performed!
- * Furthermore, afs_root (called below) *waits* until
- * initState >= 200, so we don't try this until we've gotten
- * at least that far */
- if (afs_globalVFS && afs_initState >= 200) {
- if (code = afs_root(afs_globalVFS, &rootgp))
- return code;
- mp = (struct mount *)afs_globalVFS->vfs_data;
- mp->m_rootgp = gget(mp, 0, 0, (char *)rootgp);
- afs_unlock(mp->m_rootgp); /* unlock basic gnode */
- afs_vrele(VTOAFS(rootgp)); /* zap afs_root's vnode hold */
- }
- }
-#endif
- if (afs_rootFid.Fid.Volume)
- return 0;
- else
- return ENOENT;
-}
-
-/* ptr_parm 0 is the pathname, size_parm 0 to the fetch is the chunk number */
-static void
-BPath(register struct brequest *ab)
-{
- register struct dcache *tdc = NULL;
- struct vcache *tvc = NULL;
- struct vnode *tvn = NULL;
-#ifdef AFS_LINUX22_ENV
- struct dentry *dp = NULL;
-#endif
- afs_size_t offset, len;
- struct vrequest treq;
- afs_int32 code;
-
- AFS_STATCNT(BPath);
- if ((code = afs_InitReq(&treq, ab->cred)))
- return;
- AFS_GUNLOCK();
-#ifdef AFS_LINUX22_ENV
- code = gop_lookupname((char *)ab->ptr_parm[0], AFS_UIOSYS, 1, NULL, &dp);
- if (dp)
- tvn = (struct vnode *)dp->d_inode;
-#else
- code = gop_lookupname((char *)ab->ptr_parm[0], AFS_UIOSYS, 1, NULL, &tvn);
-#endif
- AFS_GLOCK();
- osi_FreeLargeSpace((char *)ab->ptr_parm[0]); /* free path name buffer here */
- if (code)
- return;
- /* now path may not have been in afs, so check that before calling our cache manager */
- if (!tvn || !IsAfsVnode(tvn)) {
- /* release it and give up */
- if (tvn) {
-#ifdef AFS_DEC_ENV
- grele(tvn);
-#else
-#ifdef AFS_LINUX22_ENV
- dput(dp);
-#else
- AFS_RELE(tvn);
-#endif
-#endif
- }
- return;
- }
-#ifdef AFS_DEC_ENV
- tvc = VTOAFS(afs_gntovn(tvn));
-#else
- tvc = VTOAFS(tvn);
-#endif
- /* here we know its an afs vnode, so we can get the data for the chunk */
- tdc = afs_GetDCache(tvc, ab->size_parm[0], &treq, &offset, &len, 1);
- if (tdc) {
- afs_PutDCache(tdc);
- }
-#ifdef AFS_DEC_ENV
- grele(tvn);
-#else
-#ifdef AFS_LINUX22_ENV
- dput(dp);
-#else
- AFS_RELE(tvn);
-#endif
-#endif
-}
-
-/* size_parm 0 to the fetch is the chunk number,
- * ptr_parm 0 is the dcache entry to wakeup,
- * size_parm 1 is true iff we should release the dcache entry here.
- */
-static void
-BPrefetch(register struct brequest *ab)
-{
- register struct dcache *tdc;
- register struct vcache *tvc;
- afs_size_t offset, len;
- struct vrequest treq;
-
- AFS_STATCNT(BPrefetch);
- if ((len = afs_InitReq(&treq, ab->cred)))
- return;
- tvc = ab->vc;
- tdc = afs_GetDCache(tvc, ab->size_parm[0], &treq, &offset, &len, 1);
- if (tdc) {
- afs_PutDCache(tdc);
- }
- /* now, dude may be waiting for us to clear DFFetchReq bit; do so. Can't
- * use tdc from GetDCache since afs_GetDCache may fail, but someone may
- * be waiting for our wakeup anyway.
- */
- tdc = (struct dcache *)(ab->ptr_parm[0]);
- ObtainSharedLock(&tdc->lock, 640);
- if (tdc->mflags & DFFetchReq) {
- UpgradeSToWLock(&tdc->lock, 641);
- tdc->mflags &= ~DFFetchReq;
- ReleaseWriteLock(&tdc->lock);
- } else {
- ReleaseSharedLock(&tdc->lock);
- }
- afs_osi_Wakeup(&tdc->validPos);
- if (ab->size_parm[1]) {
- afs_PutDCache(tdc); /* put this one back, too */
- }
-}
-
-
-static void
-BStore(register struct brequest *ab)
-{
- register struct vcache *tvc;
- register afs_int32 code;
- struct vrequest treq;
-#if defined(AFS_SGI_ENV)
- struct cred *tmpcred;
-#endif
-
- AFS_STATCNT(BStore);
- if ((code = afs_InitReq(&treq, ab->cred)))
- return;
- code = 0;
- tvc = ab->vc;
-#if defined(AFS_SGI_ENV)
- /*
- * Since StoreOnLastReference can end up calling osi_SyncVM which
- * calls into VM code that assumes that u.u_cred has the
- * correct credentials, we set our to theirs for this xaction
- */
- tmpcred = OSI_GET_CURRENT_CRED();
- OSI_SET_CURRENT_CRED(ab->cred);
-
- /*
- * To avoid recursion since the WriteLock may be released during VM
- * operations, we hold the VOP_RWLOCK across this transaction as
- * do the other callers of StoreOnLastReference
- */
- AFS_RWLOCK((vnode_t *) tvc, 1);
-#endif
- ObtainWriteLock(&tvc->lock, 209);
- code = afs_StoreOnLastReference(tvc, &treq);
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SGI_ENV)
- OSI_SET_CURRENT_CRED(tmpcred);
- AFS_RWUNLOCK((vnode_t *) tvc, 1);
-#endif
- /* now set final return code, and wakeup anyone waiting */
- if ((ab->flags & BUVALID) == 0) {
- ab->code = afs_CheckCode(code, &treq, 43); /* set final code, since treq doesn't go across processes */
- ab->flags |= BUVALID;
- if (ab->flags & BUWAIT) {
- ab->flags &= ~BUWAIT;
- afs_osi_Wakeup(ab);
- }
- }
-}
-
-/* release a held request buffer */
-void
-afs_BRelease(register struct brequest *ab)
-{
-
- AFS_STATCNT(afs_BRelease);
- MObtainWriteLock(&afs_xbrs, 294);
- if (--ab->refCount <= 0) {
- ab->flags = 0;
- }
- if (afs_brsWaiters)
- afs_osi_Wakeup(&afs_brsWaiters);
- MReleaseWriteLock(&afs_xbrs);
-}
-
-/* return true if bkg fetch daemons are all busy */
-int
-afs_BBusy(void)
-{
- AFS_STATCNT(afs_BBusy);
- if (afs_brsDaemons > 0)
- return 0;
- return 1;
-}
-
-struct brequest *
-afs_BQueue(register short aopcode, register struct vcache *avc,
- afs_int32 dontwait, afs_int32 ause, struct AFS_UCRED *acred,
- afs_size_t asparm0, afs_size_t asparm1, void *apparm0)
-{
- register int i;
- register struct brequest *tb;
-
- AFS_STATCNT(afs_BQueue);
- MObtainWriteLock(&afs_xbrs, 296);
- while (1) {
- tb = afs_brs;
- for (i = 0; i < NBRS; i++, tb++) {
- if (tb->refCount == 0)
- break;
- }
- if (i < NBRS) {
- /* found a buffer */
- tb->opcode = aopcode;
- tb->vc = avc;
- tb->cred = acred;
- crhold(tb->cred);
- if (avc) {
-#ifdef AFS_DEC_ENV
- avc->vrefCount++;
-#else
- VN_HOLD(AFSTOV(avc));
-#endif
- }
- tb->refCount = ause + 1;
- tb->size_parm[0] = asparm0;
- tb->size_parm[1] = asparm1;
- tb->ptr_parm[0] = apparm0;
- tb->flags = 0;
- tb->code = 0;
- tb->ts = afs_brs_count++;
- /* if daemons are waiting for work, wake them up */
- if (afs_brsDaemons > 0) {
- afs_osi_Wakeup(&afs_brsDaemons);
- }
- MReleaseWriteLock(&afs_xbrs);
- return tb;
- }
- if (dontwait) {
- MReleaseWriteLock(&afs_xbrs);
- return NULL;
- }
- /* no free buffers, sleep a while */
- afs_brsWaiters++;
- MReleaseWriteLock(&afs_xbrs);
- afs_osi_Sleep(&afs_brsWaiters);
- MObtainWriteLock(&afs_xbrs, 301);
- afs_brsWaiters--;
- }
-}
-
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX41_ENV
-/* AIX 4.1 has a much different sleep/wakeup mechanism available for use.
- * The modifications here will work for either a UP or MP machine.
- */
-struct buf *afs_asyncbuf = (struct buf *)0;
-tid_t afs_asyncbuf_cv = EVENT_NULL;
-afs_int32 afs_biodcnt = 0;
-
-/* in implementing this, I assumed that all external linked lists were
- * null-terminated.
- *
- * Several places in this code traverse a linked list. The algorithm
- * used here is probably unfamiliar to most people. Careful examination
- * will show that it eliminates an assignment inside the loop, as compared
- * to the standard algorithm, at the cost of occasionally using an extra
- * variable.
- */
-
-/* get_bioreq()
- *
- * This function obtains, and returns, a pointer to a buffer for
- * processing by a daemon. It sleeps until such a buffer is available.
- * The source of buffers for it is the list afs_asyncbuf (see also
- * naix_vm_strategy). This function may be invoked concurrently by
- * several processes, that is, several instances of the same daemon.
- * naix_vm_strategy, which adds buffers to the list, runs at interrupt
- * level, while get_bioreq runs at process level.
- *
- * Since AIX 4.1 can wake just one process at a time, the separate sleep
- * addresses have been removed.
- * Note that the kernel_lock is held until the e_sleep_thread() occurs.
- * The afs_asyncbuf_lock is primarily used to serialize access between
- * process and interrupts.
- */
-Simple_lock afs_asyncbuf_lock;
-/*static*/ struct buf *
-afs_get_bioreq()
-{
- struct buf *bp = NULL;
- struct buf *bestbp;
- struct buf **bestlbpP, **lbpP;
- long bestage, stop;
- struct buf *t1P, *t2P; /* temp pointers for list manipulation */
- int oldPriority;
- afs_uint32 wait_ret;
- struct afs_bioqueue *s;
-
- /* ??? Does the forward pointer of the returned buffer need to be NULL?
- */
-
- /* Disable interrupts from the strategy function, and save the
- * prior priority level and lock access to the afs_asyncbuf.
- */
- AFS_GUNLOCK();
- oldPriority = disable_lock(INTMAX, &afs_asyncbuf_lock);
-
- while (1) {
- if (afs_asyncbuf) {
- /* look for oldest buffer */
- bp = bestbp = afs_asyncbuf;
- bestage = (long)bestbp->av_back;
- bestlbpP = &afs_asyncbuf;
- while (1) {
- lbpP = &bp->av_forw;
- bp = *lbpP;
- if (!bp)
- break;
- if ((long)bp->av_back - bestage < 0) {
- bestbp = bp;
- bestlbpP = lbpP;
- bestage = (long)bp->av_back;
- }
- }
- bp = bestbp;
- *bestlbpP = bp->av_forw;
- break;
- } else {
- /* If afs_asyncbuf is null, it is necessary to go to sleep.
- * e_wakeup_one() ensures that only one thread wakes.
- */
- int interrupted;
- /* The LOCK_HANDLER indicates to e_sleep_thread to only drop the
- * lock on an MP machine.
- */
- interrupted =
- e_sleep_thread(&afs_asyncbuf_cv, &afs_asyncbuf_lock,
- LOCK_HANDLER | INTERRUPTIBLE);
- if (interrupted == THREAD_INTERRUPTED) {
- /* re-enable interrupts from strategy */
- unlock_enable(oldPriority, &afs_asyncbuf_lock);
- AFS_GLOCK();
- return (NULL);
- }
- } /* end of "else asyncbuf is empty" */
- } /* end of "inner loop" */
-
- /*assert (bp); */
-
- unlock_enable(oldPriority, &afs_asyncbuf_lock);
- AFS_GLOCK();
-
- /* For the convenience of other code, replace the gnodes in
- * the b_vp field of bp and the other buffers on the b_work
- * chain with the corresponding vnodes.
- *
- * ??? what happens to the gnodes? They're not just cut loose,
- * are they?
- */
- for (t1P = bp;;) {
- t2P = (struct buf *)t1P->b_work;
- t1P->b_vp = ((struct gnode *)t1P->b_vp)->gn_vnode;
- if (!t2P)
- break;
-
- t1P = (struct buf *)t2P->b_work;
- t2P->b_vp = ((struct gnode *)t2P->b_vp)->gn_vnode;
- if (!t1P)
- break;
- }
-
- /* If the buffer does not specify I/O, it may immediately
- * be returned to the caller. This condition is detected
- * by examining the buffer's flags (the b_flags field). If
- * the B_PFPROT bit is set, the buffer represents a protection
- * violation, rather than a request for I/O. The remainder
- * of the outer loop handles the case where the B_PFPROT bit is clear.
- */
- if (bp->b_flags & B_PFPROT) {
- return (bp);
- }
- return (bp);
-
-} /* end of function get_bioreq() */
-
-
-/* afs_BioDaemon
- *
- * This function is the daemon. It is called from the syscall
- * interface. Ordinarily, a script or an administrator will run a
- * daemon startup utility, specifying the number of I/O daemons to
- * run. The utility will fork off that number of processes,
- * each making the appropriate syscall, which will cause this
- * function to be invoked.
- */
-static int afs_initbiod = 0; /* this is self-initializing code */
-int DOvmlock = 0;
-int
-afs_BioDaemon(afs_int32 nbiods)
-{
- afs_int32 code, s, pflg = 0;
- label_t jmpbuf;
- struct buf *bp, *bp1, *tbp1, *tbp2; /* temp pointers only */
- caddr_t tmpaddr;
- struct vnode *vp;
- struct vcache *vcp;
- char tmperr;
- if (!afs_initbiod) {
- /* XXX ###1 XXX */
- afs_initbiod = 1;
- /* pin lock, since we'll be using it in an interrupt. */
- lock_alloc(&afs_asyncbuf_lock, LOCK_ALLOC_PIN, 2, 1);
- simple_lock_init(&afs_asyncbuf_lock);
- pin(&afs_asyncbuf, sizeof(struct buf *));
- pin(&afs_asyncbuf_cv, sizeof(afs_int32));
- }
-
- /* Ignore HUP signals... */
- {
- sigset_t sigbits, osigbits;
- /*
- * add SIGHUP to the set of already masked signals
- */
- SIGFILLSET(sigbits); /* allow all signals */
- SIGDELSET(sigbits, SIGHUP); /* except SIGHUP */
- limit_sigs(&sigbits, &osigbits); /* and already masked */
- }
- /* Main body starts here -- this is an intentional infinite loop, and
- * should NEVER exit
- *
- * Now, the loop will exit if get_bioreq() returns NULL, indicating
- * that we've been interrupted.
- */
- while (1) {
- bp = afs_get_bioreq();
- if (!bp)
- break; /* we were interrupted */
- if (code = setjmpx(&jmpbuf)) {
- /* This should not have happend, maybe a lack of resources */
- AFS_GUNLOCK();
- s = disable_lock(INTMAX, &afs_asyncbuf_lock);
- for (bp1 = bp; bp; bp = bp1) {
- if (bp1)
- bp1 = (struct buf *)bp1->b_work;
- bp->b_actf = 0;
- bp->b_error = code;
- bp->b_flags |= B_ERROR;
- iodone(bp);
- }
- unlock_enable(s, &afs_asyncbuf_lock);
- AFS_GLOCK();
- continue;
- }
- vcp = VTOAFS(bp->b_vp);
- if (bp->b_flags & B_PFSTORE) { /* XXXX */
- ObtainWriteLock(&vcp->lock, 404);
- if (vcp->v.v_gnode->gn_mwrcnt) {
- afs_offs_t newlength =
- (afs_offs_t) dbtob(bp->b_blkno) + bp->b_bcount;
- if (vcp->m.Length < newlength) {
- afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
- ICL_TYPE_STRING, __FILE__, ICL_TYPE_LONG,
- __LINE__, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(vcp->m.Length),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(newlength));
- vcp->m.Length = newlength;
- }
- }
- ReleaseWriteLock(&vcp->lock);
- }
- /* If the buffer represents a protection violation, rather than
- * an actual request for I/O, no special action need be taken.
- */
- if (bp->b_flags & B_PFPROT) {
- iodone(bp); /* Notify all users of the buffer that we're done */
- clrjmpx(&jmpbuf);
- continue;
- }
- if (DOvmlock)
- ObtainWriteLock(&vcp->pvmlock, 211);
- /*
- * First map its data area to a region in the current address space
- * by calling vm_att with the subspace identifier, and a pointer to
- * the data area. vm_att returns a new data area pointer, but we
- * also want to hang onto the old one.
- */
- tmpaddr = bp->b_baddr;
- bp->b_baddr = (caddr_t) vm_att(bp->b_xmemd.subspace_id, tmpaddr);
- tmperr = afs_ustrategy(bp); /* temp variable saves offset calculation */
- if (tmperr) { /* in non-error case */
- bp->b_flags |= B_ERROR; /* should other flags remain set ??? */
- bp->b_error = tmperr;
- }
-
- /* Unmap the buffer's data area by calling vm_det. Reset data area
- * to the value that we saved above.
- */
- vm_det(bp->b_baddr);
- bp->b_baddr = tmpaddr;
-
- /*
- * buffer may be linked with other buffers via the b_work field.
- * See also naix_vm_strategy. For each buffer in the chain (including
- * bp) notify all users of the buffer that the daemon is finished
- * using it by calling iodone.
- * assumes iodone can modify the b_work field.
- */
- for (tbp1 = bp;;) {
- tbp2 = (struct buf *)tbp1->b_work;
- iodone(tbp1);
- if (!tbp2)
- break;
-
- tbp1 = (struct buf *)tbp2->b_work;
- iodone(tbp2);
- if (!tbp1)
- break;
- }
- if (DOvmlock)
- ReleaseWriteLock(&vcp->pvmlock); /* Unlock the vnode. */
- clrjmpx(&jmpbuf);
- } /* infinite loop (unless we're interrupted) */
-} /* end of afs_BioDaemon() */
-
-#else /* AFS_AIX41_ENV */
-
-
-#define squeue afs_q
-struct afs_bioqueue {
- struct squeue lruq;
- int sleeper;
- int cnt;
-};
-struct afs_bioqueue afs_bioqueue;
-struct buf *afs_busyq = NULL;
-struct buf *afs_asyncbuf;
-afs_int32 afs_biodcnt = 0;
-
-/* in implementing this, I assumed that all external linked lists were
- * null-terminated.
- *
- * Several places in this code traverse a linked list. The algorithm
- * used here is probably unfamiliar to most people. Careful examination
- * will show that it eliminates an assignment inside the loop, as compared
- * to the standard algorithm, at the cost of occasionally using an extra
- * variable.
- */
-
-/* get_bioreq()
- *
- * This function obtains, and returns, a pointer to a buffer for
- * processing by a daemon. It sleeps until such a buffer is available.
- * The source of buffers for it is the list afs_asyncbuf (see also
- * naix_vm_strategy). This function may be invoked concurrently by
- * several processes, that is, several instances of the same daemon.
- * naix_vm_strategy, which adds buffers to the list, runs at interrupt
- * level, while get_bioreq runs at process level.
- *
- * The common kernel paradigm of sleeping and waking up, in which all the
- * competing processes sleep waiting for wakeups on one address, is not
- * followed here. Instead, the following paradigm is used: when a daemon
- * goes to sleep, it checks for other sleeping daemons. If there aren't any,
- * it sleeps on the address of variable afs_asyncbuf. But if there is
- * already a daemon sleeping on that address, it threads its own unique
- * address onto a list, and sleeps on that address. This way, every
- * sleeper is sleeping on a different address, and every wakeup wakes up
- * exactly one daemon. This prevents a whole bunch of daemons from waking
- * up and then immediately having to go back to sleep. This provides a
- * performance gain and makes the I/O scheduling a bit more deterministic.
- * The list of sleepers is variable afs_bioqueue. The unique address
- * on which to sleep is passed to get_bioreq as its parameter.
- */
-/*static*/ struct buf *
-afs_get_bioreq(self)
- struct afs_bioqueue *self; /* address on which to sleep */
-
-{
- struct buf *bp = NULL;
- struct buf *bestbp;
- struct buf **bestlbpP, **lbpP;
- int bestage, stop;
- struct buf *t1P, *t2P; /* temp pointers for list manipulation */
- int oldPriority;
- afs_uint32 wait_ret;
- struct afs_bioqueue *s;
-
- /* ??? Does the forward pointer of the returned buffer need to be NULL?
- */
-
- /* Disable interrupts from the strategy function, and save the
- * prior priority level
- */
- oldPriority = i_disable(INTMAX);
-
- /* Each iteration of following loop either pulls
- * a buffer off afs_asyncbuf, or sleeps.
- */
- while (1) { /* inner loop */
- if (afs_asyncbuf) {
- /* look for oldest buffer */
- bp = bestbp = afs_asyncbuf;
- bestage = (int)bestbp->av_back;
- bestlbpP = &afs_asyncbuf;
- while (1) {
- lbpP = &bp->av_forw;
- bp = *lbpP;
- if (!bp)
- break;
- if ((int)bp->av_back - bestage < 0) {
- bestbp = bp;
- bestlbpP = lbpP;
- bestage = (int)bp->av_back;
- }
- }
- bp = bestbp;
- *bestlbpP = bp->av_forw;
- break;
- } else {
- int interrupted;
-
- /* If afs_asyncbuf is null, it is necessary to go to sleep.
- * There are two possibilities: either there is already a
- * daemon that is sleeping on the address of afs_asyncbuf,
- * or there isn't.
- */
- if (afs_bioqueue.sleeper) {
- /* enqueue */
- QAdd(&(afs_bioqueue.lruq), &(self->lruq));
- interrupted = sleep((caddr_t) self, PCATCH | (PZERO + 1));
- if (self->lruq.next != &self->lruq) { /* XXX ##3 XXX */
- QRemove(&(self->lruq)); /* dequeue */
- }
- self->cnt++;
- afs_bioqueue.sleeper = FALSE;
- if (interrupted) {
- /* re-enable interrupts from strategy */
- i_enable(oldPriority);
- return (NULL);
- }
- continue;
- } else {
- afs_bioqueue.sleeper = TRUE;
- interrupted =
- sleep((caddr_t) & afs_asyncbuf, PCATCH | (PZERO + 1));
- afs_bioqueue.sleeper = FALSE;
- if (interrupted) {
- /*
- * We need to wakeup another daemon if present
- * since we were waiting on afs_asyncbuf.
- */
-#ifdef notdef /* The following doesn't work as advertised */
- if (afs_bioqueue.lruq.next != &afs_bioqueue.lruq) {
- struct squeue *bq = afs_bioqueue.lruq.next;
- QRemove(bq);
- wakeup(bq);
- }
-#endif
- /* re-enable interrupts from strategy */
- i_enable(oldPriority);
- return (NULL);
- }
- continue;
- }
-
- } /* end of "else asyncbuf is empty" */
- } /* end of "inner loop" */
-
- /*assert (bp); */
-
- i_enable(oldPriority); /* re-enable interrupts from strategy */
-
- /* For the convenience of other code, replace the gnodes in
- * the b_vp field of bp and the other buffers on the b_work
- * chain with the corresponding vnodes.
- *
- * ??? what happens to the gnodes? They're not just cut loose,
- * are they?
- */
- for (t1P = bp;;) {
- t2P = (struct buf *)t1P->b_work;
- t1P->b_vp = ((struct gnode *)t1P->b_vp)->gn_vnode;
- if (!t2P)
- break;
-
- t1P = (struct buf *)t2P->b_work;
- t2P->b_vp = ((struct gnode *)t2P->b_vp)->gn_vnode;
- if (!t1P)
- break;
- }
-
- /* If the buffer does not specify I/O, it may immediately
- * be returned to the caller. This condition is detected
- * by examining the buffer's flags (the b_flags field). If
- * the B_PFPROT bit is set, the buffer represents a protection
- * violation, rather than a request for I/O. The remainder
- * of the outer loop handles the case where the B_PFPROT bit is clear.
- */
- if (bp->b_flags & B_PFPROT) {
- return (bp);
- }
-
- /* wake up another process to handle the next buffer, and return
- * bp to the caller.
- */
- oldPriority = i_disable(INTMAX);
-
- /* determine where to find the sleeping process.
- * There are two cases: either it is sleeping on
- * afs_asyncbuf, or it is sleeping on its own unique
- * address. These cases are distinguished by examining
- * the sleeper field of afs_bioqueue.
- */
- if (afs_bioqueue.sleeper) {
- wakeup(&afs_asyncbuf);
- } else {
- if (afs_bioqueue.lruq.next == &afs_bioqueue.lruq) {
- /* queue is empty, what now? ??? */
- /* Should this be impossible, or does */
- /* it just mean that nobody is sleeping? */ ;
- } else {
- struct squeue *bq = afs_bioqueue.lruq.next;
- QRemove(bq);
- QInit(bq);
- wakeup(bq);
- afs_bioqueue.sleeper = TRUE;
- }
- }
- i_enable(oldPriority); /* re-enable interrupts from strategy */
- return (bp);
-
-} /* end of function get_bioreq() */
-
-
-/* afs_BioDaemon
- *
- * This function is the daemon. It is called from the syscall
- * interface. Ordinarily, a script or an administrator will run a
- * daemon startup utility, specifying the number of I/O daemons to
- * run. The utility will fork off that number of processes,
- * each making the appropriate syscall, which will cause this
- * function to be invoked.
- */
-static int afs_initbiod = 0; /* this is self-initializing code */
-int DOvmlock = 0;
-afs_BioDaemon(nbiods)
- afs_int32 nbiods;
-{
- struct afs_bioqueue *self;
- afs_int32 code, s, pflg = 0;
- label_t jmpbuf;
- struct buf *bp, *bp1, *tbp1, *tbp2; /* temp pointers only */
- caddr_t tmpaddr;
- struct vnode *vp;
- struct vcache *vcp;
- char tmperr;
- if (!afs_initbiod) {
- /* XXX ###1 XXX */
- afs_initbiod = 1;
- /* Initialize the queue of waiting processes, afs_bioqueue. */
- QInit(&(afs_bioqueue.lruq));
- }
-
- /* establish ourself as a kernel process so shutdown won't kill us */
-/* u.u_procp->p_flag |= SKPROC;*/
-
- /* Initialize a token (self) to use in the queue of sleeping processes. */
- self = (struct afs_bioqueue *)afs_osi_Alloc(sizeof(struct afs_bioqueue));
- pin(self, sizeof(struct afs_bioqueue)); /* fix in memory */
- memset(self, 0, sizeof(*self));
- QInit(&(self->lruq)); /* initialize queue entry pointers */
-
-
- /* Ignore HUP signals... */
- SIGDELSET(u.u_procp->p_sig, SIGHUP);
- SIGADDSET(u.u_procp->p_sigignore, SIGHUP);
- SIGDELSET(u.u_procp->p_sigcatch, SIGHUP);
- /* Main body starts here -- this is an intentional infinite loop, and
- * should NEVER exit
- *
- * Now, the loop will exit if get_bioreq() returns NULL, indicating
- * that we've been interrupted.
- */
- while (1) {
- bp = afs_get_bioreq(self);
- if (!bp)
- break; /* we were interrupted */
- if (code = setjmpx(&jmpbuf)) {
- /* This should not have happend, maybe a lack of resources */
- s = splimp();
- for (bp1 = bp; bp; bp = bp1) {
- if (bp1)
- bp1 = bp1->b_work;
- bp->b_actf = 0;
- bp->b_error = code;
- bp->b_flags |= B_ERROR;
- iodone(bp);
- }
- splx(s);
- continue;
- }
- vcp = VTOAFS(bp->b_vp);
- if (bp->b_flags & B_PFSTORE) {
- ObtainWriteLock(&vcp->lock, 210);
- if (vcp->v.v_gnode->gn_mwrcnt) {
- afs_offs_t newlength =
- (afs_offs_t) dbtob(bp->b_blkno) + bp->b_bcount;
- if (vcp->m.Length < newlength) {
- afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH,
- ICL_TYPE_STRING, __FILE__, ICL_TYPE_LONG,
- __LINE__, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(vcp->m.Length),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(newlength));
- vcp->m.Length = newlength;
- }
- }
- ReleaseWriteLock(&vcp->lock);
- }
- /* If the buffer represents a protection violation, rather than
- * an actual request for I/O, no special action need be taken.
- */
- if (bp->b_flags & B_PFPROT) {
- iodone(bp); /* Notify all users of the buffer that we're done */
- continue;
- }
- if (DOvmlock)
- ObtainWriteLock(&vcp->pvmlock, 558);
- /*
- * First map its data area to a region in the current address space
- * by calling vm_att with the subspace identifier, and a pointer to
- * the data area. vm_att returns a new data area pointer, but we
- * also want to hang onto the old one.
- */
- tmpaddr = bp->b_baddr;
- bp->b_baddr = vm_att(bp->b_xmemd.subspace_id, tmpaddr);
- tmperr = afs_ustrategy(bp); /* temp variable saves offset calculation */
- if (tmperr) { /* in non-error case */
- bp->b_flags |= B_ERROR; /* should other flags remain set ??? */
- bp->b_error = tmperr;
- }
-
- /* Unmap the buffer's data area by calling vm_det. Reset data area
- * to the value that we saved above.
- */
- vm_det(bp->b_un.b_addr);
- bp->b_baddr = tmpaddr;
-
- /*
- * buffer may be linked with other buffers via the b_work field.
- * See also naix_vm_strategy. For each buffer in the chain (including
- * bp) notify all users of the buffer that the daemon is finished
- * using it by calling iodone.
- * assumes iodone can modify the b_work field.
- */
- for (tbp1 = bp;;) {
- tbp2 = (struct buf *)tbp1->b_work;
- iodone(tbp1);
- if (!tbp2)
- break;
-
- tbp1 = (struct buf *)tbp2->b_work;
- iodone(tbp2);
- if (!tbp1)
- break;
- }
- if (DOvmlock)
- ReleaseWriteLock(&vcp->pvmlock); /* Unlock the vnode. */
- clrjmpx(&jmpbuf);
- } /* infinite loop (unless we're interrupted) */
- unpin(self, sizeof(struct afs_bioqueue));
- afs_osi_Free(self, sizeof(struct afs_bioqueue));
-} /* end of afs_BioDaemon() */
-#endif /* AFS_AIX41_ENV */
-#endif /* AFS_AIX32_ENV */
-
-
-int afs_nbrs = 0;
-void
-afs_BackgroundDaemon(void)
-{
- struct brequest *tb;
- int i, foundAny;
-
- AFS_STATCNT(afs_BackgroundDaemon);
- /* initialize subsystem */
- if (brsInit == 0) {
- LOCK_INIT(&afs_xbrs, "afs_xbrs");
- memset((char *)afs_brs, 0, sizeof(afs_brs));
- brsInit = 1;
-#if defined (AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
- /*
- * steal the first daemon for doing delayed DSlot flushing
- * (see afs_GetDownDSlot)
- */
- AFS_GUNLOCK();
- afs_sgidaemon();
- return;
-#endif
- }
- afs_nbrs++;
-
- MObtainWriteLock(&afs_xbrs, 302);
- while (1) {
- int min_ts = 0;
- struct brequest *min_tb = NULL;
-
- if (afs_termState == AFSOP_STOP_BKG) {
- if (--afs_nbrs <= 0)
- afs_termState = AFSOP_STOP_TRUNCDAEMON;
- MReleaseWriteLock(&afs_xbrs);
- afs_osi_Wakeup(&afs_termState);
- return;
- }
-
- /* find a request */
- tb = afs_brs;
- foundAny = 0;
- for (i = 0; i < NBRS; i++, tb++) {
- /* look for request with smallest ts */
- if ((tb->refCount > 0) && !(tb->flags & BSTARTED)) {
- /* new request, not yet picked up */
- if ((min_tb && (min_ts - tb->ts > 0)) || !min_tb) {
- min_tb = tb;
- min_ts = tb->ts;
- }
- }
- }
- if ((tb = min_tb)) {
- /* claim and process this request */
- tb->flags |= BSTARTED;
- MReleaseWriteLock(&afs_xbrs);
- foundAny = 1;
- afs_Trace1(afs_iclSetp, CM_TRACE_BKG1, ICL_TYPE_INT32,
- tb->opcode);
- if (tb->opcode == BOP_FETCH)
- BPrefetch(tb);
- else if (tb->opcode == BOP_STORE)
- BStore(tb);
- else if (tb->opcode == BOP_PATH)
- BPath(tb);
- else
- panic("background bop");
- if (tb->vc) {
-#ifdef AFS_DEC_ENV
- tb->vc->vrefCount--; /* fix up reference count */
-#else
- AFS_RELE(AFSTOV(tb->vc)); /* MUST call vnode layer or could lose vnodes */
-#endif
- tb->vc = NULL;
- }
- if (tb->cred) {
- crfree(tb->cred);
- tb->cred = (struct AFS_UCRED *)0;
- }
- afs_BRelease(tb); /* this grabs and releases afs_xbrs lock */
- MObtainWriteLock(&afs_xbrs, 305);
- }
- if (!foundAny) {
- /* wait for new request */
- afs_brsDaemons++;
- MReleaseWriteLock(&afs_xbrs);
- afs_osi_Sleep(&afs_brsDaemons);
- MObtainWriteLock(&afs_xbrs, 307);
- afs_brsDaemons--;
- }
- }
-}
-
-
-void
-shutdown_daemons(void)
-{
- AFS_STATCNT(shutdown_daemons);
- if (afs_cold_shutdown) {
- afs_brsDaemons = brsInit = 0;
- rxepoch_checked = afs_nbrs = 0;
- memset((char *)afs_brs, 0, sizeof(afs_brs));
- memset((char *)&afs_xbrs, 0, sizeof(afs_lock_t));
- afs_brsWaiters = 0;
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX41_ENV
- lock_free(&afs_asyncbuf_lock);
- unpin(&afs_asyncbuf, sizeof(struct buf *));
- pin(&afs_asyncbuf_cv, sizeof(afs_int32));
-#else /* AFS_AIX41_ENV */
- afs_busyq = NULL;
- afs_biodcnt = 0;
- memset((char *)&afs_bioqueue, 0, sizeof(struct afs_bioqueue));
-#endif
- afs_initbiod = 0;
-#endif
- }
-}
-
-#if defined(AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
-/*
- * sgi - daemon - handles certain operations that otherwise
- * would use up too much kernel stack space
- *
- * This all assumes that since the caller must have the xdcache lock
- * exclusively that the list will never be more than one long
- * and noone else can attempt to add anything until we're done.
- */
-SV_TYPE afs_sgibksync;
-SV_TYPE afs_sgibkwait;
-lock_t afs_sgibklock;
-struct dcache *afs_sgibklist;
-
-int
-afs_sgidaemon(void)
-{
- int s;
- struct dcache *tdc;
-
- if (afs_sgibklock == NULL) {
- SV_INIT(&afs_sgibksync, "bksync", 0, 0);
- SV_INIT(&afs_sgibkwait, "bkwait", 0, 0);
- SPINLOCK_INIT(&afs_sgibklock, "bklock");
- }
- s = SPLOCK(afs_sgibklock);
- for (;;) {
- /* wait for something to do */
- SP_WAIT(afs_sgibklock, s, &afs_sgibksync, PINOD);
- osi_Assert(afs_sgibklist);
-
- /* XX will probably need to generalize to real list someday */
- s = SPLOCK(afs_sgibklock);
- while (afs_sgibklist) {
- tdc = afs_sgibklist;
- afs_sgibklist = NULL;
- SPUNLOCK(afs_sgibklock, s);
- AFS_GLOCK();
- tdc->dflags &= ~DFEntryMod;
- afs_WriteDCache(tdc, 1);
- AFS_GUNLOCK();
- s = SPLOCK(afs_sgibklock);
- }
-
- /* done all the work - wake everyone up */
- while (SV_SIGNAL(&afs_sgibkwait));
- }
-}
-#endif
+++ /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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_dcache.c,v 1.42 2004/05/08 04:33:07 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/afs_osidnlc.h"
-
-/* Forward declarations. */
-static void afs_GetDownD(int anumber, int *aneedSpace);
-static void afs_FreeDiscardedDCache(void);
-static void afs_DiscardDCache(struct dcache *);
-static void afs_FreeDCache(struct dcache *);
-
-/*
- * --------------------- Exported definitions ---------------------
- */
-afs_lock_t afs_xdcache; /*Lock: alloc new disk cache entries */
-afs_int32 afs_freeDCList; /*Free list for disk cache entries */
-afs_int32 afs_freeDCCount; /*Count of elts in freeDCList */
-afs_int32 afs_discardDCList; /*Discarded disk cache entries */
-afs_int32 afs_discardDCCount; /*Count of elts in discardDCList */
-struct dcache *afs_freeDSList; /*Free list for disk slots */
-struct dcache *afs_Initial_freeDSList; /*Initial list for above */
-ino_t cacheInode; /*Inode for CacheItems file */
-struct osi_file *afs_cacheInodep = 0; /* file for CacheItems inode */
-struct afs_q afs_DLRU; /*dcache LRU */
-afs_int32 afs_dhashsize = 1024;
-afs_int32 *afs_dvhashTbl; /*Data cache hash table */
-afs_int32 *afs_dchashTbl; /*Data cache hash table */
-afs_int32 *afs_dvnextTbl; /*Dcache hash table links */
-afs_int32 *afs_dcnextTbl; /*Dcache hash table links */
-struct dcache **afs_indexTable; /*Pointers to dcache entries */
-afs_hyper_t *afs_indexTimes; /*Dcache entry Access times */
-afs_int32 *afs_indexUnique; /*dcache entry Fid.Unique */
-unsigned char *afs_indexFlags; /*(only one) Is there data there? */
-afs_hyper_t afs_indexCounter; /*Fake time for marking index
- * entries */
-afs_int32 afs_cacheFiles = 0; /*Size of afs_indexTable */
-afs_int32 afs_cacheBlocks; /*1K blocks in cache */
-afs_int32 afs_cacheStats; /*Stat entries in cache */
-afs_int32 afs_blocksUsed; /*Number of blocks in use */
-afs_int32 afs_blocksDiscarded; /*Blocks freed but not truncated */
-afs_int32 afs_fsfragsize = 1023; /*Underlying Filesystem minimum unit
- *of disk allocation usually 1K
- *this value is (truefrag -1 ) to
- *save a bunch of subtracts... */
-#ifdef AFS_64BIT_CLIENT
-#ifdef AFS_VM_RDWR_ENV
-afs_size_t afs_vmMappingEnd; /* for large files (>= 2GB) the VM
- * mapping an 32bit addressing machines
- * can only be used below the 2 GB
- * line. From this point upwards we
- * must do direct I/O into the cache
- * files. The value should be on a
- * chunk boundary. */
-#endif /* AFS_VM_RDWR_ENV */
-#endif /* AFS_64BIT_CLIENT */
-
-/* The following is used to ensure that new dcache's aren't obtained when
- * the cache is nearly full.
- */
-int afs_WaitForCacheDrain = 0;
-int afs_TruncateDaemonRunning = 0;
-int afs_CacheTooFull = 0;
-
-afs_int32 afs_dcentries; /* In-memory dcache entries */
-
-
-int dcacheDisabled = 0;
-
-static int afs_UFSCacheFetchProc(), afs_UFSCacheStoreProc();
-struct afs_cacheOps afs_UfsCacheOps = {
- osi_UFSOpen,
- osi_UFSTruncate,
- afs_osi_Read,
- afs_osi_Write,
- osi_UFSClose,
- afs_UFSRead,
- afs_UFSWrite,
- afs_UFSCacheFetchProc,
- afs_UFSCacheStoreProc,
- afs_UFSGetDSlot,
- afs_UFSGetVolSlot,
- afs_UFSHandleLink,
-};
-
-struct afs_cacheOps afs_MemCacheOps = {
- afs_MemCacheOpen,
- afs_MemCacheTruncate,
- afs_MemReadBlk,
- afs_MemWriteBlk,
- afs_MemCacheClose,
- afs_MemRead,
- afs_MemWrite,
- afs_MemCacheFetchProc,
- afs_MemCacheStoreProc,
- afs_MemGetDSlot,
- afs_MemGetVolSlot,
- afs_MemHandleLink,
-};
-
-int cacheDiskType; /*Type of backing disk for cache */
-struct afs_cacheOps *afs_cacheType;
-
-
-
-
-/*
- * afs_StoreWarn
- *
- * Description:
- * Warn about failing to store a file.
- *
- * Parameters:
- * acode : Associated error code.
- * avolume : Volume involved.
- * aflags : How to handle the output:
- * aflags & 1: Print out on console
- * aflags & 2: Print out on controlling tty
- *
- * Environment:
- * Call this from close call when vnodeops is RCS unlocked.
- */
-
-void
-afs_StoreWarn(register afs_int32 acode, afs_int32 avolume,
- register afs_int32 aflags)
-{
- static char problem_fmt[] =
- "afs: failed to store file in volume %d (%s)\n";
- static char problem_fmt_w_error[] =
- "afs: failed to store file in volume %d (error %d)\n";
- static char netproblems[] = "network problems";
- static char partfull[] = "partition full";
- static char overquota[] = "over quota";
-
- AFS_STATCNT(afs_StoreWarn);
- if (acode < 0) {
- /*
- * Network problems
- */
- if (aflags & 1)
- afs_warn(problem_fmt, avolume, netproblems);
- if (aflags & 2)
- afs_warnuser(problem_fmt, avolume, netproblems);
- } else if (acode == ENOSPC) {
- /*
- * Partition full
- */
- if (aflags & 1)
- afs_warn(problem_fmt, avolume, partfull);
- if (aflags & 2)
- afs_warnuser(problem_fmt, avolume, partfull);
- } else
-#ifdef EDQUOT
- /* EDQUOT doesn't exist on solaris and won't be sent by the server.
- * Instead ENOSPC will be sent...
- */
- if (acode == EDQUOT) {
- /*
- * Quota exceeded
- */
- if (aflags & 1)
- afs_warn(problem_fmt, avolume, overquota);
- if (aflags & 2)
- afs_warnuser(problem_fmt, avolume, overquota);
- } else
-#endif
- {
- /*
- * Unknown error
- */
- if (aflags & 1)
- afs_warn(problem_fmt_w_error, avolume, acode);
- if (aflags & 2)
- afs_warnuser(problem_fmt_w_error, avolume, acode);
- }
-} /*afs_StoreWarn */
-
-void
-afs_MaybeWakeupTruncateDaemon(void)
-{
- if (!afs_CacheTooFull && afs_CacheIsTooFull()) {
- afs_CacheTooFull = 1;
- if (!afs_TruncateDaemonRunning)
- afs_osi_Wakeup((int *)afs_CacheTruncateDaemon);
- } else if (!afs_TruncateDaemonRunning
- && afs_blocksDiscarded > CM_MAXDISCARDEDCHUNKS) {
- afs_osi_Wakeup((int *)afs_CacheTruncateDaemon);
- }
-}
-
-/* Keep statistics on run time for afs_CacheTruncateDaemon. This is a
- * struct so we need only export one symbol for AIX.
- */
-static struct CTD_stats {
- osi_timeval_t CTD_beforeSleep;
- osi_timeval_t CTD_afterSleep;
- osi_timeval_t CTD_sleepTime;
- osi_timeval_t CTD_runTime;
- int CTD_nSleeps;
-} CTD_stats;
-
-u_int afs_min_cache = 0;
-void
-afs_CacheTruncateDaemon(void)
-{
- osi_timeval_t CTD_tmpTime;
- u_int counter;
- u_int cb_lowat;
- u_int dc_hiwat =
- (100 - CM_DCACHECOUNTFREEPCT +
- CM_DCACHEEXTRAPCT) * afs_cacheFiles / 100;
- afs_min_cache =
- (((10 * AFS_CHUNKSIZE(0)) + afs_fsfragsize) & ~afs_fsfragsize) >> 10;
-
- osi_GetuTime(&CTD_stats.CTD_afterSleep);
- afs_TruncateDaemonRunning = 1;
- while (1) {
- cb_lowat = ((CM_DCACHESPACEFREEPCT - CM_DCACHEEXTRAPCT)
- * afs_cacheBlocks) / 100;
- MObtainWriteLock(&afs_xdcache, 266);
- if (afs_CacheTooFull) {
- int space_needed, slots_needed;
- /* if we get woken up, we should try to clean something out */
- for (counter = 0; counter < 10; counter++) {
- space_needed =
- afs_blocksUsed - afs_blocksDiscarded - cb_lowat;
- slots_needed =
- dc_hiwat - afs_freeDCCount - afs_discardDCCount;
- afs_GetDownD(slots_needed, &space_needed);
- if ((space_needed <= 0) && (slots_needed <= 0)) {
- break;
- }
- if (afs_termState == AFSOP_STOP_TRUNCDAEMON)
- break;
- }
- if (!afs_CacheIsTooFull())
- afs_CacheTooFull = 0;
- }
- MReleaseWriteLock(&afs_xdcache);
-
- /*
- * This is a defensive check to try to avoid starving threads
- * that may need the global lock so thay can help free some
- * cache space. If this thread won't be sleeping or truncating
- * any cache files then give up the global lock so other
- * threads get a chance to run.
- */
- if ((afs_termState != AFSOP_STOP_TRUNCDAEMON) && afs_CacheTooFull
- && (!afs_blocksDiscarded || afs_WaitForCacheDrain)) {
- afs_osi_Wait(100, 0, 0); /* 100 milliseconds */
- }
-
- /*
- * This is where we free the discarded cache elements.
- */
- while (afs_blocksDiscarded && !afs_WaitForCacheDrain
- && (afs_termState != AFSOP_STOP_TRUNCDAEMON)) {
- afs_FreeDiscardedDCache();
- }
-
- /* See if we need to continue to run. Someone may have
- * signalled us while we were executing.
- */
- if (!afs_WaitForCacheDrain && !afs_CacheTooFull
- && (afs_termState != AFSOP_STOP_TRUNCDAEMON)) {
- /* Collect statistics on truncate daemon. */
- CTD_stats.CTD_nSleeps++;
- osi_GetuTime(&CTD_stats.CTD_beforeSleep);
- afs_stats_GetDiff(CTD_tmpTime, CTD_stats.CTD_afterSleep,
- CTD_stats.CTD_beforeSleep);
- afs_stats_AddTo(CTD_stats.CTD_runTime, CTD_tmpTime);
-
- afs_TruncateDaemonRunning = 0;
- afs_osi_Sleep((int *)afs_CacheTruncateDaemon);
- afs_TruncateDaemonRunning = 1;
-
- osi_GetuTime(&CTD_stats.CTD_afterSleep);
- afs_stats_GetDiff(CTD_tmpTime, CTD_stats.CTD_beforeSleep,
- CTD_stats.CTD_afterSleep);
- afs_stats_AddTo(CTD_stats.CTD_sleepTime, CTD_tmpTime);
- }
- if (afs_termState == AFSOP_STOP_TRUNCDAEMON) {
-#ifdef AFS_AFSDB_ENV
- afs_termState = AFSOP_STOP_AFSDB;
-#else
- afs_termState = AFSOP_STOP_RXEVENT;
-#endif
- afs_osi_Wakeup(&afs_termState);
- break;
- }
- }
-}
-
-
-/*
- * afs_AdjustSize
- *
- * Description:
- * Make adjustment for the new size in the disk cache entry
- *
- * Major Assumptions Here:
- * Assumes that frag size is an integral power of two, less one,
- * and that this is a two's complement machine. I don't
- * know of any filesystems which violate this assumption...
- *
- * Parameters:
- * adc : Ptr to dcache entry.
- * anewsize : New size desired.
- */
-
-void
-afs_AdjustSize(register struct dcache *adc, register afs_int32 newSize)
-{
- register afs_int32 oldSize;
-
- AFS_STATCNT(afs_AdjustSize);
-
- adc->dflags |= DFEntryMod;
- oldSize = ((adc->f.chunkBytes + afs_fsfragsize) ^ afs_fsfragsize) >> 10; /* round up */
- adc->f.chunkBytes = newSize;
- if (!newSize)
- adc->validPos = 0;
- newSize = ((newSize + afs_fsfragsize) ^ afs_fsfragsize) >> 10; /* round up */
- if (newSize > oldSize) {
- /* We're growing the file, wakeup the daemon */
- afs_MaybeWakeupTruncateDaemon();
- }
- afs_blocksUsed += (newSize - oldSize);
- afs_stats_cmperf.cacheBlocksInUse = afs_blocksUsed; /* XXX */
-}
-
-
-/*
- * afs_GetDownD
- *
- * Description:
- * This routine is responsible for moving at least one entry (but up
- * to some number of them) from the LRU queue to the free queue.
- *
- * Parameters:
- * anumber : Number of entries that should ideally be moved.
- * aneedSpace : How much space we need (1K blocks);
- *
- * Environment:
- * The anumber parameter is just a hint; at least one entry MUST be
- * moved, or we'll panic. We must be called with afs_xdcache
- * write-locked. We should try to satisfy both anumber and aneedspace,
- * whichever is more demanding - need to do several things:
- * 1. only grab up to anumber victims if aneedSpace <= 0, not
- * the whole set of MAXATONCE.
- * 2. dynamically choose MAXATONCE to reflect severity of
- * demand: something like (*aneedSpace >> (logChunk - 9))
- * N.B. if we're called with aneedSpace <= 0 and anumber > 0, that
- * indicates that the cache is not properly configured/tuned or
- * something. We should be able to automatically correct that problem.
- */
-
-#define MAXATONCE 16 /* max we can obtain at once */
-static void
-afs_GetDownD(int anumber, int *aneedSpace)
-{
-
- struct dcache *tdc;
- struct VenusFid *afid;
- afs_int32 i, j;
- afs_hyper_t vtime;
- int skip, phase;
- register struct vcache *tvc;
- afs_uint32 victims[MAXATONCE];
- struct dcache *victimDCs[MAXATONCE];
- afs_hyper_t victimTimes[MAXATONCE]; /* youngest (largest LRU time) first */
- afs_uint32 victimPtr; /* next free item in victim arrays */
- afs_hyper_t maxVictimTime; /* youngest (largest LRU time) victim */
- afs_uint32 maxVictimPtr; /* where it is */
- int discard;
-
- AFS_STATCNT(afs_GetDownD);
- if (CheckLock(&afs_xdcache) != -1)
- osi_Panic("getdownd nolock");
- /* decrement anumber first for all dudes in free list */
- /* SHOULD always decrement anumber first, even if aneedSpace >0,
- * because we should try to free space even if anumber <=0 */
- if (!aneedSpace || *aneedSpace <= 0) {
- anumber -= afs_freeDCCount;
- if (anumber <= 0)
- return; /* enough already free */
- }
- /* bounds check parameter */
- if (anumber > MAXATONCE)
- anumber = MAXATONCE; /* all we can do */
-
- /*
- * The phase variable manages reclaims. Set to 0, the first pass,
- * we don't reclaim active entries. Set to 1, we reclaim even active
- * ones.
- */
- phase = 0;
- for (i = 0; i < afs_cacheFiles; i++)
- /* turn off all flags */
- afs_indexFlags[i] &= ~IFFlag;
-
- while (anumber > 0 || (aneedSpace && *aneedSpace > 0)) {
- /* find oldest entries for reclamation */
- maxVictimPtr = victimPtr = 0;
- hzero(maxVictimTime);
- /* select victims from access time array */
- for (i = 0; i < afs_cacheFiles; i++) {
- if (afs_indexFlags[i] & (IFDataMod | IFFree | IFDiscarded)) {
- /* skip if dirty or already free */
- continue;
- }
- tdc = afs_indexTable[i];
- if (tdc && (tdc->refCount != 0)) {
- /* Referenced; can't use it! */
- continue;
- }
- hset(vtime, afs_indexTimes[i]);
-
- /* if we've already looked at this one, skip it */
- if (afs_indexFlags[i] & IFFlag)
- continue;
-
- if (victimPtr < MAXATONCE) {
- /* if there's at least one free victim slot left */
- victims[victimPtr] = i;
- hset(victimTimes[victimPtr], vtime);
- if (hcmp(vtime, maxVictimTime) > 0) {
- hset(maxVictimTime, vtime);
- maxVictimPtr = victimPtr;
- }
- victimPtr++;
- } else if (hcmp(vtime, maxVictimTime) < 0) {
- /*
- * We're older than youngest victim, so we replace at
- * least one victim
- */
- /* find youngest (largest LRU) victim */
- j = maxVictimPtr;
- if (j == victimPtr)
- osi_Panic("getdownd local");
- victims[j] = i;
- hset(victimTimes[j], vtime);
- /* recompute maxVictimTime */
- hset(maxVictimTime, vtime);
- for (j = 0; j < victimPtr; j++)
- if (hcmp(maxVictimTime, victimTimes[j]) < 0) {
- hset(maxVictimTime, victimTimes[j]);
- maxVictimPtr = j;
- }
- }
- } /* big for loop */
-
- /* now really reclaim the victims */
- j = 0; /* flag to track if we actually got any of the victims */
- /* first, hold all the victims, since we're going to release the lock
- * during the truncate operation.
- */
- for (i = 0; i < victimPtr; i++) {
- tdc = afs_GetDSlot(victims[i], 0);
- /* We got tdc->tlock(R) here */
- if (tdc->refCount == 1)
- victimDCs[i] = tdc;
- else
- victimDCs[i] = 0;
- ReleaseReadLock(&tdc->tlock);
- if (!victimDCs[i])
- afs_PutDCache(tdc);
- }
- for (i = 0; i < victimPtr; i++) {
- /* q is first elt in dcache entry */
- tdc = victimDCs[i];
- /* now, since we're dropping the afs_xdcache lock below, we
- * have to verify, before proceeding, that there are no other
- * references to this dcache entry, even now. Note that we
- * compare with 1, since we bumped it above when we called
- * afs_GetDSlot to preserve the entry's identity.
- */
- if (tdc && tdc->refCount == 1) {
- unsigned char chunkFlags;
- afs_size_t tchunkoffset = 0;
- afid = &tdc->f.fid;
- /* xdcache is lower than the xvcache lock */
- MReleaseWriteLock(&afs_xdcache);
- MObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(afid, 0, 0 /* no stats, no vlru */ );
- MReleaseReadLock(&afs_xvcache);
- MObtainWriteLock(&afs_xdcache, 527);
- skip = 0;
- if (tdc->refCount > 1)
- skip = 1;
- if (tvc) {
- tchunkoffset = AFS_CHUNKTOBASE(tdc->f.chunk);
- chunkFlags = afs_indexFlags[tdc->index];
- if (phase == 0 && osi_Active(tvc))
- skip = 1;
- if (phase > 0 && osi_Active(tvc)
- && (tvc->states & CDCLock)
- && (chunkFlags & IFAnyPages))
- skip = 1;
- if (chunkFlags & IFDataMod)
- skip = 1;
- afs_Trace4(afs_iclSetp, CM_TRACE_GETDOWND,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, skip,
- ICL_TYPE_INT32, tdc->index, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(tchunkoffset));
-
-#if defined(AFS_SUN5_ENV)
- /*
- * Now we try to invalidate pages. We do this only for
- * Solaris. For other platforms, it's OK to recycle a
- * dcache entry out from under a page, because the strategy
- * function can call afs_GetDCache().
- */
- if (!skip && (chunkFlags & IFAnyPages)) {
- int code;
-
- MReleaseWriteLock(&afs_xdcache);
- MObtainWriteLock(&tvc->vlock, 543);
- if (tvc->multiPage) {
- skip = 1;
- goto endmultipage;
- }
- /* block locking pages */
- tvc->vstates |= VPageCleaning;
- /* block getting new pages */
- tvc->activeV++;
- MReleaseWriteLock(&tvc->vlock);
- /* One last recheck */
- MObtainWriteLock(&afs_xdcache, 333);
- chunkFlags = afs_indexFlags[tdc->index];
- if (tdc->refCount > 1 || (chunkFlags & IFDataMod)
- || (osi_Active(tvc) && (tvc->states & CDCLock)
- && (chunkFlags & IFAnyPages))) {
- skip = 1;
- MReleaseWriteLock(&afs_xdcache);
- goto endputpage;
- }
- MReleaseWriteLock(&afs_xdcache);
-
- code = osi_VM_GetDownD(tvc, tdc);
-
- MObtainWriteLock(&afs_xdcache, 269);
- /* we actually removed all pages, clean and dirty */
- if (code == 0) {
- afs_indexFlags[tdc->index] &=
- ~(IFDirtyPages | IFAnyPages);
- } else
- skip = 1;
- MReleaseWriteLock(&afs_xdcache);
- endputpage:
- MObtainWriteLock(&tvc->vlock, 544);
- if (--tvc->activeV == 0
- && (tvc->vstates & VRevokeWait)) {
- tvc->vstates &= ~VRevokeWait;
- afs_osi_Wakeup((char *)&tvc->vstates);
-
- }
- if (tvc->vstates & VPageCleaning) {
- tvc->vstates &= ~VPageCleaning;
- afs_osi_Wakeup((char *)&tvc->vstates);
- }
- endmultipage:
- MReleaseWriteLock(&tvc->vlock);
- } else
-#endif /* AFS_SUN5_ENV */
- {
- MReleaseWriteLock(&afs_xdcache);
- }
-
- AFS_FAST_RELE(tvc);
- MObtainWriteLock(&afs_xdcache, 528);
- if (afs_indexFlags[tdc->index] &
- (IFDataMod | IFDirtyPages | IFAnyPages))
- skip = 1;
- if (tdc->refCount > 1)
- skip = 1;
- }
-#if defined(AFS_SUN5_ENV)
- else {
- /* no vnode, so IFDirtyPages is spurious (we don't
- * sweep dcaches on vnode recycling, so we can have
- * DIRTYPAGES set even when all pages are gone). Just
- * clear the flag.
- * Hold vcache lock to prevent vnode from being
- * created while we're clearing IFDirtyPages.
- */
- afs_indexFlags[tdc->index] &=
- ~(IFDirtyPages | IFAnyPages);
- }
-#endif
- if (skip) {
- /* skip this guy and mark him as recently used */
- afs_indexFlags[tdc->index] |= IFFlag;
- afs_Trace4(afs_iclSetp, CM_TRACE_GETDOWND,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, 2,
- ICL_TYPE_INT32, tdc->index, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(tchunkoffset));
- } else {
- /* flush this dude from the data cache and reclaim;
- * first, make sure no one will care that we damage
- * it, by removing it from all hash tables. Then,
- * melt it down for parts. Note that any concurrent
- * (new possibility!) calls to GetDownD won't touch
- * this guy because his reference count is > 0. */
- afs_Trace4(afs_iclSetp, CM_TRACE_GETDOWND,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, 3,
- ICL_TYPE_INT32, tdc->index, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(tchunkoffset));
-#ifndef AFS_DEC_ENV
- AFS_STATCNT(afs_gget);
-#endif
- afs_HashOutDCache(tdc);
- if (tdc->f.chunkBytes != 0) {
- discard = 1;
- if (aneedSpace)
- *aneedSpace -=
- (tdc->f.chunkBytes + afs_fsfragsize) >> 10;
- } else {
- discard = 0;
- }
- if (discard) {
- afs_DiscardDCache(tdc);
- } else {
- afs_FreeDCache(tdc);
- }
- anumber--;
- j = 1; /* we reclaimed at least one victim */
- }
- }
- afs_PutDCache(tdc);
- }
-
- if (phase == 0) {
- /* Phase is 0 and no one was found, so try phase 1 (ignore
- * osi_Active flag) */
- if (j == 0) {
- phase = 1;
- for (i = 0; i < afs_cacheFiles; i++)
- /* turn off all flags */
- afs_indexFlags[i] &= ~IFFlag;
- }
- } else {
- /* found no one in phase 1, we're hosed */
- if (victimPtr == 0)
- break;
- }
- } /* big while loop */
- return;
-
-} /*afs_GetDownD */
-
-
-/*
- * Description: remove adc from any hash tables that would allow it to be located
- * again by afs_FindDCache or afs_GetDCache.
- *
- * Parameters: adc -- pointer to dcache entry to remove from hash tables.
- *
- * Locks: Must have the afs_xdcache lock write-locked to call this function.
- */
-int
-afs_HashOutDCache(struct dcache *adc)
-{
- int i, us;
-
-#ifndef AFS_DEC_ENV
- AFS_STATCNT(afs_glink);
-#endif
- /* we know this guy's in the LRUQ. We'll move dude into DCQ below */
- DZap(&adc->f.inode);
- /* if this guy is in the hash table, pull him out */
- if (adc->f.fid.Fid.Volume != 0) {
- /* remove entry from first hash chains */
- i = DCHash(&adc->f.fid, adc->f.chunk);
- us = afs_dchashTbl[i];
- if (us == adc->index) {
- /* first dude in the list */
- afs_dchashTbl[i] = afs_dcnextTbl[adc->index];
- } else {
- /* somewhere on the chain */
- while (us != NULLIDX) {
- if (afs_dcnextTbl[us] == adc->index) {
- /* found item pointing at the one to delete */
- afs_dcnextTbl[us] = afs_dcnextTbl[adc->index];
- break;
- }
- us = afs_dcnextTbl[us];
- }
- if (us == NULLIDX)
- osi_Panic("dcache hc");
- }
- /* remove entry from *other* hash chain */
- i = DVHash(&adc->f.fid);
- us = afs_dvhashTbl[i];
- if (us == adc->index) {
- /* first dude in the list */
- afs_dvhashTbl[i] = afs_dvnextTbl[adc->index];
- } else {
- /* somewhere on the chain */
- while (us != NULLIDX) {
- if (afs_dvnextTbl[us] == adc->index) {
- /* found item pointing at the one to delete */
- afs_dvnextTbl[us] = afs_dvnextTbl[adc->index];
- break;
- }
- us = afs_dvnextTbl[us];
- }
- if (us == NULLIDX)
- osi_Panic("dcache hv");
- }
- }
-
- /* prevent entry from being found on a reboot (it is already out of
- * the hash table, but after a crash, we just look at fid fields of
- * stable (old) entries).
- */
- adc->f.fid.Fid.Volume = 0; /* invalid */
-
- /* mark entry as modified */
- adc->dflags |= DFEntryMod;
-
- /* all done */
- return 0;
-} /*afs_HashOutDCache */
-
-
-/*
- * afs_FlushDCache
- *
- * Description:
- * Flush the given dcache entry, pulling it from hash chains
- * and truncating the associated cache file.
- *
- * Arguments:
- * adc: Ptr to dcache entry to flush.
- *
- * Environment:
- * This routine must be called with the afs_xdcache lock held
- * (in write mode)
- */
-
-void
-afs_FlushDCache(register struct dcache *adc)
-{
- AFS_STATCNT(afs_FlushDCache);
- /*
- * Bump the number of cache files flushed.
- */
- afs_stats_cmperf.cacheFlushes++;
-
- /* remove from all hash tables */
- afs_HashOutDCache(adc);
-
- /* Free its space; special case null operation, since truncate operation
- * in UFS is slow even in this case, and this allows us to pre-truncate
- * these files at more convenient times with fewer locks set
- * (see afs_GetDownD).
- */
- if (adc->f.chunkBytes != 0) {
- afs_DiscardDCache(adc);
- afs_MaybeWakeupTruncateDaemon();
- } else {
- afs_FreeDCache(adc);
- }
-
- if (afs_WaitForCacheDrain) {
- if (afs_blocksUsed <=
- (CM_CACHESIZEDRAINEDPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 0;
- afs_osi_Wakeup(&afs_WaitForCacheDrain);
- }
- }
-} /*afs_FlushDCache */
-
-
-/*
- * afs_FreeDCache
- *
- * Description: put a dcache entry on the free dcache entry list.
- *
- * Parameters: adc -- dcache entry to free
- *
- * Environment: called with afs_xdcache lock write-locked.
- */
-static void
-afs_FreeDCache(register struct dcache *adc)
-{
- /* Thread on free list, update free list count and mark entry as
- * freed in its indexFlags element. Also, ensure DCache entry gets
- * written out (set DFEntryMod).
- */
-
- afs_dvnextTbl[adc->index] = afs_freeDCList;
- afs_freeDCList = adc->index;
- afs_freeDCCount++;
- afs_indexFlags[adc->index] |= IFFree;
- adc->dflags |= DFEntryMod;
-
- if (afs_WaitForCacheDrain) {
- if ((afs_blocksUsed - afs_blocksDiscarded) <=
- (CM_CACHESIZEDRAINEDPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 0;
- afs_osi_Wakeup(&afs_WaitForCacheDrain);
- }
- }
-}
-
-/*
- * afs_DiscardDCache
- *
- * Description:
- * Discard the cache element by moving it to the discardDCList.
- * This puts the cache element into a quasi-freed state, where
- * the space may be reused, but the file has not been truncated.
- *
- * Major Assumptions Here:
- * Assumes that frag size is an integral power of two, less one,
- * and that this is a two's complement machine. I don't
- * know of any filesystems which violate this assumption...
- *
- * Parameters:
- * adc : Ptr to dcache entry.
- *
- * Environment:
- * Must be called with afs_xdcache write-locked.
- */
-
-static void
-afs_DiscardDCache(register struct dcache *adc)
-{
- register afs_int32 size;
-
- AFS_STATCNT(afs_DiscardDCache);
-
- osi_Assert(adc->refCount == 1);
-
- size = ((adc->f.chunkBytes + afs_fsfragsize) ^ afs_fsfragsize) >> 10; /* round up */
- afs_blocksDiscarded += size;
- afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
-
- afs_dvnextTbl[adc->index] = afs_discardDCList;
- afs_discardDCList = adc->index;
- afs_discardDCCount++;
-
- adc->f.fid.Fid.Volume = 0;
- adc->dflags |= DFEntryMod;
- afs_indexFlags[adc->index] |= IFDiscarded;
-
- if (afs_WaitForCacheDrain) {
- if ((afs_blocksUsed - afs_blocksDiscarded) <=
- (CM_CACHESIZEDRAINEDPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 0;
- afs_osi_Wakeup(&afs_WaitForCacheDrain);
- }
- }
-
-} /*afs_DiscardDCache */
-
-/*
- * afs_FreeDiscardedDCache
- *
- * Description:
- * Free the next element on the list of discarded cache elements.
- */
-static void
-afs_FreeDiscardedDCache(void)
-{
- register struct dcache *tdc;
- register struct osi_file *tfile;
- register afs_int32 size;
-
- AFS_STATCNT(afs_FreeDiscardedDCache);
-
- MObtainWriteLock(&afs_xdcache, 510);
- if (!afs_blocksDiscarded) {
- MReleaseWriteLock(&afs_xdcache);
- return;
- }
-
- /*
- * Get an entry from the list of discarded cache elements
- */
- tdc = afs_GetDSlot(afs_discardDCList, 0);
- osi_Assert(tdc->refCount == 1);
- ReleaseReadLock(&tdc->tlock);
-
- afs_discardDCList = afs_dvnextTbl[tdc->index];
- afs_dvnextTbl[tdc->index] = NULLIDX;
- afs_discardDCCount--;
- size = ((tdc->f.chunkBytes + afs_fsfragsize) ^ afs_fsfragsize) >> 10; /* round up */
- afs_blocksDiscarded -= size;
- afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
- /* We can lock because we just took it off the free list */
- ObtainWriteLock(&tdc->lock, 626);
- MReleaseWriteLock(&afs_xdcache);
-
- /*
- * Truncate the element to reclaim its space
- */
- tfile = afs_CFileOpen(tdc->f.inode);
- afs_CFileTruncate(tfile, 0);
- afs_CFileClose(tfile);
- afs_AdjustSize(tdc, 0);
-
- /*
- * Free the element we just truncated
- */
- MObtainWriteLock(&afs_xdcache, 511);
- afs_indexFlags[tdc->index] &= ~IFDiscarded;
- afs_FreeDCache(tdc);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- MReleaseWriteLock(&afs_xdcache);
-}
-
-/*
- * afs_MaybeFreeDiscardedDCache
- *
- * Description:
- * Free as many entries from the list of discarded cache elements
- * as we need to get the free space down below CM_WAITFORDRAINPCT (98%).
- *
- * Parameters:
- * None
- */
-int
-afs_MaybeFreeDiscardedDCache(void)
-{
-
- AFS_STATCNT(afs_MaybeFreeDiscardedDCache);
-
- while (afs_blocksDiscarded
- && (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100)) {
- afs_FreeDiscardedDCache();
- }
- return 0;
-}
-
-/*
- * afs_GetDownDSlot
- *
- * Description:
- * Try to free up a certain number of disk slots.
- *
- * Parameters:
- * anumber : Targeted number of disk slots to free up.
- *
- * Environment:
- * Must be called with afs_xdcache write-locked.
- */
-static void
-afs_GetDownDSlot(int anumber)
-{
- struct afs_q *tq, *nq;
- struct dcache *tdc;
- int ix;
- unsigned int cnt;
-
- AFS_STATCNT(afs_GetDownDSlot);
- if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
- osi_Panic("diskless getdowndslot");
-
- if (CheckLock(&afs_xdcache) != -1)
- osi_Panic("getdowndslot nolock");
-
- /* decrement anumber first for all dudes in free list */
- for (tdc = afs_freeDSList; tdc; tdc = (struct dcache *)tdc->lruq.next)
- anumber--;
- if (anumber <= 0)
- return; /* enough already free */
-
- for (cnt = 0, tq = afs_DLRU.prev; tq != &afs_DLRU && anumber > 0;
- tq = nq, cnt++) {
- tdc = (struct dcache *)tq; /* q is first elt in dcache entry */
- nq = QPrev(tq); /* in case we remove it */
- if (tdc->refCount == 0) {
- if ((ix = tdc->index) == NULLIDX)
- osi_Panic("getdowndslot");
- /* pull the entry out of the lruq and put it on the free list */
- QRemove(&tdc->lruq);
-
- /* write-through if modified */
- if (tdc->dflags & DFEntryMod) {
-#if defined(AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
- /*
- * ask proxy to do this for us - we don't have the stack space
- */
- while (tdc->dflags & DFEntryMod) {
- int s;
- AFS_GUNLOCK();
- s = SPLOCK(afs_sgibklock);
- if (afs_sgibklist == NULL) {
- /* if slot is free, grab it. */
- afs_sgibklist = tdc;
- SV_SIGNAL(&afs_sgibksync);
- }
- /* wait for daemon to (start, then) finish. */
- SP_WAIT(afs_sgibklock, s, &afs_sgibkwait, PINOD);
- AFS_GLOCK();
- }
-#else
- tdc->dflags &= ~DFEntryMod;
- afs_WriteDCache(tdc, 1);
-#endif
- }
-
- tdc->stamp = 0;
-#ifdef IHINT
- if (tdc->ihint) {
- struct osi_file *f = (struct osi_file *)tdc->ihint;
- tdc->ihint = 0;
- afs_UFSClose(f);
- nihints--;
- }
-#endif /* IHINT */
-
-
- /* finally put the entry in the free list */
- afs_indexTable[ix] = NULL;
- afs_indexFlags[ix] &= ~IFEverUsed;
- tdc->index = NULLIDX;
- tdc->lruq.next = (struct afs_q *)afs_freeDSList;
- afs_freeDSList = tdc;
- anumber--;
- }
- }
-} /*afs_GetDownDSlot */
-
-
-/*
- * afs_RefDCache
- *
- * Description:
- * Increment the reference count on a disk cache entry,
- * which already has a non-zero refcount. In order to
- * increment the refcount of a zero-reference entry, you
- * have to hold afs_xdcache.
- *
- * Parameters:
- * adc : Pointer to the dcache entry to increment.
- *
- * Environment:
- * Nothing interesting.
- */
-int
-afs_RefDCache(struct dcache *adc)
-{
- ObtainWriteLock(&adc->tlock, 627);
- if (adc->refCount < 0)
- osi_Panic("RefDCache: negative refcount");
- adc->refCount++;
- ReleaseWriteLock(&adc->tlock);
- return 0;
-}
-
-
-/*
- * afs_PutDCache
- *
- * Description:
- * Decrement the reference count on a disk cache entry.
- *
- * Parameters:
- * ad : Ptr to the dcache entry to decrement.
- *
- * Environment:
- * Nothing interesting.
- */
-int
-afs_PutDCache(register struct dcache *adc)
-{
- AFS_STATCNT(afs_PutDCache);
- ObtainWriteLock(&adc->tlock, 276);
- if (adc->refCount <= 0)
- osi_Panic("putdcache");
- --adc->refCount;
- ReleaseWriteLock(&adc->tlock);
- return 0;
-}
-
-
-/*
- * afs_TryToSmush
- *
- * Description:
- * Try to discard all data associated with this file from the
- * cache.
- *
- * Parameters:
- * avc : Pointer to the cache info for the file.
- *
- * Environment:
- * Both pvnLock and lock are write held.
- */
-void
-afs_TryToSmush(register struct vcache *avc, struct AFS_UCRED *acred, int sync)
-{
- register struct dcache *tdc;
- register int index;
- register int i;
- AFS_STATCNT(afs_TryToSmush);
- afs_Trace2(afs_iclSetp, CM_TRACE_TRYTOSMUSH, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
- sync = 1; /* XX Temp testing XX */
-
-#if defined(AFS_SUN5_ENV)
- ObtainWriteLock(&avc->vlock, 573);
- avc->activeV++; /* block new getpages */
- ReleaseWriteLock(&avc->vlock);
-#endif
-
- /* Flush VM pages */
- osi_VM_TryToSmush(avc, acred, sync);
-
- /*
- * Get the hash chain containing all dce's for this fid
- */
- i = DVHash(&avc->fid);
- MObtainWriteLock(&afs_xdcache, 277);
- for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
- i = afs_dvnextTbl[index]; /* next pointer this hash table */
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- int releaseTlock = 1;
- tdc = afs_GetDSlot(index, NULL);
- if (!FidCmp(&tdc->f.fid, &avc->fid)) {
- if (sync) {
- if ((afs_indexFlags[index] & IFDataMod) == 0
- && tdc->refCount == 1) {
- ReleaseReadLock(&tdc->tlock);
- releaseTlock = 0;
- afs_FlushDCache(tdc);
- }
- } else
- afs_indexTable[index] = 0;
- }
- if (releaseTlock)
- ReleaseReadLock(&tdc->tlock);
- afs_PutDCache(tdc);
- }
- }
-#if defined(AFS_SUN5_ENV)
- ObtainWriteLock(&avc->vlock, 545);
- if (--avc->activeV == 0 && (avc->vstates & VRevokeWait)) {
- avc->vstates &= ~VRevokeWait;
- afs_osi_Wakeup((char *)&avc->vstates);
- }
- ReleaseWriteLock(&avc->vlock);
-#endif
- MReleaseWriteLock(&afs_xdcache);
- /*
- * It's treated like a callback so that when we do lookups we'll invalidate the unique bit if any
- * trytoSmush occured during the lookup call
- */
- afs_allCBs++;
-}
-
-/*
- * afs_FindDCache
- *
- * Description:
- * Given the cached info for a file and a byte offset into the
- * file, make sure the dcache entry for that file and containing
- * the given byte is available, returning it to our caller.
- *
- * Parameters:
- * avc : Pointer to the (held) vcache entry to look in.
- * abyte : Which byte we want to get to.
- *
- * Returns:
- * Pointer to the dcache entry covering the file & desired byte,
- * or NULL if not found.
- *
- * Environment:
- * The vcache entry is held upon entry.
- */
-
-struct dcache *
-afs_FindDCache(register struct vcache *avc, afs_size_t abyte)
-{
- afs_int32 chunk;
- register afs_int32 i, index;
- register struct dcache *tdc;
-
- AFS_STATCNT(afs_FindDCache);
- chunk = AFS_CHUNK(abyte);
-
- /*
- * Hash on the [fid, chunk] and get the corresponding dcache index
- * after write-locking the dcache.
- */
- i = DCHash(&avc->fid, chunk);
- MObtainWriteLock(&afs_xdcache, 278);
- for (index = afs_dchashTbl[i]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, NULL);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid) && chunk == tdc->f.chunk) {
- break; /* leaving refCount high for caller */
- }
- afs_PutDCache(tdc);
- }
- index = afs_dcnextTbl[index];
- }
- MReleaseWriteLock(&afs_xdcache);
- if (index != NULLIDX) {
- hset(afs_indexTimes[tdc->index], afs_indexCounter);
- hadd32(afs_indexCounter, 1);
- return tdc;
- } else
- return NULL;
-
-} /*afs_FindDCache */
-
-
-/*
- * afs_UFSCacheStoreProc
- *
- * Description:
- * Called upon store.
- *
- * Parameters:
- * acall : Ptr to the Rx call structure involved.
- * afile : Ptr to the related file descriptor.
- * alen : Size of the file in bytes.
- * avc : Ptr to the vcache entry.
- * shouldWake : is it "safe" to return early from close() ?
- * abytesToXferP : Set to the number of bytes to xfer.
- * NOTE: This parameter is only used if AFS_NOSTATS
- * is not defined.
- * abytesXferredP : Set to the number of bytes actually xferred.
- * NOTE: This parameter is only used if AFS_NOSTATS
- * is not defined.
- *
- * Environment:
- * Nothing interesting.
- */
-static int
-afs_UFSCacheStoreProc(register struct rx_call *acall, struct osi_file *afile,
- register afs_int32 alen, struct vcache *avc,
- int *shouldWake, afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP)
-{
- afs_int32 code, got;
- register char *tbuffer;
- register int tlen;
-
- AFS_STATCNT(UFS_CacheStoreProc);
-
-#ifndef AFS_NOSTATS
- /*
- * In this case, alen is *always* the amount of data we'll be trying
- * to ship here.
- */
- (*abytesToXferP) = alen;
- (*abytesXferredP) = 0;
-#endif /* AFS_NOSTATS */
-
- afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
- ICL_TYPE_FID, &(avc->fid), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_INT32, alen);
- tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- while (alen > 0) {
- tlen = (alen > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : alen);
- got = afs_osi_Read(afile, -1, tbuffer, tlen);
- if ((got < 0)
-#if defined(KERNEL_HAVE_UERROR)
- || (got != tlen && getuerror())
-#endif
- ) {
- osi_FreeLargeSpace(tbuffer);
- return EIO;
- }
- afs_Trace2(afs_iclSetp, CM_TRACE_STOREPROC2, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(*tbuffer), ICL_TYPE_INT32, got);
- RX_AFS_GUNLOCK();
- code = rx_Write(acall, tbuffer, got); /* writing 0 bytes will
- * push a short packet. Is that really what we want, just because the
- * data didn't come back from the disk yet? Let's try it and see. */
- RX_AFS_GLOCK();
-#ifndef AFS_NOSTATS
- (*abytesXferredP) += code;
-#endif /* AFS_NOSTATS */
- if (code != got) {
- osi_FreeLargeSpace(tbuffer);
- return -33;
- }
- alen -= got;
- /*
- * If file has been locked on server, we can allow the store
- * to continue.
- */
- if (shouldWake && *shouldWake && (rx_GetRemoteStatus(acall) & 1)) {
- *shouldWake = 0; /* only do this once */
- afs_wakeup(avc);
- }
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
- ICL_TYPE_FID, &(avc->fid), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_INT32, alen);
- osi_FreeLargeSpace(tbuffer);
- return 0;
-
-} /* afs_UFSCacheStoreProc */
-
-
-/*
- * afs_UFSCacheFetchProc
- *
- * Description:
- * Routine called on fetch; also tells people waiting for data
- * that more has arrived.
- *
- * Parameters:
- * acall : Ptr to the Rx call structure.
- * afile : File descriptor for the cache file.
- * abase : Base offset to fetch.
- * adc : Ptr to the dcache entry for the file, write-locked.
- * avc : Ptr to the vcache entry for the file.
- * abytesToXferP : Set to the number of bytes to xfer.
- * NOTE: This parameter is only used if AFS_NOSTATS
- * is not defined.
- * abytesXferredP : Set to the number of bytes actually xferred.
- * NOTE: This parameter is only used if AFS_NOSTATS
- * is not defined.
- *
- * Environment:
- * Nothing interesting.
- */
-
-static int
-afs_UFSCacheFetchProc(register struct rx_call *acall, struct osi_file *afile,
- afs_size_t abase, struct dcache *adc,
- struct vcache *avc, afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP, afs_int32 lengthFound)
-{
- afs_int32 length;
- register afs_int32 code;
- register char *tbuffer;
- register int tlen;
- int moredata = 0;
-
- AFS_STATCNT(UFS_CacheFetchProc);
- osi_Assert(WriteLocked(&adc->lock));
- afile->offset = 0; /* Each time start from the beginning */
- length = lengthFound;
-#ifndef AFS_NOSTATS
- (*abytesToXferP) = 0;
- (*abytesXferredP) = 0;
-#endif /* AFS_NOSTATS */
- tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- adc->validPos = abase;
- do {
- if (moredata) {
- RX_AFS_GUNLOCK();
- code = rx_Read(acall, (char *)&length, sizeof(afs_int32));
- RX_AFS_GLOCK();
- length = ntohl(length);
- if (code != sizeof(afs_int32)) {
- osi_FreeLargeSpace(tbuffer);
- code = rx_Error(acall);
- return (code ? code : -1); /* try to return code, not -1 */
- }
- }
- /*
- * The fetch protocol is extended for the AFS/DFS translator
- * to allow multiple blocks of data, each with its own length,
- * to be returned. As long as the top bit is set, there are more
- * blocks expected.
- *
- * We do not do this for AFS file servers because they sometimes
- * return large negative numbers as the transfer size.
- */
- if (avc->states & CForeign) {
- moredata = length & 0x80000000;
- length &= ~0x80000000;
- } else {
- moredata = 0;
- }
-#ifndef AFS_NOSTATS
- (*abytesToXferP) += length;
-#endif /* AFS_NOSTATS */
- while (length > 0) {
- tlen = (length > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : length);
-#ifdef RX_KERNEL_TRACE
- afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
- "before rx_Read");
-#endif
- RX_AFS_GUNLOCK();
- code = rx_Read(acall, tbuffer, tlen);
- RX_AFS_GLOCK();
-#ifdef RX_KERNEL_TRACE
- afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
- "after rx_Read");
-#endif
-#ifndef AFS_NOSTATS
- (*abytesXferredP) += code;
-#endif /* AFS_NOSTATS */
- if (code != tlen) {
- osi_FreeLargeSpace(tbuffer);
- afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64READ,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
- ICL_TYPE_INT32, length);
- return -34;
- }
- code = afs_osi_Write(afile, -1, tbuffer, tlen);
- if (code != tlen) {
- osi_FreeLargeSpace(tbuffer);
- return EIO;
- }
- abase += tlen;
- length -= tlen;
- adc->validPos = abase;
- if (afs_osi_Wakeup(&adc->validPos) == 0)
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, adc, ICL_TYPE_INT32,
- adc->dflags);
- }
- } while (moredata);
- osi_FreeLargeSpace(tbuffer);
- return 0;
-
-} /* afs_UFSCacheFetchProc */
-
-/*
- * afs_GetDCache
- *
- * Description:
- * This function is called to obtain a reference to data stored in
- * the disk cache, locating a chunk of data containing the desired
- * byte and returning a reference to the disk cache entry, with its
- * reference count incremented.
- *
- * Parameters:
- * IN:
- * avc : Ptr to a vcache entry (unlocked)
- * abyte : Byte position in the file desired
- * areq : Request structure identifying the requesting user.
- * aflags : Settings as follows:
- * 1 : Set locks
- * 2 : Return after creating entry.
- * 4 : called from afs_vnop_write.c
- * *alen contains length of data to be written.
- * OUT:
- * aoffset : Set to the offset within the chunk where the resident
- * byte is located.
- * alen : Set to the number of bytes of data after the desired
- * byte (including the byte itself) which can be read
- * from this chunk.
- *
- * Environment:
- * The vcache entry pointed to by avc is unlocked upon entry.
- */
-
-struct tlocal1 {
- struct AFSVolSync tsync;
- struct AFSFetchStatus OutStatus;
- struct AFSCallBack CallBack;
-};
-
-/*
- * Update the vnode-to-dcache hint if we can get the vnode lock
- * right away. Assumes dcache entry is at least read-locked.
- */
-void
-updateV2DC(int lockVc, struct vcache *v, struct dcache *d, int src)
-{
- if (!lockVc || 0 == NBObtainWriteLock(&v->lock, src)) {
- if (hsame(v->m.DataVersion, d->f.versionNo) && v->callback) {
- v->quick.dc = d;
- v->quick.stamp = d->stamp = MakeStamp();
- v->quick.minLoc = AFS_CHUNKTOBASE(d->f.chunk);
- /* Don't think I need these next two lines forever */
- v->quick.len = d->f.chunkBytes;
- v->h1.dchint = d;
- }
- if (lockVc)
- ReleaseWriteLock(&v->lock);
- }
-}
-
-/* avc - Write-locked unless aflags & 1 */
-struct dcache *
-afs_GetDCache(register struct vcache *avc, afs_size_t abyte,
- register struct vrequest *areq, afs_size_t * aoffset,
- afs_size_t * alen, int aflags)
-{
- register afs_int32 i, code, code1 = 0, shortcut;
-#if defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
- register afs_int32 adjustsize = 0;
-#endif
- int setLocks;
- afs_int32 index;
- afs_int32 us;
- afs_int32 chunk;
- afs_size_t maxGoodLength; /* amount of good data at server */
- struct rx_call *tcall;
- afs_size_t Position = 0;
-#ifdef AFS_64BIT_CLIENT
- afs_size_t tsize;
- afs_size_t lengthFound; /* as returned from server */
-#endif /* AFS_64BIT_CLIENT */
- afs_int32 size, tlen; /* size of segment to transfer */
- struct tlocal1 *tsmall = 0;
- register struct dcache *tdc;
- register struct osi_file *file;
- register struct conn *tc;
- int downDCount = 0;
- struct server *newCallback;
- char setNewCallback;
- char setVcacheStatus;
- char doVcacheUpdate;
- char slowPass = 0;
- int doAdjustSize = 0;
- int doReallyAdjustSize = 0;
- int overWriteWholeChunk = 0;
-
- XSTATS_DECLS
-#ifndef AFS_NOSTATS
- struct afs_stats_xferData *xferP; /* Ptr to this op's xfer struct */
- osi_timeval_t xferStartTime, /*FS xfer start time */
- xferStopTime; /*FS xfer stop time */
- afs_size_t bytesToXfer; /* # bytes to xfer */
- afs_size_t bytesXferred; /* # bytes actually xferred */
- struct afs_stats_AccessInfo *accP; /*Ptr to access record in stats */
- int fromReplica; /*Are we reading from a replica? */
- int numFetchLoops; /*# times around the fetch/analyze loop */
-#endif /* AFS_NOSTATS */
-
- AFS_STATCNT(afs_GetDCache);
-
- if (dcacheDisabled)
- return NULL;
-
- setLocks = aflags & 1;
-
- /*
- * Determine the chunk number and offset within the chunk corresponding
- * to the desired byte.
- */
- if (avc->fid.Fid.Vnode & 1) { /* if (vType(avc) == VDIR) */
- chunk = 0;
- } else {
- chunk = AFS_CHUNK(abyte);
- }
-
- /* come back to here if we waited for the cache to drain. */
- RetryGetDCache:
-
- setNewCallback = setVcacheStatus = 0;
-
- if (setLocks) {
- if (slowPass)
- ObtainWriteLock(&avc->lock, 616);
- else
- ObtainReadLock(&avc->lock);
- }
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- */
-
- shortcut = 0;
-
- /* check hints first! (might could use bcmp or some such...) */
- if ((tdc = avc->h1.dchint)) {
- int dcLocked;
-
- /*
- * The locking order between afs_xdcache and dcache lock matters.
- * The hint dcache entry could be anywhere, even on the free list.
- * Locking afs_xdcache ensures that noone is trying to pull dcache
- * entries from the free list, and thereby assuming them to be not
- * referenced and not locked.
- */
- MObtainReadLock(&afs_xdcache);
- dcLocked = (0 == NBObtainSharedLock(&tdc->lock, 601));
-
- if (dcLocked && (tdc->index != NULLIDX)
- && !FidCmp(&tdc->f.fid, &avc->fid) && chunk == tdc->f.chunk
- && !(afs_indexFlags[tdc->index] & (IFFree | IFDiscarded))) {
- /* got the right one. It might not be the right version, and it
- * might be fetching, but it's the right dcache entry.
- */
- /* All this code should be integrated better with what follows:
- * I can save a good bit more time under a write lock if I do..
- */
- ObtainWriteLock(&tdc->tlock, 603);
- tdc->refCount++;
- ReleaseWriteLock(&tdc->tlock);
-
- MReleaseReadLock(&afs_xdcache);
- shortcut = 1;
-
- if (hsame(tdc->f.versionNo, avc->m.DataVersion)
- && !(tdc->dflags & DFFetching)) {
-
- afs_stats_cmperf.dcacheHits++;
- MObtainWriteLock(&afs_xdcache, 559);
- QRemove(&tdc->lruq);
- QAdd(&afs_DLRU, &tdc->lruq);
- MReleaseWriteLock(&afs_xdcache);
-
- /* Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S)
- */
- goto done;
- }
- } else {
- if (dcLocked)
- ReleaseSharedLock(&tdc->lock);
- MReleaseReadLock(&afs_xdcache);
- }
-
- if (!shortcut)
- tdc = 0;
- }
-
- /* Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S) if tdc
- */
-
- if (!tdc) { /* If the hint wasn't the right dcache entry */
- /*
- * Hash on the [fid, chunk] and get the corresponding dcache index
- * after write-locking the dcache.
- */
- RetryLookup:
-
- /* Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- */
-
- i = DCHash(&avc->fid, chunk);
- /* check to make sure our space is fine */
- afs_MaybeWakeupTruncateDaemon();
-
- MObtainWriteLock(&afs_xdcache, 280);
- us = NULLIDX;
- for (index = afs_dchashTbl[i]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, NULL);
- ReleaseReadLock(&tdc->tlock);
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * afs_xdcache(W)
- */
- if (!FidCmp(&tdc->f.fid, &avc->fid) && chunk == tdc->f.chunk) {
- /* Move it up in the beginning of the list */
- if (afs_dchashTbl[i] != index) {
- afs_dcnextTbl[us] = afs_dcnextTbl[index];
- afs_dcnextTbl[index] = afs_dchashTbl[i];
- afs_dchashTbl[i] = index;
- }
- MReleaseWriteLock(&afs_xdcache);
- ObtainSharedLock(&tdc->lock, 606);
- break; /* leaving refCount high for caller */
- }
- afs_PutDCache(tdc);
- tdc = 0;
- }
- us = index;
- index = afs_dcnextTbl[index];
- }
-
- /*
- * If we didn't find the entry, we'll create one.
- */
- if (index == NULLIDX) {
- /*
- * Locks held:
- * avc->lock(R) if setLocks
- * avc->lock(W) if !setLocks
- * afs_xdcache(W)
- */
- afs_Trace2(afs_iclSetp, CM_TRACE_GETDCACHE1, ICL_TYPE_POINTER,
- avc, ICL_TYPE_INT32, chunk);
-
- /* Make sure there is a free dcache entry for us to use */
- if (afs_discardDCList == NULLIDX && afs_freeDCList == NULLIDX) {
- while (1) {
- if (!setLocks)
- avc->states |= CDCLock;
- afs_GetDownD(5, (int *)0); /* just need slots */
- if (!setLocks)
- avc->states &= ~CDCLock;
- if (afs_discardDCList != NULLIDX
- || afs_freeDCList != NULLIDX)
- break;
- /* If we can't get space for 5 mins we give up and panic */
- if (++downDCount > 300)
- osi_Panic("getdcache");
- MReleaseWriteLock(&afs_xdcache);
- /*
- * Locks held:
- * avc->lock(R) if setLocks
- * avc->lock(W) if !setLocks
- */
- afs_osi_Wait(1000, 0, 0);
- goto RetryLookup;
- }
- }
-
- if (afs_discardDCList == NULLIDX
- || ((aflags & 2) && afs_freeDCList != NULLIDX)) {
-
- afs_indexFlags[afs_freeDCList] &= ~IFFree;
- tdc = afs_GetDSlot(afs_freeDCList, 0);
- osi_Assert(tdc->refCount == 1);
- ReleaseReadLock(&tdc->tlock);
- ObtainWriteLock(&tdc->lock, 604);
- afs_freeDCList = afs_dvnextTbl[tdc->index];
- afs_freeDCCount--;
- } else {
- afs_indexFlags[afs_discardDCList] &= ~IFDiscarded;
- tdc = afs_GetDSlot(afs_discardDCList, 0);
- osi_Assert(tdc->refCount == 1);
- ReleaseReadLock(&tdc->tlock);
- ObtainWriteLock(&tdc->lock, 605);
- afs_discardDCList = afs_dvnextTbl[tdc->index];
- afs_discardDCCount--;
- size =
- ((tdc->f.chunkBytes +
- afs_fsfragsize) ^ afs_fsfragsize) >> 10;
- afs_blocksDiscarded -= size;
- afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
- if (aflags & 2) {
- /* Truncate the chunk so zeroes get filled properly */
- file = afs_CFileOpen(tdc->f.inode);
- afs_CFileTruncate(file, 0);
- afs_CFileClose(file);
- afs_AdjustSize(tdc, 0);
- }
- }
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks
- * avc->lock(W) if !setLocks
- * tdc->lock(W)
- * afs_xdcache(W)
- */
-
- /*
- * Fill in the newly-allocated dcache record.
- */
- afs_indexFlags[tdc->index] &= ~(IFDirtyPages | IFAnyPages);
- tdc->f.fid = avc->fid;
- afs_indexUnique[tdc->index] = tdc->f.fid.Fid.Unique;
- hones(tdc->f.versionNo); /* invalid value */
- tdc->f.chunk = chunk;
- tdc->validPos = AFS_CHUNKTOBASE(chunk);
- /* XXX */
- if (tdc->lruq.prev == &tdc->lruq)
- osi_Panic("lruq 1");
-
- /*
- * Now add to the two hash chains - note that i is still set
- * from the above DCHash call.
- */
- afs_dcnextTbl[tdc->index] = afs_dchashTbl[i];
- afs_dchashTbl[i] = tdc->index;
- i = DVHash(&avc->fid);
- afs_dvnextTbl[tdc->index] = afs_dvhashTbl[i];
- afs_dvhashTbl[i] = tdc->index;
- tdc->dflags = DFEntryMod;
- tdc->mflags = 0;
- tdc->f.states = 0;
- afs_MaybeWakeupTruncateDaemon();
- MReleaseWriteLock(&afs_xdcache);
- ConvertWToSLock(&tdc->lock);
- }
- }
-
-
- /* vcache->dcache hint failed */
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S)
- */
- afs_Trace4(afs_iclSetp, CM_TRACE_GETDCACHE2, ICL_TYPE_POINTER, avc,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
- hgetlo(tdc->f.versionNo), ICL_TYPE_INT32,
- hgetlo(avc->m.DataVersion));
- /*
- * Here we have the entry in tdc, with its refCount incremented.
- * Note: we don't use the S-lock on avc; it costs concurrency when
- * storing a file back to the server.
- */
-
- /*
- * Not a newly created file so we need to check the file's length and
- * compare data versions since someone could have changed the data or we're
- * reading a file written elsewhere. We only want to bypass doing no-op
- * read rpcs on newly created files (dv of 0) since only then we guarantee
- * that this chunk's data hasn't been filled by another client.
- */
- size = AFS_CHUNKSIZE(abyte);
- if (aflags & 4) /* called from write */
- tlen = *alen;
- else /* called from read */
- tlen = tdc->validPos - abyte;
- Position = AFS_CHUNKTOBASE(chunk);
- afs_Trace4(afs_iclSetp, CM_TRACE_GETDCACHE3, ICL_TYPE_INT32, tlen,
- ICL_TYPE_INT32, aflags, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(abyte), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(Position));
- if ((aflags & 4) && (hiszero(avc->m.DataVersion)))
- doAdjustSize = 1;
- if ((aflags & 4) && (abyte == Position) && (tlen >= size))
- overWriteWholeChunk = 1;
- if (doAdjustSize || overWriteWholeChunk) {
-#if defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
-#ifdef AFS_SGI_ENV
-#ifdef AFS_SGI64_ENV
- if (doAdjustSize)
- adjustsize = NBPP;
-#else /* AFS_SGI64_ENV */
- if (doAdjustSize)
- adjustsize = 8192;
-#endif /* AFS_SGI64_ENV */
-#else /* AFS_SGI_ENV */
- if (doAdjustSize)
- adjustsize = 4096;
-#endif /* AFS_SGI_ENV */
- if (AFS_CHUNKTOBASE(chunk) + adjustsize >= avc->m.Length &&
-#else /* defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV) */
-#if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV)
- if ((doAdjustSize || (AFS_CHUNKTOBASE(chunk) >= avc->m.Length)) &&
-#else
- if (AFS_CHUNKTOBASE(chunk) >= avc->m.Length &&
-#endif
-#endif /* defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV) */
- !hsame(avc->m.DataVersion, tdc->f.versionNo))
- doReallyAdjustSize = 1;
-
- if (doReallyAdjustSize || overWriteWholeChunk) {
- /* no data in file to read at this position */
- UpgradeSToWLock(&tdc->lock, 607);
-
- file = afs_CFileOpen(tdc->f.inode);
- afs_CFileTruncate(file, 0);
- afs_CFileClose(file);
- afs_AdjustSize(tdc, 0);
- hset(tdc->f.versionNo, avc->m.DataVersion);
- tdc->dflags |= DFEntryMod;
-
- ConvertWToSLock(&tdc->lock);
- }
- }
-
- /*
- * We must read in the whole chunk if the version number doesn't
- * match.
- */
- if (aflags & 2) {
- /* don't need data, just a unique dcache entry */
- ObtainWriteLock(&afs_xdcache, 608);
- hset(afs_indexTimes[tdc->index], afs_indexCounter);
- hadd32(afs_indexCounter, 1);
- ReleaseWriteLock(&afs_xdcache);
-
- updateV2DC(setLocks, avc, tdc, 553);
- if (vType(avc) == VDIR)
- *aoffset = abyte;
- else
- *aoffset = AFS_CHUNKOFFSET(abyte);
- if (tdc->validPos < abyte)
- *alen = (afs_size_t) 0;
- else
- *alen = tdc->validPos - abyte;
- ReleaseSharedLock(&tdc->lock);
- if (setLocks) {
- if (slowPass)
- ReleaseWriteLock(&avc->lock);
- else
- ReleaseReadLock(&avc->lock);
- }
- return tdc; /* check if we're done */
- }
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S)
- */
- osi_Assert((setLocks && !slowPass) || WriteLocked(&avc->lock));
-
- setNewCallback = setVcacheStatus = 0;
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S)
- */
- if (!hsame(avc->m.DataVersion, tdc->f.versionNo) && !overWriteWholeChunk) {
- /*
- * Version number mismatch.
- */
- UpgradeSToWLock(&tdc->lock, 609);
-
- /*
- * If data ever existed for this vnode, and this is a text object,
- * do some clearing. Now, you'd think you need only do the flush
- * when VTEXT is on, but VTEXT is turned off when the text object
- * is freed, while pages are left lying around in memory marked
- * with this vnode. If we would reactivate (create a new text
- * object from) this vnode, we could easily stumble upon some of
- * these old pages in pagein. So, we always flush these guys.
- * Sun has a wonderful lack of useful invariants in this system.
- *
- * avc->flushDV is the data version # of the file at the last text
- * flush. Clearly, at least, we don't have to flush the file more
- * often than it changes
- */
- if (hcmp(avc->flushDV, avc->m.DataVersion) < 0) {
- /*
- * By here, the cache entry is always write-locked. We can
- * deadlock if we call osi_Flush with the cache entry locked...
- * Unlock the dcache too.
- */
- ReleaseWriteLock(&tdc->lock);
- if (setLocks && !slowPass)
- ReleaseReadLock(&avc->lock);
- else
- ReleaseWriteLock(&avc->lock);
-
- osi_FlushText(avc);
- /*
- * Call osi_FlushPages in open, read/write, and map, since it
- * is too hard here to figure out if we should lock the
- * pvnLock.
- */
- if (setLocks && !slowPass)
- ObtainReadLock(&avc->lock);
- else
- ObtainWriteLock(&avc->lock, 66);
- ObtainWriteLock(&tdc->lock, 610);
- }
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(W)
- */
-
- /* Watch for standard race condition around osi_FlushText */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- updateV2DC(setLocks, avc, tdc, 569); /* set hint */
- afs_stats_cmperf.dcacheHits++;
- ConvertWToSLock(&tdc->lock);
- goto done;
- }
-
- /* Sleep here when cache needs to be drained. */
- if (setLocks && !slowPass
- && (afs_blocksUsed >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100)) {
- /* Make sure truncate daemon is running */
- afs_MaybeWakeupTruncateDaemon();
- ObtainWriteLock(&tdc->tlock, 614);
- tdc->refCount--; /* we'll re-obtain the dcache when we re-try. */
- ReleaseWriteLock(&tdc->tlock);
- ReleaseWriteLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- while ((afs_blocksUsed - afs_blocksDiscarded) >
- (CM_WAITFORDRAINPCT * afs_cacheBlocks) / 100) {
- afs_WaitForCacheDrain = 1;
- afs_osi_Sleep(&afs_WaitForCacheDrain);
- }
- afs_MaybeFreeDiscardedDCache();
- /* need to check if someone else got the chunk first. */
- goto RetryGetDCache;
- }
-
- /* Do not fetch data beyond truncPos. */
- maxGoodLength = avc->m.Length;
- if (avc->truncPos < maxGoodLength)
- maxGoodLength = avc->truncPos;
- Position = AFS_CHUNKBASE(abyte);
- if (vType(avc) == VDIR) {
- size = avc->m.Length;
- if (size > tdc->f.chunkBytes) {
- /* pre-reserve space for file */
- afs_AdjustSize(tdc, size);
- }
- size = 999999999; /* max size for transfer */
- } else {
- size = AFS_CHUNKSIZE(abyte); /* expected max size */
- /* don't read past end of good data on server */
- if (Position + size > maxGoodLength)
- size = maxGoodLength - Position;
- if (size < 0)
- size = 0; /* Handle random races */
- if (size > tdc->f.chunkBytes) {
- /* pre-reserve space for file */
- afs_AdjustSize(tdc, size); /* changes chunkBytes */
- /* max size for transfer still in size */
- }
- }
- if (afs_mariner && !tdc->f.chunk)
- afs_MarinerLog("fetch$Fetching", avc); /* , Position, size, afs_indexCounter ); */
- /*
- * Right now, we only have one tool, and it's a hammer. So, we
- * fetch the whole file.
- */
- DZap(&tdc->f.inode); /* pages in cache may be old */
-#ifdef IHINT
- if (file = tdc->ihint) {
- if (tdc->f.inode == file->inum)
- usedihint++;
- else {
- tdc->ihint = 0;
- afs_UFSClose(file);
- file = 0;
- nihints--;
- file = osi_UFSOpen(tdc->f.inode);
- }
- } else
-#endif /* IHINT */
- file = afs_CFileOpen(tdc->f.inode);
- afs_RemoveVCB(&avc->fid);
- tdc->f.states |= DWriting;
- tdc->dflags |= DFFetching;
- tdc->validPos = Position; /* which is AFS_CHUNKBASE(abyte) */
- if (tdc->mflags & DFFetchReq) {
- tdc->mflags &= ~DFFetchReq;
- if (afs_osi_Wakeup(&tdc->validPos) == 0)
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
- tdc->dflags);
- }
- tsmall =
- (struct tlocal1 *)osi_AllocLargeSpace(sizeof(struct tlocal1));
- setVcacheStatus = 0;
-#ifndef AFS_NOSTATS
- /*
- * Remember if we are doing the reading from a replicated volume,
- * and how many times we've zipped around the fetch/analyze loop.
- */
- fromReplica = (avc->states & CRO) ? 1 : 0;
- numFetchLoops = 0;
- accP = &(afs_stats_cmfullperf.accessinf);
- if (fromReplica)
- (accP->replicatedRefs)++;
- else
- (accP->unreplicatedRefs)++;
-#endif /* AFS_NOSTATS */
- /* this is a cache miss */
- afs_Trace4(afs_iclSetp, CM_TRACE_FETCHPROC, ICL_TYPE_POINTER, avc,
- ICL_TYPE_FID, &(avc->fid), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(Position), ICL_TYPE_INT32, size);
-
- if (size)
- afs_stats_cmperf.dcacheMisses++;
- code = 0;
- /*
- * Dynamic root support: fetch data from local memory.
- */
- if (afs_IsDynroot(avc)) {
- char *dynrootDir;
- int dynrootLen;
-
- afs_GetDynroot(&dynrootDir, &dynrootLen, &tsmall->OutStatus);
-
- dynrootDir += Position;
- dynrootLen -= Position;
- if (size > dynrootLen)
- size = dynrootLen;
- if (size < 0)
- size = 0;
- code = afs_CFileWrite(file, 0, dynrootDir, size);
- afs_PutDynroot();
-
- if (code == size)
- code = 0;
- else
- code = -1;
-
- tdc->validPos = Position + size;
- afs_CFileTruncate(file, size); /* prune it */
- } else
- /*
- * Not a dynamic vnode: do the real fetch.
- */
- do {
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(W)
- */
-
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- afs_int32 length_hi, length, bytes;
-#ifndef AFS_NOSTATS
- numFetchLoops++;
- if (fromReplica)
- (accP->numReplicasAccessed)++;
-
-#endif /* AFS_NOSTATS */
- if (!setLocks || slowPass) {
- avc->callback = tc->srvr->server;
- } else {
- newCallback = tc->srvr->server;
- setNewCallback = 1;
- }
- i = osi_Time();
- RX_AFS_GUNLOCK();
- tcall = rx_NewCall(tc->id);
- RX_AFS_GLOCK();
-
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHDATA);
-#ifdef AFS_64BIT_CLIENT
- length_hi = code = 0;
- if (!afs_serverHasNo64Bit(tc)) {
- tsize = size;
- RX_AFS_GUNLOCK();
- code =
- StartRXAFS_FetchData64(tcall,
- (struct AFSFid *)&avc->fid.
- Fid, Position, tsize);
- if (code != 0) {
- RX_AFS_GLOCK();
- afs_Trace2(afs_iclSetp, CM_TRACE_FETCH64CODE,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32,
- code);
- } else {
- bytes =
- rx_Read(tcall, (char *)&length_hi,
- sizeof(afs_int32));
- RX_AFS_GLOCK();
- if (bytes == sizeof(afs_int32)) {
- length_hi = ntohl(length_hi);
- } else {
- length_hi = 0;
- code = rx_Error(tcall);
- RX_AFS_GUNLOCK();
- code1 = rx_EndCall(tcall, code);
- RX_AFS_GLOCK();
- tcall = (struct rx_call *)0;
- }
- }
- }
- if (code == RXGEN_OPCODE || afs_serverHasNo64Bit(tc)) {
- if (Position > 0x7FFFFFFF) {
- code = EFBIG;
- } else {
- afs_int32 pos;
- pos = Position;
- RX_AFS_GUNLOCK();
- if (!tcall)
- tcall = rx_NewCall(tc->id);
- code =
- StartRXAFS_FetchData(tcall, (struct AFSFid *)
- &avc->fid.Fid, pos,
- size);
- RX_AFS_GLOCK();
- }
- afs_serverSetNo64Bit(tc);
- }
- if (code == 0) {
- RX_AFS_GUNLOCK();
- bytes =
- rx_Read(tcall, (char *)&length,
- sizeof(afs_int32));
- RX_AFS_GLOCK();
- if (bytes == sizeof(afs_int32)) {
- length = ntohl(length);
- } else {
- code = rx_Error(tcall);
- }
- }
- FillInt64(lengthFound, length_hi, length);
- afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64LENG,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
- ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(lengthFound));
-#else /* AFS_64BIT_CLIENT */
- RX_AFS_GUNLOCK();
- code =
- StartRXAFS_FetchData(tcall,
- (struct AFSFid *)&avc->fid.Fid,
- Position, size);
- RX_AFS_GLOCK();
- if (code == 0) {
- RX_AFS_GUNLOCK();
- bytes =
- rx_Read(tcall, (char *)&length,
- sizeof(afs_int32));
- RX_AFS_GLOCK();
- if (bytes == sizeof(afs_int32)) {
- length = ntohl(length);
- } else {
- code = rx_Error(tcall);
- }
- }
-#endif /* AFS_64BIT_CLIENT */
- if (code == 0) {
-
-#ifndef AFS_NOSTATS
- xferP =
- &(afs_stats_cmfullperf.rpc.
- fsXferTimes[AFS_STATS_FS_XFERIDX_FETCHDATA]);
- osi_GetuTime(&xferStartTime);
-
- code =
- afs_CacheFetchProc(tcall, file,
- (afs_size_t) Position, tdc,
- avc, &bytesToXfer,
- &bytesXferred, length);
-
- osi_GetuTime(&xferStopTime);
- (xferP->numXfers)++;
- if (!code) {
- (xferP->numSuccesses)++;
- afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_FETCHDATA] +=
- bytesXferred;
- (xferP->sumBytes) +=
- (afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_FETCHDATA] >> 10);
- afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_FETCHDATA] &= 0x3FF;
- if (bytesXferred < xferP->minBytes)
- xferP->minBytes = bytesXferred;
- if (bytesXferred > xferP->maxBytes)
- xferP->maxBytes = bytesXferred;
-
- /*
- * Tally the size of the object. Note: we tally the actual size,
- * NOT the number of bytes that made it out over the wire.
- */
- if (bytesToXfer <= AFS_STATS_MAXBYTES_BUCKET0)
- (xferP->count[0])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET1)
- (xferP->count[1])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET2)
- (xferP->count[2])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET3)
- (xferP->count[3])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET4)
- (xferP->count[4])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET5)
- (xferP->count[5])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET6)
- (xferP->count[6])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET7)
- (xferP->count[7])++;
- else
- (xferP->count[8])++;
-
- afs_stats_GetDiff(elapsedTime, xferStartTime,
- xferStopTime);
- afs_stats_AddTo((xferP->sumTime), elapsedTime);
- afs_stats_SquareAddTo((xferP->sqrTime),
- elapsedTime);
- if (afs_stats_TimeLessThan
- (elapsedTime, (xferP->minTime))) {
- afs_stats_TimeAssign((xferP->minTime),
- elapsedTime);
- }
- if (afs_stats_TimeGreaterThan
- (elapsedTime, (xferP->maxTime))) {
- afs_stats_TimeAssign((xferP->maxTime),
- elapsedTime);
- }
- }
-#else
- code =
- afs_CacheFetchProc(tcall, file, Position, tdc,
- avc, 0, 0, length);
-#endif /* AFS_NOSTATS */
- }
- if (code == 0) {
- RX_AFS_GUNLOCK();
- code =
- EndRXAFS_FetchData(tcall, &tsmall->OutStatus,
- &tsmall->CallBack,
- &tsmall->tsync);
- RX_AFS_GLOCK();
- }
- XSTATS_END_TIME;
- RX_AFS_GUNLOCK();
- if (tcall)
- code1 = rx_EndCall(tcall, code);
- RX_AFS_GLOCK();
- } else {
- code = -1;
- }
- if (!code && code1)
- code = code1;
-
- if (code == 0) {
- /* callback could have been broken (or expired) in a race here,
- * but we return the data anyway. It's as good as we knew about
- * when we started. */
- /*
- * validPos is updated by CacheFetchProc, and can only be
- * modifed under a dcache write lock, which we've blocked out
- */
- size = tdc->validPos - Position; /* actual segment size */
- if (size < 0)
- size = 0;
- afs_CFileTruncate(file, size); /* prune it */
- } else {
- if (!setLocks || slowPass) {
- ObtainWriteLock(&afs_xcbhash, 453);
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CUnique);
- avc->callback = NULL;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- } else {
- /* Something lost. Forget about performance, and go
- * back with a vcache write lock.
- */
- afs_CFileTruncate(file, 0);
- afs_AdjustSize(tdc, 0);
- afs_CFileClose(file);
- osi_FreeLargeSpace(tsmall);
- tsmall = 0;
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = 0;
- ReleaseReadLock(&avc->lock);
- slowPass = 1;
- goto RetryGetDCache;
- }
- }
-
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_FETCHDATA, SHARED_LOCK, NULL));
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(W)
- */
-
-#ifndef AFS_NOSTATS
- /*
- * In the case of replicated access, jot down info on the number of
- * attempts it took before we got through or gave up.
- */
- if (fromReplica) {
- if (numFetchLoops <= 1)
- (accP->refFirstReplicaOK)++;
- if (numFetchLoops > accP->maxReplicasPerRef)
- accP->maxReplicasPerRef = numFetchLoops;
- }
-#endif /* AFS_NOSTATS */
-
- tdc->dflags &= ~DFFetching;
- if (afs_osi_Wakeup(&tdc->validPos) == 0)
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER,
- tdc, ICL_TYPE_INT32, tdc->dflags);
- if (avc->execsOrWriters == 0)
- tdc->f.states &= ~DWriting;
-
- /* now, if code != 0, we have an error and should punt.
- * note that we have the vcache write lock, either because
- * !setLocks or slowPass.
- */
- if (code) {
- afs_CFileTruncate(file, 0);
- afs_AdjustSize(tdc, 0);
- afs_CFileClose(file);
- ZapDCE(tdc); /* sets DFEntryMod */
- if (vType(avc) == VDIR) {
- DZap(&tdc->f.inode);
- }
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- ObtainWriteLock(&afs_xcbhash, 454);
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- /*
- * Locks held:
- * avc->lock(W); assert(!setLocks || slowPass)
- */
- osi_Assert(!setLocks || slowPass);
- tdc = NULL;
- goto done;
- }
-
- /* otherwise we copy in the just-fetched info */
- afs_CFileClose(file);
- afs_AdjustSize(tdc, size); /* new size */
- /*
- * Copy appropriate fields into vcache. Status is
- * copied later where we selectively acquire the
- * vcache write lock.
- */
- if (slowPass)
- afs_ProcessFS(avc, &tsmall->OutStatus, areq);
- else
- setVcacheStatus = 1;
- hset64(tdc->f.versionNo, tsmall->OutStatus.dataVersionHigh,
- tsmall->OutStatus.DataVersion);
- tdc->dflags |= DFEntryMod;
- afs_indexFlags[tdc->index] |= IFEverUsed;
- ConvertWToSLock(&tdc->lock);
- } /*Data version numbers don't match */
- else {
- /*
- * Data version numbers match.
- */
- afs_stats_cmperf.dcacheHits++;
- } /*Data version numbers match */
-
- updateV2DC(setLocks, avc, tdc, 335); /* set hint */
- done:
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- * tdc->lock(S) if tdc
- */
-
- /*
- * See if this was a reference to a file in the local cell.
- */
- if (afs_IsPrimaryCellNum(avc->fid.Cell))
- afs_stats_cmperf.dlocalAccesses++;
- else
- afs_stats_cmperf.dremoteAccesses++;
-
- /* Fix up LRU info */
-
- if (tdc) {
- MObtainWriteLock(&afs_xdcache, 602);
- hset(afs_indexTimes[tdc->index], afs_indexCounter);
- hadd32(afs_indexCounter, 1);
- MReleaseWriteLock(&afs_xdcache);
-
- /* return the data */
- if (vType(avc) == VDIR)
- *aoffset = abyte;
- else
- *aoffset = AFS_CHUNKOFFSET(abyte);
- *alen = (tdc->f.chunkBytes - *aoffset);
- ReleaseSharedLock(&tdc->lock);
- }
-
- /*
- * Locks held:
- * avc->lock(R) if setLocks && !slowPass
- * avc->lock(W) if !setLocks || slowPass
- */
-
- /* Fix up the callback and status values in the vcache */
- doVcacheUpdate = 0;
- if (setLocks && !slowPass) {
- /* DCLOCKXXX
- *
- * This is our dirty little secret to parallel fetches.
- * We don't write-lock the vcache while doing the fetch,
- * but potentially we'll need to update the vcache after
- * the fetch is done.
- *
- * Drop the read lock and try to re-obtain the write
- * lock. If the vcache still has the same DV, it's
- * ok to go ahead and install the new data.
- */
- afs_hyper_t currentDV, statusDV;
-
- hset(currentDV, avc->m.DataVersion);
-
- if (setNewCallback && avc->callback != newCallback)
- doVcacheUpdate = 1;
-
- if (tsmall) {
- hset64(statusDV, tsmall->OutStatus.dataVersionHigh,
- tsmall->OutStatus.DataVersion);
-
- if (setVcacheStatus && avc->m.Length != tsmall->OutStatus.Length)
- doVcacheUpdate = 1;
- if (setVcacheStatus && !hsame(currentDV, statusDV))
- doVcacheUpdate = 1;
- }
-
- ReleaseReadLock(&avc->lock);
-
- if (doVcacheUpdate) {
- ObtainWriteLock(&avc->lock, 615);
- if (!hsame(avc->m.DataVersion, currentDV)) {
- /* We lose. Someone will beat us to it. */
- doVcacheUpdate = 0;
- ReleaseWriteLock(&avc->lock);
- }
- }
- }
-
- /* With slow pass, we've already done all the updates */
- if (slowPass) {
- ReleaseWriteLock(&avc->lock);
- }
-
- /* Check if we need to perform any last-minute fixes with a write-lock */
- if (!setLocks || doVcacheUpdate) {
- if (setNewCallback)
- avc->callback = newCallback;
- if (tsmall && setVcacheStatus)
- afs_ProcessFS(avc, &tsmall->OutStatus, areq);
- if (setLocks)
- ReleaseWriteLock(&avc->lock);
- }
-
- if (tsmall)
- osi_FreeLargeSpace(tsmall);
-
- return tdc;
-} /*afs_GetDCache */
-
-
-/*
- * afs_WriteThroughDSlots
- *
- * Description:
- * Sweep through the dcache slots and write out any modified
- * in-memory data back on to our caching store.
- *
- * Parameters:
- * None.
- *
- * Environment:
- * The afs_xdcache is write-locked through this whole affair.
- */
-void
-afs_WriteThroughDSlots(void)
-{
- register struct dcache *tdc;
- register afs_int32 i, touchedit = 0;
-
- struct afs_q DirtyQ, *tq;
-
- AFS_STATCNT(afs_WriteThroughDSlots);
-
- /*
- * Because of lock ordering, we can't grab dcache locks while
- * holding afs_xdcache. So we enter xdcache, get a reference
- * for every dcache entry, and exit xdcache.
- */
- MObtainWriteLock(&afs_xdcache, 283);
- QInit(&DirtyQ);
- for (i = 0; i < afs_cacheFiles; i++) {
- tdc = afs_indexTable[i];
-
- /* Grab tlock in case the existing refcount isn't zero */
- if (tdc && !(afs_indexFlags[i] & (IFFree | IFDiscarded))) {
- ObtainWriteLock(&tdc->tlock, 623);
- tdc->refCount++;
- ReleaseWriteLock(&tdc->tlock);
-
- QAdd(&DirtyQ, &tdc->dirty);
- }
- }
- MReleaseWriteLock(&afs_xdcache);
-
- /*
- * Now, for each dcache entry we found, check if it's dirty.
- * If so, get write-lock, get afs_xdcache, which protects
- * afs_cacheInodep, and flush it. Don't forget to put back
- * the refcounts.
- */
-
-#define DQTODC(q) ((struct dcache *)(((char *) (q)) - sizeof(struct afs_q)))
-
- for (tq = DirtyQ.prev; tq != &DirtyQ; tq = QPrev(tq)) {
- tdc = DQTODC(tq);
- if (tdc->dflags & DFEntryMod) {
- int wrLock;
-
- wrLock = (0 == NBObtainWriteLock(&tdc->lock, 619));
-
- /* Now that we have the write lock, double-check */
- if (wrLock && (tdc->dflags & DFEntryMod)) {
- tdc->dflags &= ~DFEntryMod;
- MObtainWriteLock(&afs_xdcache, 620);
- afs_WriteDCache(tdc, 1);
- MReleaseWriteLock(&afs_xdcache);
- touchedit = 1;
- }
- if (wrLock)
- ReleaseWriteLock(&tdc->lock);
- }
-
- afs_PutDCache(tdc);
- }
-
- MObtainWriteLock(&afs_xdcache, 617);
- if (!touchedit && (cacheDiskType != AFS_FCACHE_TYPE_MEM)) {
- /* Touch the file to make sure that the mtime on the file is kept
- * up-to-date to avoid losing cached files on cold starts because
- * their mtime seems old...
- */
- struct afs_fheader theader;
-
- theader.magic = AFS_FHMAGIC;
- theader.firstCSize = AFS_FIRSTCSIZE;
- theader.otherCSize = AFS_OTHERCSIZE;
- theader.version = AFS_CI_VERSION;
- afs_osi_Write(afs_cacheInodep, 0, &theader, sizeof(theader));
- }
- MReleaseWriteLock(&afs_xdcache);
-}
-
-/*
- * afs_MemGetDSlot
- *
- * Description:
- * Return a pointer to an freshly initialized dcache entry using
- * a memory-based cache. The tlock will be read-locked.
- *
- * Parameters:
- * aslot : Dcache slot to look at.
- * tmpdc : Ptr to dcache entry.
- *
- * Environment:
- * Must be called with afs_xdcache write-locked.
- */
-
-struct dcache *
-afs_MemGetDSlot(register afs_int32 aslot, register struct dcache *tmpdc)
-{
- register struct dcache *tdc;
- int existing = 0;
-
- AFS_STATCNT(afs_MemGetDSlot);
- if (CheckLock(&afs_xdcache) != -1)
- osi_Panic("getdslot nolock");
- if (aslot < 0 || aslot >= afs_cacheFiles)
- osi_Panic("getdslot slot");
- tdc = afs_indexTable[aslot];
- if (tdc) {
- QRemove(&tdc->lruq); /* move to queue head */
- QAdd(&afs_DLRU, &tdc->lruq);
- /* We're holding afs_xdcache, but get tlock in case refCount != 0 */
- ObtainWriteLock(&tdc->tlock, 624);
- tdc->refCount++;
- ConvertWToRLock(&tdc->tlock);
- return tdc;
- }
- if (tmpdc == NULL) {
- if (!afs_freeDSList)
- afs_GetDownDSlot(4);
- if (!afs_freeDSList) {
- /* none free, making one is better than a panic */
- afs_stats_cmperf.dcacheXAllocs++; /* count in case we have a leak */
- tdc = (struct dcache *)afs_osi_Alloc(sizeof(struct dcache));
-#ifdef KERNEL_HAVE_PIN
- pin((char *)tdc, sizeof(struct dcache)); /* XXX */
-#endif
- } else {
- tdc = afs_freeDSList;
- afs_freeDSList = (struct dcache *)tdc->lruq.next;
- existing = 1;
- }
- tdc->dflags = 0; /* up-to-date, not in free q */
- tdc->mflags = 0;
- QAdd(&afs_DLRU, &tdc->lruq);
- if (tdc->lruq.prev == &tdc->lruq)
- osi_Panic("lruq 3");
- } else {
- tdc = tmpdc;
- tdc->f.states = 0;
- }
-
- /* initialize entry */
- tdc->f.fid.Cell = 0;
- tdc->f.fid.Fid.Volume = 0;
- tdc->f.chunk = -1;
- hones(tdc->f.versionNo);
- tdc->f.inode = aslot;
- tdc->dflags |= DFEntryMod;
- tdc->refCount = 1;
- tdc->index = aslot;
- afs_indexUnique[aslot] = tdc->f.fid.Fid.Unique;
-
- if (existing) {
- osi_Assert(0 == NBObtainWriteLock(&tdc->lock, 674));
- osi_Assert(0 == NBObtainWriteLock(&tdc->mflock, 675));
- osi_Assert(0 == NBObtainWriteLock(&tdc->tlock, 676));
- }
-
- RWLOCK_INIT(&tdc->lock, "dcache lock");
- RWLOCK_INIT(&tdc->tlock, "dcache tlock");
- RWLOCK_INIT(&tdc->mflock, "dcache flock");
- ObtainReadLock(&tdc->tlock);
-
- if (tmpdc == NULL)
- afs_indexTable[aslot] = tdc;
- return tdc;
-
-} /*afs_MemGetDSlot */
-
-unsigned int last_error = 0, lasterrtime = 0;
-
-/*
- * afs_UFSGetDSlot
- *
- * Description:
- * Return a pointer to an freshly initialized dcache entry using
- * a UFS-based disk cache. The dcache tlock will be read-locked.
- *
- * Parameters:
- * aslot : Dcache slot to look at.
- * tmpdc : Ptr to dcache entry.
- *
- * Environment:
- * afs_xdcache lock write-locked.
- */
-struct dcache *
-afs_UFSGetDSlot(register afs_int32 aslot, register struct dcache *tmpdc)
-{
- register afs_int32 code;
- register struct dcache *tdc;
- int existing = 0;
- int entryok;
-
- AFS_STATCNT(afs_UFSGetDSlot);
- if (CheckLock(&afs_xdcache) != -1)
- osi_Panic("getdslot nolock");
- if (aslot < 0 || aslot >= afs_cacheFiles)
- osi_Panic("getdslot slot");
- tdc = afs_indexTable[aslot];
- if (tdc) {
- QRemove(&tdc->lruq); /* move to queue head */
- QAdd(&afs_DLRU, &tdc->lruq);
- /* Grab tlock in case refCount != 0 */
- ObtainWriteLock(&tdc->tlock, 625);
- tdc->refCount++;
- ConvertWToRLock(&tdc->tlock);
- return tdc;
- }
- /* otherwise we should read it in from the cache file */
- /*
- * If we weren't passed an in-memory region to place the file info,
- * we have to allocate one.
- */
- if (tmpdc == NULL) {
- if (!afs_freeDSList)
- afs_GetDownDSlot(4);
- if (!afs_freeDSList) {
- /* none free, making one is better than a panic */
- afs_stats_cmperf.dcacheXAllocs++; /* count in case we have a leak */
- tdc = (struct dcache *)afs_osi_Alloc(sizeof(struct dcache));
-#ifdef KERNEL_HAVE_PIN
- pin((char *)tdc, sizeof(struct dcache)); /* XXX */
-#endif
- } else {
- tdc = afs_freeDSList;
- afs_freeDSList = (struct dcache *)tdc->lruq.next;
- existing = 1;
- }
- tdc->dflags = 0; /* up-to-date, not in free q */
- tdc->mflags = 0;
- QAdd(&afs_DLRU, &tdc->lruq);
- if (tdc->lruq.prev == &tdc->lruq)
- osi_Panic("lruq 3");
- } else {
- tdc = tmpdc;
- tdc->f.states = 0;
- tdc->ihint = 0;
- }
-
- /*
- * Seek to the aslot'th entry and read it in.
- */
- code =
- afs_osi_Read(afs_cacheInodep,
- sizeof(struct fcache) * aslot +
- sizeof(struct afs_fheader), (char *)(&tdc->f),
- sizeof(struct fcache));
- entryok = 1;
- if (code != sizeof(struct fcache))
- entryok = 0;
- if (!afs_CellNumValid(tdc->f.fid.Cell))
- entryok = 0;
-
- if (!entryok) {
- tdc->f.fid.Cell = 0;
- tdc->f.fid.Fid.Volume = 0;
- tdc->f.chunk = -1;
- hones(tdc->f.versionNo);
- tdc->dflags |= DFEntryMod;
-#if defined(KERNEL_HAVE_UERROR)
- last_error = getuerror();
-#endif
- lasterrtime = osi_Time();
- afs_indexUnique[aslot] = tdc->f.fid.Fid.Unique;
- }
- tdc->refCount = 1;
- tdc->index = aslot;
- if (tdc->f.chunk >= 0)
- tdc->validPos = AFS_CHUNKTOBASE(tdc->f.chunk) + tdc->f.chunkBytes;
- else
- tdc->validPos = 0;
-
- if (existing) {
- osi_Assert(0 == NBObtainWriteLock(&tdc->lock, 674));
- osi_Assert(0 == NBObtainWriteLock(&tdc->mflock, 675));
- osi_Assert(0 == NBObtainWriteLock(&tdc->tlock, 676));
- }
-
- RWLOCK_INIT(&tdc->lock, "dcache lock");
- RWLOCK_INIT(&tdc->tlock, "dcache tlock");
- RWLOCK_INIT(&tdc->mflock, "dcache flock");
- ObtainReadLock(&tdc->tlock);
-
- /*
- * If we didn't read into a temporary dcache region, update the
- * slot pointer table.
- */
- if (tmpdc == NULL)
- afs_indexTable[aslot] = tdc;
- return tdc;
-
-} /*afs_UFSGetDSlot */
-
-
-
-/*
- * afs_WriteDCache
- *
- * Description:
- * write a particular dcache entry back to its home in the
- * CacheInfo file.
- *
- * Parameters:
- * adc : Pointer to the dcache entry to write.
- * atime : If true, set the modtime on the file to the current time.
- *
- * Environment:
- * Must be called with the afs_xdcache lock at least read-locked,
- * and dcache entry at least read-locked.
- * The reference count is not changed.
- */
-
-int
-afs_WriteDCache(register struct dcache *adc, int atime)
-{
- register afs_int32 code;
-
- if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
- return 0;
- AFS_STATCNT(afs_WriteDCache);
- if (atime)
- adc->f.modTime = osi_Time();
- /*
- * Seek to the right dcache slot and write the in-memory image out to disk.
- */
- afs_cellname_write();
- code =
- afs_osi_Write(afs_cacheInodep,
- sizeof(struct fcache) * adc->index +
- sizeof(struct afs_fheader), (char *)(&adc->f),
- sizeof(struct fcache));
- if (code != sizeof(struct fcache))
- return EIO;
- return 0;
-}
-
-
-
-/*
- * afs_wakeup
- *
- * Description:
- * Wake up users of a particular file waiting for stores to take
- * place.
- *
- * Parameters:
- * avc : Ptr to related vcache entry.
- *
- * Environment:
- * Nothing interesting.
- */
-
-int
-afs_wakeup(register struct vcache *avc)
-{
- register int i;
- register struct brequest *tb;
- tb = afs_brs;
- AFS_STATCNT(afs_wakeup);
- for (i = 0; i < NBRS; i++, tb++) {
- /* if request is valid and for this file, we've found it */
- if (tb->refCount > 0 && avc == tb->vc) {
-
- /*
- * If CSafeStore is on, then we don't awaken the guy
- * waiting for the store until the whole store has finished.
- * Otherwise, we do it now. Note that if CSafeStore is on,
- * the BStore routine actually wakes up the user, instead
- * of us.
- * I think this is redundant now because this sort of thing
- * is already being handled by the higher-level code.
- */
- if ((avc->states & CSafeStore) == 0) {
- tb->code = 0;
- tb->flags |= BUVALID;
- if (tb->flags & BUWAIT) {
- tb->flags &= ~BUWAIT;
- afs_osi_Wakeup(tb);
- }
- }
- break;
- }
- }
- return 0;
-}
-
-
-/*
- * afs_InitCacheFile
- *
- * Description:
- * Given a file name and inode, set up that file to be an
- * active member in the AFS cache. This also involves checking
- * the usability of its data.
- *
- * Parameters:
- * afile : Name of the cache file to initialize.
- * ainode : Inode of the file.
- *
- * Environment:
- * This function is called only during initialization.
- */
-
-int
-afs_InitCacheFile(char *afile, ino_t ainode)
-{
- register afs_int32 code;
-#if defined(AFS_LINUX22_ENV)
- struct dentry *filevp;
-#else
- struct vnode *filevp;
-#endif
- afs_int32 index;
- int fileIsBad;
- struct osi_file *tfile;
- struct osi_stat tstat;
- register struct dcache *tdc;
-
- AFS_STATCNT(afs_InitCacheFile);
- index = afs_stats_cmperf.cacheNumEntries;
- if (index >= afs_cacheFiles)
- return EINVAL;
-
- MObtainWriteLock(&afs_xdcache, 282);
- tdc = afs_GetDSlot(index, NULL);
- ReleaseReadLock(&tdc->tlock);
- MReleaseWriteLock(&afs_xdcache);
-
- ObtainWriteLock(&tdc->lock, 621);
- MObtainWriteLock(&afs_xdcache, 622);
- if (afile) {
- code = gop_lookupname(afile, AFS_UIOSYS, 0, NULL, &filevp);
- if (code) {
- ReleaseWriteLock(&afs_xdcache);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- return code;
- }
- /*
- * We have a VN_HOLD on filevp. Get the useful info out and
- * return. We make use of the fact that the cache is in the
- * UFS file system, and just record the inode number.
- */
-#ifdef AFS_LINUX22_ENV
- tdc->f.inode = VTOI(filevp->d_inode)->i_number;
- dput(filevp);
-#else
- tdc->f.inode = afs_vnodeToInumber(filevp);
-#ifdef AFS_DEC_ENV
- grele(filevp);
-#else
- AFS_RELE(filevp);
-#endif
-#endif /* AFS_LINUX22_ENV */
- } else {
- tdc->f.inode = ainode;
- }
- fileIsBad = 0;
- if ((tdc->f.states & DWriting) || tdc->f.fid.Fid.Volume == 0)
- fileIsBad = 1;
- tfile = osi_UFSOpen(tdc->f.inode);
- code = afs_osi_Stat(tfile, &tstat);
- if (code)
- osi_Panic("initcachefile stat");
-
- /*
- * If file size doesn't match the cache info file, it's probably bad.
- */
- if (tdc->f.chunkBytes != tstat.size)
- fileIsBad = 1;
- tdc->f.chunkBytes = 0;
-
- /*
- * If file changed within T (120?) seconds of cache info file, it's
- * probably bad. In addition, if slot changed within last T seconds,
- * the cache info file may be incorrectly identified, and so slot
- * may be bad.
- */
- if (cacheInfoModTime < tstat.mtime + 120)
- fileIsBad = 1;
- if (cacheInfoModTime < tdc->f.modTime + 120)
- fileIsBad = 1;
- /* In case write through is behind, make sure cache items entry is
- * at least as new as the chunk.
- */
- if (tdc->f.modTime < tstat.mtime)
- fileIsBad = 1;
- if (fileIsBad) {
- tdc->f.fid.Fid.Volume = 0; /* not in the hash table */
- if (tstat.size != 0)
- osi_UFSTruncate(tfile, 0);
- /* put entry in free cache slot list */
- afs_dvnextTbl[tdc->index] = afs_freeDCList;
- afs_freeDCList = index;
- afs_freeDCCount++;
- afs_indexFlags[index] |= IFFree;
- afs_indexUnique[index] = 0;
- } else {
- /*
- * We must put this entry in the appropriate hash tables.
- * Note that i is still set from the above DCHash call
- */
- code = DCHash(&tdc->f.fid, tdc->f.chunk);
- afs_dcnextTbl[tdc->index] = afs_dchashTbl[code];
- afs_dchashTbl[code] = tdc->index;
- code = DVHash(&tdc->f.fid);
- afs_dvnextTbl[tdc->index] = afs_dvhashTbl[code];
- afs_dvhashTbl[code] = tdc->index;
- afs_AdjustSize(tdc, tstat.size); /* adjust to new size */
- if (tstat.size > 0)
- /* has nontrivial amt of data */
- afs_indexFlags[index] |= IFEverUsed;
- afs_stats_cmperf.cacheFilesReused++;
- /*
- * Initialize index times to file's mod times; init indexCounter
- * to max thereof
- */
- hset32(afs_indexTimes[index], tstat.atime);
- if (hgetlo(afs_indexCounter) < tstat.atime) {
- hset32(afs_indexCounter, tstat.atime);
- }
- afs_indexUnique[index] = tdc->f.fid.Fid.Unique;
- } /*File is not bad */
-
- osi_UFSClose(tfile);
- tdc->f.states &= ~DWriting;
- tdc->dflags &= ~DFEntryMod;
- /* don't set f.modTime; we're just cleaning up */
- afs_WriteDCache(tdc, 0);
- ReleaseWriteLock(&afs_xdcache);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- afs_stats_cmperf.cacheNumEntries++;
- return 0;
-}
-
-
-/*Max # of struct dcache's resident at any time*/
-/*
- * If 'dchint' is enabled then in-memory dcache min is increased because of
- * crashes...
- */
-#define DDSIZE 200
-
-/*
- * afs_dcacheInit
- *
- * Description:
- * Initialize dcache related variables.
- */
-void
-afs_dcacheInit(int afiles, int ablocks, int aDentries, int achunk, int aflags)
-{
- register struct dcache *tdp;
- int i;
- int code;
-
- afs_freeDCList = NULLIDX;
- afs_discardDCList = NULLIDX;
- afs_freeDCCount = 0;
- afs_freeDSList = NULL;
- hzero(afs_indexCounter);
-
- LOCK_INIT(&afs_xdcache, "afs_xdcache");
-
- /*
- * Set chunk size
- */
- if (achunk) {
- if (achunk < 0 || achunk > 30)
- achunk = 13; /* Use default */
- AFS_SETCHUNKSIZE(achunk);
- }
-
- if (!aDentries)
- aDentries = DDSIZE;
-
- if (aflags & AFSCALL_INIT_MEMCACHE) {
- /*
- * Use a memory cache instead of a disk cache
- */
- cacheDiskType = AFS_FCACHE_TYPE_MEM;
- afs_cacheType = &afs_MemCacheOps;
- afiles = (afiles < aDentries) ? afiles : aDentries; /* min */
- ablocks = afiles * (AFS_FIRSTCSIZE / 1024);
- /* ablocks is reported in 1K blocks */
- code = afs_InitMemCache(afiles, AFS_FIRSTCSIZE, aflags);
- if (code != 0) {
- printf("afsd: memory cache too large for available memory.\n");
- printf("afsd: AFS files cannot be accessed.\n\n");
- dcacheDisabled = 1;
- afiles = ablocks = 0;
- } else
- printf("Memory cache: Allocating %d dcache entries...",
- aDentries);
- } else {
- cacheDiskType = AFS_FCACHE_TYPE_UFS;
- afs_cacheType = &afs_UfsCacheOps;
- }
-
- if (aDentries > 512)
- afs_dhashsize = 2048;
- /* initialize hash tables */
- afs_dvhashTbl =
- (afs_int32 *) afs_osi_Alloc(afs_dhashsize * sizeof(afs_int32));
- afs_dchashTbl =
- (afs_int32 *) afs_osi_Alloc(afs_dhashsize * sizeof(afs_int32));
- for (i = 0; i < afs_dhashsize; i++) {
- afs_dvhashTbl[i] = NULLIDX;
- afs_dchashTbl[i] = NULLIDX;
- }
- afs_dvnextTbl = (afs_int32 *) afs_osi_Alloc(afiles * sizeof(afs_int32));
- afs_dcnextTbl = (afs_int32 *) afs_osi_Alloc(afiles * sizeof(afs_int32));
- for (i = 0; i < afiles; i++) {
- afs_dvnextTbl[i] = NULLIDX;
- afs_dcnextTbl[i] = NULLIDX;
- }
-
- /* Allocate and zero the pointer array to the dcache entries */
- afs_indexTable = (struct dcache **)
- afs_osi_Alloc(sizeof(struct dcache *) * afiles);
- memset((char *)afs_indexTable, 0, sizeof(struct dcache *) * afiles);
- afs_indexTimes =
- (afs_hyper_t *) afs_osi_Alloc(afiles * sizeof(afs_hyper_t));
- memset((char *)afs_indexTimes, 0, afiles * sizeof(afs_hyper_t));
- afs_indexUnique =
- (afs_int32 *) afs_osi_Alloc(afiles * sizeof(afs_uint32));
- memset((char *)afs_indexUnique, 0, afiles * sizeof(afs_uint32));
- afs_indexFlags = (u_char *) afs_osi_Alloc(afiles * sizeof(u_char));
- memset((char *)afs_indexFlags, 0, afiles * sizeof(char));
-
- /* Allocate and thread the struct dcache entries themselves */
- tdp = afs_Initial_freeDSList =
- (struct dcache *)afs_osi_Alloc(aDentries * sizeof(struct dcache));
- memset((char *)tdp, 0, aDentries * sizeof(struct dcache));
-#ifdef KERNEL_HAVE_PIN
- pin((char *)afs_indexTable, sizeof(struct dcache *) * afiles); /* XXX */
- pin((char *)afs_indexTimes, sizeof(afs_hyper_t) * afiles); /* XXX */
- pin((char *)afs_indexFlags, sizeof(char) * afiles); /* XXX */
- pin((char *)afs_indexUnique, sizeof(afs_int32) * afiles); /* XXX */
- pin((char *)tdp, aDentries * sizeof(struct dcache)); /* XXX */
- pin((char *)afs_dvhashTbl, sizeof(afs_int32) * afs_dhashsize); /* XXX */
- pin((char *)afs_dchashTbl, sizeof(afs_int32) * afs_dhashsize); /* XXX */
- pin((char *)afs_dcnextTbl, sizeof(afs_int32) * afiles); /* XXX */
- pin((char *)afs_dvnextTbl, sizeof(afs_int32) * afiles); /* XXX */
-#endif
-
- afs_freeDSList = &tdp[0];
- for (i = 0; i < aDentries - 1; i++) {
- tdp[i].lruq.next = (struct afs_q *)(&tdp[i + 1]);
- }
- tdp[aDentries - 1].lruq.next = (struct afs_q *)0;
-
- afs_stats_cmperf.cacheBlocksOrig = afs_stats_cmperf.cacheBlocksTotal =
- afs_cacheBlocks = ablocks;
- afs_ComputeCacheParms(); /* compute parms based on cache size */
-
- afs_dcentries = aDentries;
- afs_blocksUsed = 0;
- QInit(&afs_DLRU);
-}
-
-/*
- * shutdown_dcache
- *
- */
-void
-shutdown_dcache(void)
-{
- int i;
-
- afs_osi_Free(afs_dvnextTbl, afs_cacheFiles * sizeof(afs_int32));
- afs_osi_Free(afs_dcnextTbl, afs_cacheFiles * sizeof(afs_int32));
- afs_osi_Free(afs_indexTable, afs_cacheFiles * sizeof(struct dcache *));
- afs_osi_Free(afs_indexTimes, afs_cacheFiles * sizeof(afs_hyper_t));
- afs_osi_Free(afs_indexUnique, afs_cacheFiles * sizeof(afs_uint32));
- afs_osi_Free(afs_indexFlags, afs_cacheFiles * sizeof(u_char));
- afs_osi_Free(afs_Initial_freeDSList,
- afs_dcentries * sizeof(struct dcache));
-#ifdef KERNEL_HAVE_PIN
- unpin((char *)afs_dcnextTbl, afs_cacheFiles * sizeof(afs_int32));
- unpin((char *)afs_dvnextTbl, afs_cacheFiles * sizeof(afs_int32));
- unpin((char *)afs_indexTable, afs_cacheFiles * sizeof(struct dcache *));
- unpin((char *)afs_indexTimes, afs_cacheFiles * sizeof(afs_hyper_t));
- unpin((char *)afs_indexUnique, afs_cacheFiles * sizeof(afs_uint32));
- unpin((u_char *) afs_indexFlags, afs_cacheFiles * sizeof(u_char));
- unpin(afs_Initial_freeDSList, afs_dcentries * sizeof(struct dcache));
-#endif
-
-
- for (i = 0; i < afs_dhashsize; i++) {
- afs_dvhashTbl[i] = NULLIDX;
- afs_dchashTbl[i] = NULLIDX;
- }
-
- afs_osi_Free(afs_dvhashTbl, afs_dhashsize * sizeof(afs_int32));
- afs_osi_Free(afs_dchashTbl, afs_dhashsize * sizeof(afs_int32));
-
- afs_blocksUsed = afs_dcentries = 0;
- hzero(afs_indexCounter);
-
- afs_freeDCCount = 0;
- afs_freeDCList = NULLIDX;
- afs_discardDCList = NULLIDX;
- afs_freeDSList = afs_Initial_freeDSList = 0;
-
- LOCK_INIT(&afs_xdcache, "afs_xdcache");
- QInit(&afs_DLRU);
-
-}
+++ /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
- */
-
-/*
- * Dynamic /afs volume support.
- *
- * Implements:
- * afs_IsDynrootFid
- * afs_GetDynrootFid
- * afs_IsDynroot
- * afs_DynrootInvalidate
- * afs_GetDynroot
- * afs_PutDynroot
- * afs_DynrootNewVnode
- * afs_SetDynrootEnable
- * afs_GetDynrootEnable
- * afs_DynrootVOPRemove
- * afs_DynrootVOPSymlink
- *
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h"
-#include "afs/afs_osi.h"
-#include "afsint.h"
-#include "afs/lock.h"
-
-#include "afs/prs_fs.h"
-#include "afs/dir.h"
-
-#define AFS_DYNROOT_CELLNAME "dynroot"
-#define AFS_DYNROOT_VOLUME 1
-#define AFS_DYNROOT_VNODE 1
-#define AFS_DYNROOT_UNIQUE 1
-
-/*
- * Vnode numbers in dynroot are composed of a type field (upper 8 bits)
- * and a type-specific identifier in the lower 24 bits.
- */
-#define VN_TYPE_CELL 0x01 /* Corresponds to a struct cell */
-#define VN_TYPE_ALIAS 0x02 /* Corresponds to a struct cell_alias */
-#define VN_TYPE_SYMLINK 0x03 /* User-created symlink in /afs */
-
-#define VNUM_TO_VNTYPE(vnum) ((vnum) >> 24)
-#define VNUM_TO_VNID(vnum) ((vnum) & 0x00ffffff)
-#define VNUM_FROM_TYPEID(type, id) \
- ((type) << 24 | (id))
-#define VNUM_TO_CIDX(vnum) (VNUM_TO_VNID(vnum) >> 2)
-#define VNUM_TO_RW(vnum) (VNUM_TO_VNID(vnum) >> 1 & 1)
-#define VNUM_FROM_CIDX_RW(cidx, rw) \
- VNUM_FROM_TYPEID(VN_TYPE_CELL, \
- ((cidx) << 2 | (rw) << 1))
-#define VNUM_FROM_CAIDX_RW(caidx, rw) \
- VNUM_FROM_TYPEID(VN_TYPE_ALIAS, \
- ((caidx) << 2 | (rw) << 1))
-
-static int afs_dynrootEnable = 0;
-static int afs_dynrootCell = 0;
-
-static afs_rwlock_t afs_dynrootDirLock;
-/* Start of variables protected by afs_dynrootDirLock */
-static char *afs_dynrootDir = NULL;
-static int afs_dynrootDirLen;
-static int afs_dynrootDirLinkcnt;
-static int afs_dynrootDirVersion;
-static int afs_dynrootVersion = 1;
-static int afs_dynrootVersionHigh = 1;
-/* End of variables protected by afs_dynrootDirLock */
-
-/* A dynamically-created symlink in a dynroot /afs */
-struct afs_dynSymlink {
- struct afs_dynSymlink *next;
- int index;
- char *name;
- char *target;
-};
-
-static afs_rwlock_t afs_dynSymlinkLock;
-/* Start of variables protected by afs_dynSymlinkLock */
-static struct afs_dynSymlink *afs_dynSymlinkBase = NULL;
-static int afs_dynSymlinkIndex = 0;
-/* End of variables protected by afs_dynSymlinkLock */
-
-/*
- * Set up a cell for dynroot if it's not there yet.
- */
-static int
-afs_dynrootCellInit()
-{
- if (afs_dynrootEnable && !afs_dynrootCell) {
- afs_int32 cellHosts[MAXCELLHOSTS];
- struct cell *tc;
- int code;
-
- memset(cellHosts, 0, sizeof(cellHosts));
- code =
- afs_NewCell(AFS_DYNROOT_CELLNAME, cellHosts, CNoSUID | CNoAFSDB,
- NULL, 0, 0, 0);
- if (code)
- return code;
- tc = afs_GetCellByName(AFS_DYNROOT_CELLNAME, READ_LOCK);
- if (!tc)
- return ENODEV;
- afs_dynrootCell = tc->cellNum;
- afs_PutCell(tc, READ_LOCK);
- }
-
- return 0;
-}
-
-/*
- * Returns non-zero iff fid corresponds to the top of the dynroot volume.
- */
-int
-afs_IsDynrootFid(struct VenusFid *fid)
-{
- return (afs_dynrootEnable && fid->Cell == afs_dynrootCell
- && fid->Fid.Volume == AFS_DYNROOT_VOLUME
- && fid->Fid.Vnode == AFS_DYNROOT_VNODE
- && fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
-}
-
-/*
- * Obtain the magic dynroot volume Fid.
- */
-void
-afs_GetDynrootFid(struct VenusFid *fid)
-{
- fid->Cell = afs_dynrootCell;
- fid->Fid.Volume = AFS_DYNROOT_VOLUME;
- fid->Fid.Vnode = AFS_DYNROOT_VNODE;
- fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
-}
-
-/*
- * Returns non-zero iff avc is a pointer to the dynroot /afs vnode.
- */
-int
-afs_IsDynroot(struct vcache *avc)
-{
- return afs_IsDynrootFid(&avc->fid);
-}
-
-/*
- * Given the current page and chunk pointers in a directory, adjust them
- * appropriately so that the given file name can be appended. Used for
- * computing the size of a directory.
- */
-static void
-afs_dynroot_computeDirEnt(char *name, int *curPageP, int *curChunkP)
-{
- int esize;
-
- esize = afs_dir_NameBlobs(name);
- if (*curChunkP + esize > EPP) {
- *curPageP += 1;
- *curChunkP = 1;
- }
- *curChunkP += esize;
-}
-
-/*
- * Add directory entry by given name to a directory. Assumes the
- * caller has allocated the directory to be large enough to hold
- * the necessary entry.
- */
-static void
-afs_dynroot_addDirEnt(struct DirHeader *dirHeader, int *curPageP,
- int *curChunkP, char *name, int vnode)
-{
- char *dirBase = (char *)dirHeader;
- struct PageHeader *pageHeader;
- struct DirEntry *dirEntry;
- int sizeOfEntry, i, t1, t2;
- int curPage = *curPageP;
- int curChunk = *curChunkP;
- int didNewPage = 0;
-
- /*
- * Check if we need to flip pages.. If so, init the new page.
- */
- sizeOfEntry = afs_dir_NameBlobs(name);
- if (curChunk + sizeOfEntry > EPP) {
- curPage++;
- curChunk = 1;
- didNewPage = 1;
- }
-
- pageHeader = (struct PageHeader *)(dirBase + curPage * AFS_PAGESIZE);
- if (didNewPage) {
- pageHeader->pgcount = 0;
- pageHeader->tag = htons(1234);
- pageHeader->freecount = 0;
- pageHeader->freebitmap[0] = 0x01;
- for (i = 1; i < EPP / 8; i++)
- pageHeader->freebitmap[i] = 0;
-
- dirHeader->alloMap[curPage] = EPP - 1;
- }
-
- dirEntry = (struct DirEntry *)(pageHeader + curChunk);
- dirEntry->flag = 1;
- dirEntry->length = 0;
- dirEntry->next = 0;
- dirEntry->fid.vnode = htonl(vnode);
- dirEntry->fid.vunique = htonl(1);
- strcpy(dirEntry->name, name);
-
- for (i = curChunk; i < curChunk + sizeOfEntry; i++) {
- t1 = i / 8;
- t2 = i % 8;
- pageHeader->freebitmap[t1] |= (1 << t2);
- }
-
- /*
- * Add the new entry to the correct hash chain.
- */
- i = DirHash(name);
- dirEntry->next = dirHeader->hashTable[i];
- dirHeader->hashTable[i] = htons(curPage * EPP + curChunk);
-
- curChunk += sizeOfEntry;
- dirHeader->alloMap[curPage] -= sizeOfEntry;
-
- *curPageP = curPage;
- *curChunkP = curChunk;
-}
-
-/*
- * Invalidate the /afs vnode for dynroot; called when the underlying
- * directory has changed and needs to be re-read.
- */
-void
-afs_DynrootInvalidate(void)
-{
- afs_int32 retry;
- struct vcache *tvc;
- struct VenusFid tfid;
-
- if (!afs_dynrootEnable)
- return;
-
- ObtainWriteLock(&afs_dynrootDirLock, 687);
- afs_dynrootVersion++;
- afs_dynrootVersionHigh = osi_Time();
- ReleaseWriteLock(&afs_dynrootDirLock);
-
- afs_GetDynrootFid(&tfid);
- do {
- retry = 0;
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&tfid, &retry, 0);
- ReleaseReadLock(&afs_xvcache);
- } while (retry);
- if (tvc) {
- tvc->states &= ~(CStatd | CUnique);
- osi_dnlc_purgedp(tvc);
- afs_PutVCache(tvc);
- }
-}
-
-/*
- * Regenerates the dynroot contents from the current list of
- * cells. Useful when the list of cells has changed due to
- * an AFSDB lookup, for instance.
- */
-static void
-afs_RebuildDynroot(void)
-{
- int cellidx, maxcellidx, i;
- int aliasidx, maxaliasidx;
- struct cell *c;
- struct cell_alias *ca;
- int curChunk, curPage;
- int dirSize, dotLen;
- char *newDir, *dotCell;
- struct DirHeader *dirHeader;
- int linkCount = 0;
- struct afs_dynSymlink *ts;
- int newVersion;
-
- ObtainReadLock(&afs_dynrootDirLock);
- newVersion = afs_dynrootVersion;
- ReleaseReadLock(&afs_dynrootDirLock);
-
- /*
- * Compute the amount of space we need for the fake dir
- */
- curChunk = 13;
- curPage = 0;
-
- /* Reserve space for "." and ".." */
- curChunk += 2;
-
- for (cellidx = 0;; cellidx++) {
- c = afs_GetCellByIndex(cellidx, READ_LOCK);
- if (!c)
- break;
- if (c->cellNum == afs_dynrootCell)
- continue;
-
- dotLen = strlen(c->cellName) + 2;
- dotCell = afs_osi_Alloc(dotLen);
- strcpy(dotCell, ".");
- afs_strcat(dotCell, c->cellName);
-
- afs_dynroot_computeDirEnt(c->cellName, &curPage, &curChunk);
- afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);
-
- afs_osi_Free(dotCell, dotLen);
- afs_PutCell(c, READ_LOCK);
- }
- maxcellidx = cellidx;
-
- for (aliasidx = 0;; aliasidx++) {
- ca = afs_GetCellAlias(aliasidx);
- if (!ca)
- break;
-
- dotLen = strlen(ca->alias) + 2;
- dotCell = afs_osi_Alloc(dotLen);
- strcpy(dotCell, ".");
- afs_strcat(dotCell, ca->alias);
-
- afs_dynroot_computeDirEnt(ca->alias, &curPage, &curChunk);
- afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);
-
- afs_osi_Free(dotCell, dotLen);
- afs_PutCellAlias(ca);
- }
- maxaliasidx = aliasidx;
-
- ObtainReadLock(&afs_dynSymlinkLock);
- ts = afs_dynSymlinkBase;
- while (ts) {
- afs_dynroot_computeDirEnt(ts->name, &curPage, &curChunk);
- ts = ts->next;
- }
-
- dirSize = (curPage + 1) * AFS_PAGESIZE;
- newDir = afs_osi_Alloc(dirSize);
-
- /*
- * Now actually construct the directory.
- */
- curChunk = 13;
- curPage = 0;
- dirHeader = (struct DirHeader *)newDir;
-
- dirHeader->header.pgcount = 0;
- dirHeader->header.tag = htons(1234);
- dirHeader->header.freecount = 0;
-
- dirHeader->header.freebitmap[0] = 0xff;
- dirHeader->header.freebitmap[1] = 0x1f;
- for (i = 2; i < EPP / 8; i++)
- dirHeader->header.freebitmap[i] = 0;
- dirHeader->alloMap[0] = EPP - DHE - 1;
- for (i = 1; i < MAXPAGES; i++)
- dirHeader->alloMap[i] = EPP;
- for (i = 0; i < NHASHENT; i++)
- dirHeader->hashTable[i] = 0;
-
- /* Install "." and ".." */
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
- linkCount += 2;
-
- for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
- c = afs_GetCellByIndex(cellidx, READ_LOCK);
- if (!c)
- continue;
- if (c->cellNum == afs_dynrootCell)
- continue;
-
- dotLen = strlen(c->cellName) + 2;
- dotCell = afs_osi_Alloc(dotLen);
- strcpy(dotCell, ".");
- afs_strcat(dotCell, c->cellName);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, c->cellName,
- VNUM_FROM_CIDX_RW(cellidx, 0));
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
- VNUM_FROM_CIDX_RW(cellidx, 1));
- afs_osi_Free(dotCell, dotLen);
-
- linkCount += 2;
- afs_PutCell(c, READ_LOCK);
- }
-
- for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) {
- ca = afs_GetCellAlias(aliasidx);
- if (!ca)
- continue;
-
- dotLen = strlen(ca->alias) + 2;
- dotCell = afs_osi_Alloc(dotLen);
- strcpy(dotCell, ".");
- afs_strcat(dotCell, ca->alias);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ca->alias,
- VNUM_FROM_CAIDX_RW(aliasidx, 0));
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
- VNUM_FROM_CAIDX_RW(aliasidx, 1));
- afs_osi_Free(dotCell, dotLen);
- afs_PutCellAlias(ca);
- }
-
- ts = afs_dynSymlinkBase;
- while (ts) {
- int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ts->name, vnum);
- ts = ts->next;
- }
-
- ReleaseReadLock(&afs_dynSymlinkLock);
-
- ObtainWriteLock(&afs_dynrootDirLock, 549);
- if (afs_dynrootDir)
- afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
- afs_dynrootDir = newDir;
- afs_dynrootDirLen = dirSize;
- afs_dynrootDirLinkcnt = linkCount;
- afs_dynrootDirVersion = newVersion;
- ReleaseWriteLock(&afs_dynrootDirLock);
-}
-
-/*
- * Returns a pointer to the base of the dynroot directory in memory,
- * length thereof, and a FetchStatus.
- */
-void
-afs_GetDynroot(char **dynrootDir, int *dynrootLen,
- struct AFSFetchStatus *status)
-{
- ObtainReadLock(&afs_dynrootDirLock);
- if (!afs_dynrootDir || afs_dynrootDirVersion != afs_dynrootVersion) {
- ReleaseReadLock(&afs_dynrootDirLock);
- afs_RebuildDynroot();
- ObtainReadLock(&afs_dynrootDirLock);
- }
-
- if (dynrootDir)
- *dynrootDir = afs_dynrootDir;
- if (dynrootLen)
- *dynrootLen = afs_dynrootDirLen;
-
- if (status) {
- memset(status, 0, sizeof(struct AFSFetchStatus));
- status->FileType = Directory;
- status->LinkCount = afs_dynrootDirLinkcnt;
- status->Length = afs_dynrootDirLen;
- status->DataVersion = afs_dynrootVersion;
- status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
- status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
- status->UnixModeBits = 0755;
- status->ParentVnode = 1;
- status->ParentUnique = 1;
- status->dataVersionHigh = afs_dynrootVersionHigh;
- }
-}
-
-/*
- * Puts back the dynroot read lock.
- */
-void
-afs_PutDynroot(void)
-{
- ReleaseReadLock(&afs_dynrootDirLock);
-}
-
-/*
- * Inform dynroot that a new vnode is being created. Return value
- * is non-zero if this vnode is handled by dynroot, in which case
- * FetchStatus will be filled in.
- */
-int
-afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
-{
- if (!afs_dynrootEnable)
- return 0;
-
- if (afs_IsDynroot(avc)) {
- afs_GetDynroot(0, 0, status);
- afs_PutDynroot();
- return 1;
- }
-
- /*
- * Check if this is an entry under /afs, e.g. /afs/cellname.
- */
- if (avc->fid.Cell == afs_dynrootCell
- && avc->fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
-
- struct cell *c;
- struct cell_alias *ca;
- int namelen, linklen, cellidx, rw;
-
- memset(status, 0, sizeof(struct AFSFetchStatus));
-
- status->FileType = SymbolicLink;
- status->LinkCount = 1;
- status->DataVersion = 1;
- status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
- status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
- status->ParentVnode = 1;
- status->ParentUnique = 1;
-
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_SYMLINK) {
- struct afs_dynSymlink *ts;
- int index = VNUM_TO_VNID(avc->fid.Fid.Vnode);
-
- ObtainReadLock(&afs_dynSymlinkLock);
- ts = afs_dynSymlinkBase;
- while (ts) {
- if (ts->index == index)
- break;
- ts = ts->next;
- }
-
- if (ts) {
- linklen = strlen(ts->target);
- avc->linkData = afs_osi_Alloc(linklen + 1);
- strcpy(avc->linkData, ts->target);
-
- status->Length = linklen;
- status->UnixModeBits = 0755;
- }
- ReleaseReadLock(&afs_dynSymlinkLock);
-
- return ts ? 1 : 0;
- }
-
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_CELL
- && VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_ALIAS) {
- afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n",
- VNUM_TO_VNTYPE(avc->fid.Fid.Vnode));
- return 0;
- }
-
- cellidx = VNUM_TO_CIDX(avc->fid.Fid.Vnode);
- rw = VNUM_TO_RW(avc->fid.Fid.Vnode);
-
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_ALIAS) {
- char *realName;
-
- ca = afs_GetCellAlias(cellidx);
- if (!ca) {
- afs_warn("dynroot vnode inconsistency, can't find alias %d\n",
- cellidx);
- return 0;
- }
-
- /*
- * linkData needs to contain the name of the cell
- * we're aliasing for.
- */
- realName = ca->cell;
- if (!realName) {
- afs_warn("dynroot: alias %s missing real cell name\n",
- ca->alias);
- avc->linkData = afs_strdup("unknown");
- linklen = 7;
- } else {
- int namelen = strlen(realName);
- linklen = rw + namelen;
- avc->linkData = afs_osi_Alloc(linklen + 1);
- strcpy(avc->linkData, rw ? "." : "");
- afs_strcat(avc->linkData, realName);
- }
-
- status->UnixModeBits = 0755;
- afs_PutCellAlias(ca);
- } else {
- c = afs_GetCellByIndex(cellidx, READ_LOCK);
- if (!c) {
- afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
- cellidx);
- return 0;
- }
-
- /*
- * linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
- */
- namelen = strlen(c->cellName);
- linklen = 1 + namelen + 10;
- avc->linkData = afs_osi_Alloc(linklen + 1);
- strcpy(avc->linkData, rw ? "%" : "#");
- afs_strcat(avc->linkData, c->cellName);
- afs_strcat(avc->linkData, ":root.cell");
-
- status->UnixModeBits = 0644;
- afs_PutCell(c, READ_LOCK);
- }
-
- status->Length = linklen;
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Enable or disable dynroot. Returns 0 if successful.
- */
-int
-afs_SetDynrootEnable(int enable)
-{
- afs_dynrootEnable = enable;
- return afs_dynrootCellInit();
-}
-
-/*
- * Check if dynroot support is enabled.
- */
-int
-afs_GetDynrootEnable(void)
-{
- return afs_dynrootEnable;
-}
-
-/*
- * Remove a temporary symlink entry from /afs.
- */
-int
-afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred, char *aname)
-{
- struct afs_dynSymlink **tpps;
- struct afs_dynSymlink *tps;
- int found = 0;
-
- if (acred->cr_uid)
- return EPERM;
-
- ObtainWriteLock(&afs_dynSymlinkLock, 97);
- tpps = &afs_dynSymlinkBase;
- while (*tpps) {
- tps = *tpps;
- if (afs_strcasecmp(aname, tps->name) == 0) {
- afs_osi_Free(tps->name, strlen(tps->name) + 1);
- afs_osi_Free(tps->target, strlen(tps->target) + 1);
- *tpps = tps->next;
- afs_osi_Free(tps, sizeof(*tps));
- afs_dynSymlinkIndex++;
- found = 1;
- break;
- }
- tpps = &(tps->next);
- }
- ReleaseWriteLock(&afs_dynSymlinkLock);
- if (found) {
- afs_DynrootInvalidate();
- return 0;
- }
-
- if (afs_CellOrAliasExists(aname))
- return EROFS;
- else
- return ENOENT;
-}
-
-/*
- * Create a temporary symlink entry in /afs.
- */
-int
-afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname, char *atargetName)
-{
- struct afs_dynSymlink *tps;
-
- if (acred->cr_uid)
- return EPERM;
- if (afs_CellOrAliasExists(aname))
- return EEXIST;
-
- /* Check if it's already a symlink */
- ObtainWriteLock(&afs_dynSymlinkLock, 91);
- tps = afs_dynSymlinkBase;
- while (tps) {
- if (afs_strcasecmp(aname, tps->name) == 0) {
- ReleaseWriteLock(&afs_dynSymlinkLock);
- return EEXIST;
- }
- tps = tps->next;
- }
-
- /* Doesn't already exist -- go ahead and create it */
- tps = afs_osi_Alloc(sizeof(*tps));
- tps->index = afs_dynSymlinkIndex++;
- tps->next = afs_dynSymlinkBase;
- tps->name = afs_osi_Alloc(strlen(aname) + 1);
- strcpy(tps->name, aname);
- tps->target = afs_osi_Alloc(strlen(atargetName) + 1);
- strcpy(tps->target, atargetName);
- afs_dynSymlinkBase = tps;
- ReleaseWriteLock(&afs_dynSymlinkLock);
-
- afs_DynrootInvalidate();
- 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_exporter.c,v 1.8 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics gathering code */
-
-struct afs_exporter *root_exported = 0; /* Head of "exporters" link list */
-afs_lock_t afs_xexp;
-
-
-/* Add a new "afs exporter" entry to the table of exporters. The default initial values of the entry are passed in as parameters. */
-static afs_int32 init_xexported = 0;
-
-struct afs_exporter *
-exporter_add(afs_int32 size, struct exporterops *ops, afs_int32 state,
- afs_int32 type, char *data)
-{
- struct afs_exporter *ex, *op;
- afs_int32 length;
-
- AFS_STATCNT(exporter_add);
- if (!init_xexported) {
- init_xexported = 1;
- LOCK_INIT(&afs_xexp, "afs_xexp");
- }
- length = (size ? size : sizeof(struct afs_exporter));
- ex = (struct afs_exporter *)afs_osi_Alloc(length);
- memset((char *)ex, 0, length);
- MObtainWriteLock(&afs_xexp, 308);
- for (op = root_exported; op; op = op->exp_next) {
- if (!op->exp_next)
- break;
- }
- if (op)
- op->exp_next = ex;
- else
- root_exported = ex;
- MReleaseWriteLock(&afs_xexp);
- ex->exp_next = 0;
- ex->exp_op = ops;
- ex->exp_states = state;
- ex->exp_data = data;
- ex->exp_type = type;
- return ex;
-}
-
-
-/* Returns the "afs exporter" structure of type, "type". NULL is returned if not found */
-struct afs_exporter *
-exporter_find(int type)
-{
- struct afs_exporter *op;
-
- AFS_STATCNT(exporter_add);
- MObtainReadLock(&afs_xexp);
- for (op = root_exported; op; op = op->exp_next) {
- if (op->exp_type == type) {
- MReleaseReadLock(&afs_xexp);
- return op;
- }
- }
- MReleaseReadLock(&afs_xexp);
- return (struct afs_exporter *)0;
-}
-
-
-void
-shutdown_exporter(void)
-{
- struct afs_exporter *ex, *op;
-
- for (op = root_exported; op; op = ex) {
- ex = op->exp_next;
- afs_osi_Free(op, sizeof(struct afs_exporter));
- }
- init_xexported = 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
- */
-
-/*
- * afs_init.c - initialize AFS client.
- *
- * Implements:
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_init.c,v 1.28 2004/05/08 04:23:56 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-/* Exported variables */
-struct osi_dev cacheDev; /*Cache device */
-afs_int32 cacheInfoModTime; /*Last time cache info modified */
-#if defined(AFS_OSF_ENV) || defined(AFS_DEC_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-struct mount *afs_cacheVfsp = 0;
-#elif defined(AFS_LINUX20_ENV)
-struct super_block *afs_cacheSBp = 0;
-#else
-struct vfs *afs_cacheVfsp = 0;
-#endif
-afs_rwlock_t afs_puttofileLock; /* not used */
-char *afs_sysname = 0; /* So that superuser may change the
- * local value of @sys */
-char *afs_sysnamelist[MAXNUMSYSNAMES]; /* For support of a list of sysname */
-int afs_sysnamecount = 0;
-struct volume *Initialafs_freeVolList;
-int afs_memvolumes = 0;
-#if defined(AFS_XBSD_ENV)
-static struct vnode *volumeVnode;
-#endif
-
-/*
- * Initialization order is important. Must first call afs_CacheInit,
- * then cache file and volume file initialization routines. Next, the
- * individual cache entry initialization routines are called.
- */
-
-
-/*
- * afs_CacheInit
- *
- * Description:
- *
- * Parameters:
- * astatSize : The number of stat cache (vnode) entries to
- * allocate.
- * afiles : The number of disk files to allocate to the cache
- * ablocks : The max number of 1 Kbyte blocks that all of
- * the files in the cache may occupy.
- * aDentries : Number of dcache entries to allocate.
- * aVolumes : Number of volume cache entries to allocate.
- * achunk : Power of 2 to make the chunks.
- * aflags : Flags passed in.
- * inodes : max inodes to pin down in inode[]
- * users : what should size of per-user access cache be?
- *
- * Environment:
- * This routine should only be called at initialization time, since
- * it reclaims no resources and doesn't sufficiently synchronize
- * with other processes.
- */
-
-struct cm_initparams cm_initParams;
-static int afs_cacheinit_flag = 0;
-int
-afs_CacheInit(afs_int32 astatSize, afs_int32 afiles, afs_int32 ablocks,
- afs_int32 aDentries, afs_int32 aVolumes, afs_int32 achunk,
- afs_int32 aflags, afs_int32 ninodes, afs_int32 nusers)
-{
- register afs_int32 i;
- register struct volume *tv;
-
- AFS_STATCNT(afs_CacheInit);
- /*
- * Jot down the epoch time, namely when this incarnation of the
- * Cache Manager started.
- */
- afs_stats_cmperf.epoch = pag_epoch = osi_Time();
-#ifdef SYS_NAME_ID
- afs_stats_cmperf.sysName_ID = SYS_NAME_ID;
-#else
- afs_stats_cmperf.sysName_ID = SYS_NAME_ID_UNDEFINED;
-#endif /* SYS_NAME_ID */
-
- printf("Starting AFS cache scan...");
- if (afs_cacheinit_flag)
- return 0;
- afs_cacheinit_flag = 1;
- cacheInfoModTime = 0;
- maxIHint = ninodes;
- nihints = 0;
- usedihint = 0;
-
- LOCK_INIT(&afs_ftf, "afs_ftf");
- RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
- osi_dnlc_init();
-
-
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- {
- afs_int32 preallocs;
-
- /*
- * We want to also reserve space for the gnode struct which is associated
- * with each vnode (vcache) one; we want to use the pinned pool for them
- * since they're referenced at interrupt level.
- */
- if (afs_stats_cmperf.SmallBlocksAlloced + astatSize < 3600)
- preallocs = astatSize;
- else {
- preallocs = 3600 - afs_stats_cmperf.SmallBlocksAlloced;
- if (preallocs <= 0)
- preallocs = 10;
- }
- osi_AllocMoreSSpace(preallocs);
- }
-#endif
- /*
- * create volume list structure
- */
- if (aVolumes < 50)
- aVolumes = 50;
- else if (aVolumes > 3000)
- aVolumes = 3000;
-
- tv = (struct volume *)afs_osi_Alloc(aVolumes * sizeof(struct volume));
- for (i = 0; i < aVolumes - 1; i++)
- tv[i].next = &tv[i + 1];
- tv[aVolumes - 1].next = NULL;
- afs_freeVolList = Initialafs_freeVolList = tv;
- afs_memvolumes = aVolumes;
-
- afs_cacheFiles = afiles;
- afs_cacheStats = astatSize;
- afs_vcacheInit(astatSize);
- afs_dcacheInit(afiles, ablocks, aDentries, achunk, aflags);
-#ifdef AFS_64BIT_CLIENT
-#ifdef AFS_VM_RDWR_ENV
- afs_vmMappingEnd = AFS_CHUNKBASE(0x7fffffff);
-#endif /* AFS_VM_RDWR_ENV */
-#endif /* AFS_64BIT_CLIENT */
-
-#if defined(AFS_AIX_ENV) && !defined(AFS_AIX51_ENV)
- {
- static void afs_procsize_init(void);
-
- afs_procsize_init();
- }
-#endif
-
- /* Save the initialization parameters for later pioctl queries. */
- cm_initParams.cmi_version = CMI_VERSION;
- cm_initParams.cmi_nChunkFiles = afiles;
- cm_initParams.cmi_nStatCaches = astatSize;
- cm_initParams.cmi_nDataCaches = aDentries;
- cm_initParams.cmi_nVolumeCaches = aVolumes;
- cm_initParams.cmi_firstChunkSize = AFS_FIRSTCSIZE;
- cm_initParams.cmi_otherChunkSize = AFS_OTHERCSIZE;
- cm_initParams.cmi_cacheSize = afs_cacheBlocks;
- cm_initParams.cmi_setTime = afs_setTime;
- cm_initParams.cmi_memCache = (aflags & AFSCALL_INIT_MEMCACHE) ? 1 : 0;
-
- return 0;
-
-} /*afs_CacheInit */
-
-
-/*
- * afs_ComputeCacheParams
- *
- * Description:
- * Set some cache parameters.
- *
- * Parameters:
- * None.
- */
-
-void
-afs_ComputeCacheParms(void)
-{
- register afs_int32 i;
- afs_int32 afs_maxCacheDirty;
-
- /*
- * Don't allow more than 2/3 of the files in the cache to be dirty.
- */
- afs_maxCacheDirty = (2 * afs_cacheFiles) / 3;
-
- /*
- * Also, don't allow more than 2/3 of the total space get filled
- * with dirty chunks. Compute the total number of chunks required
- * to fill the cache, make sure we don't set out limit above 2/3 of
- * that. If the cache size is greater than 1G, avoid overflow at
- * the expense of precision on the chunk size.
- */
- if (afs_cacheBlocks & 0xffe00000) {
- i = afs_cacheBlocks / (AFS_FIRSTCSIZE >> 10);
- } else {
- i = (afs_cacheBlocks << 10) / AFS_FIRSTCSIZE;
- }
- i = (2 * i) / 3;
- if (afs_maxCacheDirty > i)
- afs_maxCacheDirty = i;
- if (afs_maxCacheDirty < 1)
- afs_maxCacheDirty = 1;
- afs_stats_cmperf.cacheMaxDirtyChunks = afs_maxCacheDirty;
-} /*afs_ComputeCacheParms */
-
-
-/*
- * LookupInodeByPath
- *
- * Look up inode given a file name.
- * Optionally return the vnode too.
- * If the vnode is not returned, we rele it.
- */
-static int
-LookupInodeByPath(char *filename, ino_t * inode, struct vnode **fvpp)
-{
- afs_int32 code;
-
-#ifdef AFS_LINUX22_ENV
- struct dentry *dp;
- code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &dp);
- if (code)
- return code;
- *inode = dp->d_inode->i_ino;
- dput(dp);
-#else
- struct vnode *filevp;
- code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &filevp);
- if (code)
- return code;
- *inode = afs_vnodeToInumber(filevp);
- if (fvpp)
- *fvpp = filevp;
- else {
-#if defined(AFS_DEC_ENV)
- grele(filevp);
-#else
- AFS_RELE(filevp);
-#endif
- }
-#endif /* AFS_LINUX22_ENV */
-
- return 0;
-}
-
-int
-afs_InitCellInfo(char *afile)
-{
- ino_t inode;
- int code;
-
- code = LookupInodeByPath(afile, &inode, NULL);
- return afs_cellname_init(inode, code);
-}
-
-/*
- * afs_InitVolumeInfo
- *
- * Description:
- * Set up the volume info storage file.
- *
- * Parameters:
- * afile : the file to be declared to be the volume info storage
- * file for AFS. It must be already truncated to 0 length.
- *
- * Environment:
- * This function is called only during initialization.
- *
- * WARNING: Data will be written to this file over time by AFS.
- */
-
-int
-afs_InitVolumeInfo(char *afile)
-{
- int code;
- struct osi_file *tfile;
-
- AFS_STATCNT(afs_InitVolumeInfo);
-#if defined(AFS_XBSD_ENV)
- /*
- * On Open/Free/NetBSD, we can get into big trouble if we don't hold the volume file
- * vnode. SetupVolume holds afs_xvolume lock exclusive.
- * SetupVolume->GetVolSlot->UFSGetVolSlot->{GetVolCache or WriteVolCache}
- * ->osi_UFSOpen->VFS_VGET()->ffs_vget->getnewvnode->vgone on some vnode.
- * If it's AFS, then ->vclean->afs_nbsd_reclaim->FlushVCache->QueueVCB->
- * GetVolume->FindVolume-> waits on afs_xvolume lock !
- *
- * In general, anything that's called with afs_xvolume locked must not
- * end up calling getnewvnode(). The only cases I've found so far
- * are things which try to get the volumeInode, and since we keep
- * it in the cache...
- */
- code = LookupInodeByPath(afile, &volumeInode, &volumeVnode);
-#else
- code = LookupInodeByPath(afile, &volumeInode, NULL);
-#endif
- if (code)
- return code;
- tfile = afs_CFileOpen(volumeInode);
- afs_CFileTruncate(tfile, 0);
- afs_CFileClose(tfile);
- return 0;
-}
-
-/*
- * afs_InitCacheInfo
- *
- * Description:
- * Set up the given file as the AFS cache info file.
- *
- * Parameters:
- * afile : Name of the file assumed to be the cache info file
- * for the Cache Manager; it will be used as such.
- * Side Effects: This sets afs_fragsize, which is used in the cache usage
- * calculations such as in afs_adjustsize()
- *
- * Environment:
- * This function is called only during initialization. The given
- * file should NOT be truncated to 0 lenght; its contents descrebe
- * what data is really in the cache.
- *
- * WARNING: data will be written to this file over time by AFS.
- *
- * NOTE: Starting to use separate osi_InitCacheInfo() routines to clean up
- * code.
- *
- */
-int
-afs_InitCacheInfo(register char *afile)
-{
- register afs_int32 code;
- struct osi_stat tstat;
- register struct osi_file *tfile;
- struct afs_fheader theader;
- struct vnode *filevp;
- int goodFile;
-
- AFS_STATCNT(afs_InitCacheInfo);
- if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
- osi_Panic("afs_InitCacheInfo --- called for non-ufs cache!");
-#ifdef AFS_LINUX22_ENV
- code = osi_InitCacheInfo(afile);
- if (code)
- return code;
-#else
- code = gop_lookupname(afile, AFS_UIOSYS, 0, NULL, &filevp);
- if (code || !filevp)
- return ENOENT;
- {
-#if defined(AFS_SUN56_ENV)
- struct statvfs64 st;
-#elif defined(AFS_HPUX102_ENV)
- struct k_statvfs st;
-#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) ||defined(AFS_HPUX100_ENV)
- struct statvfs st;
-#elif defined(AFS_DUX40_ENV)
- struct nstatfs st;
-#else
- struct statfs st;
-#endif /* SUN56 */
-
-#if defined(AFS_SGI_ENV)
-#ifdef AFS_SGI65_ENV
- VFS_STATVFS(filevp->v_vfsp, &st, NULL, code);
- if (!code)
-#else
- if (!VFS_STATFS(filevp->v_vfsp, &st, NULL))
-#endif /* AFS_SGI65_ENV */
-#elif defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
- if (!VFS_STATVFS(filevp->v_vfsp, &st))
-#elif defined(AFS_OSF_ENV)
-
- VFS_STATFS(filevp->v_vfsp, code);
- /* struct copy */
- st = filevp->v_vfsp->m_stat;
- if (code == 0)
-#elif defined(AFS_AIX41_ENV)
- if (!VFS_STATFS(filevp->v_vfsp, &st, &afs_osi_cred))
-#elif defined(AFS_LINUX20_ENV)
- {
- KERNEL_SPACE_DECL;
- TO_USER_SPACE();
-
- VFS_STATFS(filevp->v_vfsp, &st);
- TO_KERNEL_SPACE();
- }
-#elif defined(AFS_DARWIN_ENV)
- if (!VFS_STATFS(filevp->v_mount, &st, current_proc()))
-#elif defined(AFS_FBSD50_ENV)
- if (!VFS_STATFS(filevp->v_mount, &st, curthread))
-#elif defined(AFS_XBSD_ENV)
- if (!VFS_STATFS(filevp->v_mount, &st, curproc))
-#else
- if (!VFS_STATFS(filevp->v_vfsp, &st))
-#endif /* SGI... */
-#if defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
- afs_fsfragsize = st.f_frsize - 1;
-#else
- afs_fsfragsize = st.f_bsize - 1;
-#endif
- }
-#if defined(AFS_LINUX20_ENV)
- cacheInode = filevp->i_ino;
- afs_cacheSBp = filevp->i_sb;
-#elif defined(AFS_XBSD_ENV)
- cacheInode = VTOI(filevp)->i_number;
- cacheDev.mp = filevp->v_mount;
- cacheDev.held_vnode = filevp;
- vref(filevp); /* Make sure mount point stays busy. XXX */
-#if !defined(AFS_OBSD_ENV)
- afs_cacheVfsp = filevp->v_vfsp;
-#endif
-#else
-#if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
- afs_InitDualFSCacheOps(filevp);
-#endif
- cacheInode = afs_vnodeToInumber(filevp);
- cacheDev.dev = afs_vnodeToDev(filevp);
- afs_cacheVfsp = filevp->v_vfsp;
-#endif /* AFS_LINUX20_ENV */
- AFS_RELE(filevp);
-#endif /* AFS_LINUX22_ENV */
- tfile = osi_UFSOpen(cacheInode);
- afs_osi_Stat(tfile, &tstat);
- cacheInfoModTime = tstat.mtime;
- code = afs_osi_Read(tfile, -1, &theader, sizeof(theader));
- goodFile = 0;
- if (code == sizeof(theader)) {
- /* read the header correctly */
- if (theader.magic == AFS_FHMAGIC
- && theader.firstCSize == AFS_FIRSTCSIZE
- && theader.otherCSize == AFS_OTHERCSIZE
- && theader.version == AFS_CI_VERSION)
- goodFile = 1;
- }
- if (!goodFile) {
- /* write out a good file label */
- theader.magic = AFS_FHMAGIC;
- theader.firstCSize = AFS_FIRSTCSIZE;
- theader.otherCSize = AFS_OTHERCSIZE;
- theader.version = AFS_CI_VERSION;
- afs_osi_Write(tfile, 0, &theader, sizeof(theader));
- /*
- * Truncate the rest of the file, since it may be arbitrarily
- * wrong
- */
- osi_UFSTruncate(tfile, sizeof(struct afs_fheader));
- }
- /* Leave the file open now, since reopening the file makes public pool
- * vnode systems (like OSF/Alpha) much harder to handle, That's because
- * they can do a vnode recycle operation any time we open a file, which
- * we'd do on any afs_GetDSlot call, etc.
- */
- afs_cacheInodep = (struct osi_file *)tfile;
- return 0;
-}
-
-int afs_resourceinit_flag = 0;
-int
-afs_ResourceInit(int preallocs)
-{
- register afs_int32 i;
- static struct rx_securityClass *secobj;
-
- AFS_STATCNT(afs_ResourceInit);
- RWLOCK_INIT(&afs_xuser, "afs_xuser");
- RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
- RWLOCK_INIT(&afs_xserver, "afs_xserver");
- RWLOCK_INIT(&afs_xsrvAddr, "afs_xsrvAddr");
- RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
- RWLOCK_INIT(&afs_xinterface, "afs_xinterface");
- LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
-#ifndef AFS_FBSD_ENV
-#ifndef AFS_AIX32_ENV
- LOCK_INIT(&osi_fsplock, "osi_fsplock");
-#endif
- LOCK_INIT(&osi_flplock, "osi_flplock");
-#endif
- RWLOCK_INIT(&afs_xconn, "afs_xconn");
-
- afs_CellInit();
- afs_InitCBQueue(1); /* initialize callback queues */
-
- if (afs_resourceinit_flag == 0) {
- afs_resourceinit_flag = 1;
- for (i = 0; i < NFENTRIES; i++)
- fvTable[i] = 0;
- for (i = 0; i < MAXNUMSYSNAMES; i++)
- afs_sysnamelist[i] = afs_osi_Alloc(MAXSYSNAME);
- afs_sysname = afs_sysnamelist[0];
- strcpy(afs_sysname, SYS_NAME);
- afs_sysnamecount = 1;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- {
-
- if ((preallocs > 256) && (preallocs < 3600))
- afs_preallocs = preallocs;
- osi_AllocMoreSSpace(afs_preallocs);
- osi_AllocMoreMSpace(100);
- }
-#endif
- }
-
- secobj = rxnull_NewServerSecurityObject();
- afs_server =
- rx_NewService(0, 1, "afs", &secobj, 1, RXAFSCB_ExecuteRequest);
- afs_server =
- rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", &secobj, 1,
- RXSTATS_ExecuteRequest);
- rx_StartServer(0);
- afs_osi_Wakeup(&afs_server); /* wakeup anyone waiting for it */
- return 0;
-
-} /*afs_ResourceInit */
-
-#if defined(AFS_AIX_ENV) && !defined(AFS_AIX51_ENV)
-
-/*
- * AIX dynamic sizeof(struct proc)
- *
- * AIX keeps its proc structures in an array. The size of struct proc
- * varies from release to release of the OS. In order to maintain
- * binary compatibility with releases later than what we build on, we
- * need to determine the size of struct proc at run time.
- *
- * We need this in order to walk the proc[] array to do PAG garbage
- * collection.
- *
- * We also need this in order to support 'klog -setpag', since the
- * kernel code needs to locate the proc structure for the parent process
- * of the current process.
- *
- * To compute sizeof(struct proc), we need the addresses of two proc
- * structures and their corresponding pids. Given the pids, we can use
- * the PROCMASK() macro to compute their corresponding indices in the
- * proc[] array. By dividing the distance between the pointers by the
- * number of proc structures, we can compute the size of a single proc
- * structure.
- *
- * We know the base address of the proc table from v.vb_proc:
- *
- * <sys/sysconfig.h> declares sysconfig() and SYS_GETPARMS;
- * (we don't use this, but I note it here for completeness)
- *
- * <sys/var.h> declares struct var and external variable v;
- *
- * v.v_proc NPROC
- * v.vb_proc &proc[0]
- * v.ve_proc &proc[x] (current highwater mark for
- * proc[] array usage)
- *
- * The first proc pointer is v.vb_proc, which is the proc structure for
- * process 0. Process 0's pointer to its first child is the other proc
- * pointer. If process 0 has no children, we simply give up and do not
- * support features that require knowing the size of struct proc.
- */
-
-static void
-afs_procsize_init(void)
-{
- struct proc *p0; /* pointer to process 0 */
- struct proc *pN; /* pointer to process 0's first child */
-#ifdef AFS_AIX51_ENV
- struct pvproc *pV;
-#endif
- int pN_index;
- ptrdiff_t pN_offset;
- int procsize;
-
- p0 = (struct proc *)v.vb_proc;
- if (!p0) {
- afs_gcpags = AFS_GCPAGS_EPROC0;
- return;
- }
-#ifdef AFS_AIX51_ENV
- pN = (struct proc *)0;
- pV = p0->p_pvprocp;
- if (pV) {
- pV = pV->pv_child;
- if (pV)
- pN = pV->pv_procp;
- }
-#else
- pN = p0->p_child;
-#endif
- if (!pN) {
- afs_gcpags = AFS_GCPAGS_EPROCN;
- return;
- }
-
- if (pN->p_pid == p0->p_pid) {
- afs_gcpags = AFS_GCPAGS_EEQPID;
- return;
- }
-
- pN_index = PROCMASK(pN->p_pid);
- pN_offset = ((char *)pN - (char *)p0);
- procsize = pN_offset / pN_index;
-
- /*
- * check that the computation was exact
- */
-
- if (pN_index * procsize != pN_offset) {
- afs_gcpags = AFS_GCPAGS_EINEXACT;
- return;
- }
-
- /*
- * check that the proc table size is a multiple of procsize.
- */
-
- if ((((char *)v.ve_proc - (char *)v.vb_proc) % procsize) != 0) {
- afs_gcpags = AFS_GCPAGS_EPROCEND;
- return;
- }
-
- /* okay, use it */
-
- afs_gcpags_procsize = procsize;
-}
-#endif
-
-/*
- * shutdown_cache
- *
- * Description:
- * Clean up and shut down the AFS cache.
- *
- * Parameters:
- * None.
- *
- * Environment:
- * Nothing interesting.
- */
-void
-shutdown_cache(void)
-{
- AFS_STATCNT(shutdown_cache);
- afs_WriteThroughDSlots();
- if (afs_cold_shutdown) {
- afs_cacheinit_flag = 0;
- shutdown_dcache();
- shutdown_vcache();
-
- afs_cacheStats = 0;
- afs_cacheFiles = afs_cacheBlocks = 0;
- pag_epoch = maxIHint = nihints = usedihint = 0;
- pagCounter = 0;
-#if defined(AFS_XBSD_ENV)
- vrele(volumeVnode); /* let it go, finally. */
- volumeVnode = NULL;
- if (cacheDev.held_vnode) {
- vrele(cacheDev.held_vnode);
- cacheDev.held_vnode = NULL;
- }
-#endif
- cacheInode = volumeInode = (ino_t) 0;
-
- cacheInfoModTime = 0;
-
- afs_fsfragsize = 1023;
- memset((char *)&afs_stats_cmperf, 0, sizeof(afs_stats_cmperf));
- memset((char *)&cacheDev, 0, sizeof(struct osi_dev));
- osi_dnlc_shutdown();
- }
-} /*shutdown_cache */
-
-
-void
-shutdown_vnodeops(void)
-{
-#if !defined(AFS_SGI_ENV) && !defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
- struct buf *afs_bread_freebp = 0;
-#endif
-
-
- AFS_STATCNT(shutdown_vnodeops);
- if (afs_cold_shutdown) {
-#ifndef AFS_SUN5_ENV /* XXX */
- lastWarnTime = 0;
-#endif
-#ifndef AFS_LINUX20_ENV
- afs_rd_stash_i = 0;
-#endif
-#if !defined(AFS_SGI_ENV) && !defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
- afs_bread_freebp = 0;
-#endif
- shutdown_mariner();
- }
-}
-
-
-void
-shutdown_AFS(void)
-{
- int i;
- register struct srvAddr *sa;
-
- AFS_STATCNT(shutdown_AFS);
- if (afs_cold_shutdown) {
- afs_resourceinit_flag = 0;
- /*
- * Free Volumes table allocations
- */
- {
- struct volume *tv;
- for (i = 0; i < NVOLS; i++) {
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->name) {
- afs_osi_Free(tv->name, strlen(tv->name) + 1);
- tv->name = 0;
- }
- }
- afs_volumes[i] = 0;
- }
- }
-
- /*
- * Free FreeVolList allocations
- */
- afs_osi_Free(Initialafs_freeVolList,
- afs_memvolumes * sizeof(struct volume));
- afs_freeVolList = Initialafs_freeVolList = 0;
-
- /* XXX HACK fort MEM systems XXX
- *
- * For -memcache cache managers when we run out of free in memory volumes
- * we simply malloc more; we won't be able to free those additional volumes.
- */
-
-
-
- /*
- * Free Users table allocation
- */
- {
- struct unixuser *tu, *ntu;
- for (i = 0; i < NUSERS; i++) {
- for (tu = afs_users[i]; tu; tu = ntu) {
- ntu = tu->next;
- if (tu->stp)
- afs_osi_Free(tu->stp, tu->stLen);
- if (tu->exporter)
- EXP_RELE(tu->exporter);
- afs_osi_Free(tu, sizeof(struct unixuser));
- }
- afs_users[i] = 0;
- }
- }
-
- /*
- * Free Servers table allocation
- */
- {
- struct server *ts, *nts;
- struct conn *tc, *ntc;
- register struct afs_cbr *tcbrp, *tbrp;
-
- for (i = 0; i < NSERVERS; i++) {
- for (ts = afs_servers[i]; ts; ts = nts) {
- nts = ts->next;
- for (sa = ts->addr; sa; sa = sa->next_sa) {
- if (sa->conns) {
- /*
- * Free all server's connection structs
- */
- tc = sa->conns;
- while (tc) {
- ntc = tc->next;
- AFS_GUNLOCK();
- rx_DestroyConnection(tc->id);
- AFS_GLOCK();
- afs_osi_Free(tc, sizeof(struct conn));
- tc = ntc;
- }
- }
- }
- for (tcbrp = ts->cbrs; tcbrp; tcbrp = tbrp) {
- /*
- * Free all server's callback structs
- */
- tbrp = tcbrp->next;
- afs_FreeCBR(tcbrp);
- }
- afs_osi_Free(ts, sizeof(struct server));
- }
- afs_servers[i] = 0;
- }
- }
- for (i = 0; i < NFENTRIES; i++)
- fvTable[i] = 0;
- /* Reinitialize local globals to defaults */
- for (i = 0; i < MAXNUMSYSNAMES; i++)
- afs_osi_Free(afs_sysnamelist[i], MAXSYSNAME);
- afs_sysname = 0;
- afs_sysnamecount = 0;
- afs_marinerHost = 0;
- afs_setTimeHost = NULL;
- afs_volCounter = 1;
- afs_waitForever = afs_waitForeverCount = 0;
- afs_FVIndex = -1;
- afs_server = (struct rx_service *)0;
- RWLOCK_INIT(&afs_xconn, "afs_xconn");
- memset((char *)&afs_rootFid, 0, sizeof(struct VenusFid));
- RWLOCK_INIT(&afs_xuser, "afs_xuser");
- RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
- RWLOCK_INIT(&afs_xserver, "afs_xserver");
- LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
-
- shutdown_cell();
- shutdown_server();
- }
-}
+++ /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
- */
-
-/*******************************************************************\
-* *
-* Information Technology Center *
-* Carnegie-Mellon University *
-* *
-* *
-* *
-\*******************************************************************/
-
-
-/*
- Locking routines for Vice.
-
-*/
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_lock.c,v 1.9 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-/* probably needed if lock_trace is enabled - should ifdef */
-int afs_trclock = 0;
-
-void Lock_Obtain();
-void Lock_ReleaseR();
-void Lock_ReleaseW();
-
-void
-Lock_Init(register struct afs_lock *lock)
-{
-
- AFS_STATCNT(Lock_Init);
- lock->readers_reading = 0;
- lock->excl_locked = 0;
- lock->wait_states = 0;
- lock->num_waiting = 0;
-#if defined(INSTRUMENT_LOCKS)
- lock->pid_last_reader = 0;
- lock->pid_writer = 0;
- lock->src_indicator = 0;
-#endif /* INSTRUMENT_LOCKS */
- lock->time_waiting.tv_sec = 0;
- lock->time_waiting.tv_usec = 0;
-}
-\f
-void
-ObtainLock(register struct afs_lock *lock, int how,
- unsigned int src_indicator)
-{
- switch (how) {
- case READ_LOCK:
- if (!((lock)->excl_locked & WRITE_LOCK))
- (lock)->readers_reading++;
- else
- Afs_Lock_Obtain(lock, READ_LOCK);
-#if defined(INSTRUMENT_LOCKS)
- (lock)->pid_last_reader = MyPidxx;
-#endif /* INSTRUMENT_LOCKS */
- break;
- case WRITE_LOCK:
- if (!(lock)->excl_locked && !(lock)->readers_reading)
- (lock)->excl_locked = WRITE_LOCK;
- else
- Afs_Lock_Obtain(lock, WRITE_LOCK);
-#if defined(INSTRUMENT_LOCKS)
- (lock)->pid_writer = MyPidxx;
- (lock)->src_indicator = src_indicator;
-#endif /* INSTRUMENT_LOCKS */
- break;
- case SHARED_LOCK:
- if (!(lock)->excl_locked)
- (lock)->excl_locked = SHARED_LOCK;
- else
- Afs_Lock_Obtain(lock, SHARED_LOCK);
-#if defined(INSTRUMENT_LOCKS)
- (lock)->pid_writer = MyPidxx;
- (lock)->src_indicator = src_indicator;
-#endif /* INSTRUMENT_LOCKS */
- break;
- }
-}
-
-void
-ReleaseLock(register struct afs_lock *lock, int how)
-{
- if (how == READ_LOCK) {
- if (!--lock->readers_reading && lock->wait_states) {
-#if defined(INSTRUMENT_LOCKS)
- if (lock->pid_last_reader == MyPidxx)
- lock->pid_last_reader = 0;
-#endif /* INSTRUMENT_LOCKS */
- Afs_Lock_ReleaseW(lock);
- }
- } else if (how == WRITE_LOCK) {
- lock->excl_locked &= ~WRITE_LOCK;
-#if defined(INSTRUMENT_LOCKS)
- lock->pid_writer = 0;
-#endif /* INSTRUMENT_LOCKS */
- if (lock->wait_states)
- Afs_Lock_ReleaseR(lock);
- } else if (how == SHARED_LOCK) {
- lock->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);
-#if defined(INSTRUMENT_LOCKS)
- lock->pid_writer = 0;
-#endif /* INSTRUMENT_LOCKS */
- if (lock->wait_states)
- Afs_Lock_ReleaseR(lock);
- }
-}
-
-void
-Afs_Lock_Obtain(register struct afs_lock *lock, int how)
-{
- osi_timeval_t tt1, tt2, et;
- afs_uint32 us;
-
- AFS_STATCNT(Lock_Obtain);
-
- AFS_ASSERT_GLOCK();
- osi_GetuTime(&tt1);
-
- switch (how) {
-
- case READ_LOCK:
- lock->num_waiting++;
- do {
- lock->wait_states |= READ_LOCK;
- afs_osi_Sleep(&lock->readers_reading);
- } while (lock->excl_locked & WRITE_LOCK);
- lock->num_waiting--;
- lock->readers_reading++;
- break;
-
- case WRITE_LOCK:
- lock->num_waiting++;
- do {
- lock->wait_states |= WRITE_LOCK;
- afs_osi_Sleep(&lock->excl_locked);
- } while (lock->excl_locked || lock->readers_reading);
- lock->num_waiting--;
- lock->excl_locked = WRITE_LOCK;
- break;
-
- case SHARED_LOCK:
- lock->num_waiting++;
- do {
- lock->wait_states |= SHARED_LOCK;
- afs_osi_Sleep(&lock->excl_locked);
- } while (lock->excl_locked);
- lock->num_waiting--;
- lock->excl_locked = SHARED_LOCK;
- break;
-
- case BOOSTED_LOCK:
- lock->num_waiting++;
- do {
- lock->wait_states |= WRITE_LOCK;
- afs_osi_Sleep(&lock->excl_locked);
- } while (lock->readers_reading);
- lock->num_waiting--;
- lock->excl_locked = WRITE_LOCK;
- break;
-
- default:
- osi_Panic("afs locktype");
- }
-
- osi_GetuTime(&tt2);
- afs_stats_GetDiff(et, tt1, tt2);
- afs_stats_AddTo((lock->time_waiting), et);
- us = (et.tv_sec << 20) + et.tv_usec;
-
- if (afs_trclock) {
- afs_Trace3(afs_iclSetp, CM_TRACE_LOCKSLEPT, ICL_TYPE_INT32, us,
- ICL_TYPE_POINTER, lock, ICL_TYPE_INT32, how);
- }
-}
-
-/* release a lock, giving preference to new readers */
-void
-Afs_Lock_ReleaseR(register struct afs_lock *lock)
-{
- AFS_STATCNT(Lock_ReleaseR);
- AFS_ASSERT_GLOCK();
- if (lock->wait_states & READ_LOCK) {
- lock->wait_states &= ~READ_LOCK;
- afs_osi_Wakeup(&lock->readers_reading);
- } else {
- lock->wait_states &= ~EXCL_LOCKS;
- afs_osi_Wakeup(&lock->excl_locked);
- }
-}
-
-/* release a lock, giving preference to new writers */
-void
-Afs_Lock_ReleaseW(register struct afs_lock *lock)
-{
- AFS_STATCNT(Lock_ReleaseW);
- AFS_ASSERT_GLOCK();
- if (lock->wait_states & EXCL_LOCKS) {
- lock->wait_states &= ~EXCL_LOCKS;
- afs_osi_Wakeup(&lock->excl_locked);
- } else {
- lock->wait_states &= ~READ_LOCK;
- afs_osi_Wakeup(&lock->readers_reading);
- }
-}
-
-/*
-Wait for some change in the lock status.
-void Lock_Wait(register struct afs_lock *lock)
-{
- AFS_STATCNT(Lock_Wait);
- if (lock->readers_reading || lock->excl_locked) return 1;
- lock->wait_states |= READ_LOCK;
- afs_osi_Sleep(&lock->readers_reading);
- return 0;
-}
-*/
-
-/* These next guys exist to provide an interface to drop a lock atomically with
- * blocking. They're trivial to do in a non-preemptive LWP environment.
- */
-
-/* release a write lock and sleep on an address, atomically */
-void
-afs_osi_SleepR(register char *addr, register struct afs_lock *alock)
-{
- AFS_STATCNT(osi_SleepR);
- ReleaseReadLock(alock);
- afs_osi_Sleep(addr);
-}
-
-/* release a write lock and sleep on an address, atomically */
-void
-afs_osi_SleepW(register char *addr, register struct afs_lock *alock)
-{
- AFS_STATCNT(osi_SleepW);
- ReleaseWriteLock(alock);
- afs_osi_Sleep(addr);
-}
-
-/* release a write lock and sleep on an address, atomically */
-void
-afs_osi_SleepS(register char *addr, register struct afs_lock *alock)
-{
- AFS_STATCNT(osi_SleepS);
- ReleaseSharedLock(alock);
- afs_osi_Sleep(addr);
-}
-
-
-#ifndef AFS_NOBOZO_LOCK
-/* operations on locks that don't mind if we lock the same thing twice. I'd like to dedicate
- this function to Sun Microsystems' Version 4.0 virtual memory system, without
- which this wouldn't have been necessary */
-void
-afs_BozonLock(struct afs_bozoLock *alock, struct vcache *avc)
-{
- AFS_STATCNT(afs_BozonLock);
- while (1) {
- if (alock->count == 0) {
- /* lock not held, we win */
-#ifdef AFS_SUN5_ENV
- alock->proc = (char *)ttoproc(curthread);
-#else
-#ifdef AFS_64BITPOINTER_ENV
- /* To shut up SGI compiler on remark(1413) warnings. */
- alock->proc = (char *)(long)MyPidxx;
-#else /* AFS_64BITPOINTER_ENV */
- alock->proc = (char *)MyPidxx;
-#endif /* AFS_64BITPOINTER_ENV */
-#endif
- alock->count = 1;
- return;
-#ifdef AFS_SUN5_ENV
- } else if (alock->proc == (char *)ttoproc(curthread)) {
-#else
-#ifdef AFS_64BITPOINTER_ENV
- /* To shut up SGI compiler on remark(1413) warnings. */
- } else if (alock->proc == (char *)(long)MyPidxx) {
-#else /* AFS_64BITPOINTER_ENV */
- } else if (alock->proc == (char *)MyPidxx) {
-#endif /* AFS_64BITPOINTER_ENV */
-#endif
- /* lock is held, but by us, so we win anyway */
- alock->count++;
- return;
- } else {
- /* lock is held, and not by us; we wait */
- alock->flags |= AFS_BOZONWAITING;
- afs_osi_Sleep(alock);
- }
- }
-}
-
-/* releasing the same type of lock as defined above */
-void
-afs_BozonUnlock(struct afs_bozoLock *alock, struct vcache *avc)
-{
- AFS_STATCNT(afs_BozonUnlock);
- if (alock->count <= 0)
- osi_Panic("BozoUnlock");
- if ((--alock->count) == 0) {
- if (alock->flags & AFS_BOZONWAITING) {
- alock->flags &= ~AFS_BOZONWAITING;
- afs_osi_Wakeup(alock);
- }
- }
-}
-
-void
-afs_BozonInit(struct afs_bozoLock *alock, struct vcache *avc)
-{
- AFS_STATCNT(afs_BozonInit);
- alock->count = 0;
- alock->flags = 0;
- alock->proc = NULL;
-}
-
-int
-afs_CheckBozonLock(struct afs_bozoLock *alock)
-{
- AFS_STATCNT(afs_CheckBozonLock);
- if (alock->count || (alock->flags & AFS_BOZONWAITING))
- return 1;
- return 0;
-}
-
-int
-afs_CheckBozonLockBlocking(struct afs_bozoLock *alock)
-{
- AFS_STATCNT(afs_CheckBozonLockBlocking);
- if (alock->count || (alock->flags & AFS_BOZONWAITING))
-#ifdef AFS_SUN5_ENV
- if (alock->proc != (char *)ttoproc(curthread))
-#else
-#ifdef AFS_64BITPOINTER_ENV
- /* To shut up SGI compiler on remark(1413) warnings. */
- if (alock->proc != (char *)(long)MyPidxx)
-#else /* AFS_64BITPOINTER_ENV */
- if (alock->proc != (char *)MyPidxx)
-#endif /* AFS_64BITPOINTER_ENV */
-#endif
- return 1;
- return 0;
-}
-#endif
-
-/* Not static - used conditionally if lock tracing is enabled */
-int
-Afs_Lock_Trace(int op, struct afs_lock *alock, int type, char *file, int line)
-{
- int traceok;
- struct afs_icl_log *tlp;
- struct afs_icl_set *tsp;
-
- if (!afs_trclock)
- return 1;
- if ((alock) == &afs_icl_lock)
- return 1;
-
- ObtainReadLock(&afs_icl_lock);
- traceok = 1;
- for (tlp = afs_icl_allLogs; tlp; tlp = tlp->nextp)
- if ((alock) == &tlp->lock)
- traceok = 0;
- for (tsp = afs_icl_allSets; tsp; tsp = tsp->nextp)
- if ((alock) == &tsp->lock)
- traceok = 0;
- ReleaseReadLock(&afs_icl_lock);
- if (!traceok)
- return 1;
-
- afs_Trace4(afs_iclSetp, op, ICL_TYPE_STRING, (long)file, ICL_TYPE_INT32,
- (long)line, ICL_TYPE_POINTER, (long)alock, ICL_TYPE_LONG,
- (long)type);
- 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
- */
-
-/*
- * afs_mariner.c - fetch/store monitoring facility.
- */
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_mariner.c,v 1.8 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-/* Exported variables */
-struct rx_service *afs_server;
-
-
-#define SMAR 20 /* size of a mariner name */
-#define NMAR 10 /* number of mariner names */
-static char marinerNames[NMAR][SMAR];
-static struct vcache *marinerVCs[NMAR];
-static int marinerPtr = 0; /* pointer to next mariner slot to use */
-
-/* Exported variables */
-afs_int32 afs_mariner = 0;
-afs_int32 afs_marinerHost = 0;
-
-int
-afs_AddMarinerName(register char *aname, register struct vcache *avc)
-{
- register int i;
- register char *tp;
-
- AFS_STATCNT(afs_AddMarinerName);
- i = marinerPtr++;
- if (i >= NMAR) {
- i = 0;
- marinerPtr = 1;
- }
- tp = marinerNames[i];
- strncpy(tp, aname, SMAR);
- tp[SMAR - 1] = 0;
- marinerVCs[i] = avc;
- return 0;
-}
-
-char *
-afs_GetMariner(register struct vcache *avc)
-{
- register int i;
- AFS_STATCNT(afs_GetMariner);
- for (i = 0; i < NMAR; i++) {
- if (marinerVCs[i] == avc) {
- return marinerNames[i];
- }
- }
- return "a file";
-}
-
-void
-afs_MarinerLogFetch(register struct vcache *avc, register afs_int32 off,
- register afs_int32 bytes, register afs_int32 idx)
-{
- struct sockaddr_in taddr;
- register char *tp, *tp1, *tp2;
- struct iovec dvec;
- int len;
-
-
- AFS_STATCNT(afs_MarinerLog);
- taddr.sin_family = AF_INET;
- taddr.sin_addr.s_addr = afs_marinerHost;
- taddr.sin_port = htons(2106);
-#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
- taddr.sin_len = sizeof(taddr);
-#endif /* AFS_OSF_ENV */
- tp = tp1 = (char *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- strcpy(tp, "fetch$Fetching ");
- tp += 15; /* change it if string changes */
- tp2 = afs_GetMariner(avc);
- strcpy(tp, tp2);
- tp += strlen(tp2);
- *tp++ = '\n';
- /* note, console doesn't want a terminating null */
- len = strlen(tp1) - 1;
- /* I don't care if mariner packets fail to be sent */
- dvec.iov_base = tp1;
- dvec.iov_len = len;
- AFS_GUNLOCK();
- (void)osi_NetSend(afs_server->socket, &taddr, &dvec, 1, len, 0);
- AFS_GLOCK();
- osi_FreeSmallSpace(tp1);
-} /*afs_MarinerLogFetch */
-
-void
-afs_MarinerLog(register char *astring, register struct vcache *avc)
-{
- struct sockaddr_in taddr;
- register char *tp, *tp1, *buf;
- struct iovec dvec;
-
- AFS_STATCNT(afs_MarinerLog);
- taddr.sin_family = AF_INET;
- taddr.sin_addr.s_addr = afs_marinerHost;
- taddr.sin_port = htons(2106);
-#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
- taddr.sin_len = sizeof(taddr);
-#endif /* AFS_OSF_ENV */
- tp = buf = (char *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-
- strcpy(tp, astring);
- tp += strlen(astring);
- *tp++ = ' ';
- tp1 = afs_GetMariner(avc);
- strcpy(tp, tp1);
- tp += strlen(tp1);
- *tp++ = '\n';
- /* note, console doesn't want a terminating null */
- /* I don't care if mariner packets fail to be sent */
- dvec.iov_base = buf;
- dvec.iov_len = tp - buf;
- AFS_GUNLOCK();
- (void)osi_NetSend(afs_server->socket, &taddr, &dvec, 1, tp - buf, 0);
- AFS_GLOCK();
- osi_FreeSmallSpace(buf);
-} /*afs_MarinerLog */
-
-void
-shutdown_mariner(void)
-{
- int i;
-
- marinerPtr = 0;
- afs_mariner = 0;
-
- for (i = 0; i < NMAR; i++)
- marinerVCs[i] = 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_memcache.c,v 1.15 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#ifndef AFS_LINUX22_ENV
-#include "rpc/types.h"
-#endif
-#ifdef AFS_ALPHA_ENV
-#undef kmem_alloc
-#undef kmem_free
-#undef mem_alloc
-#undef mem_free
-#undef register
-#endif /* AFS_ALPHA_ENV */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-
-/* memory cache routines */
-static struct memCacheEntry *memCache;
-static int memCacheBlkSize = 8192;
-static int memMaxBlkNumber = 0;
-static int memAllocMaySleep = 0;
-
-extern int cacheDiskType;
-
-int
-afs_InitMemCache(int blkCount, int blkSize, int flags)
-{
- int index;
-
- AFS_STATCNT(afs_InitMemCache);
- if (blkSize)
- memCacheBlkSize = blkSize;
-
- memMaxBlkNumber = blkCount;
- memCache = (struct memCacheEntry *)
- afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
- if (flags & AFSCALL_INIT_MEMCACHE_SLEEP) {
- memAllocMaySleep = 1;
- }
-
- for (index = 0; index < memMaxBlkNumber; index++) {
- char *blk;
- (memCache + index)->size = 0;
- (memCache + index)->dataSize = memCacheBlkSize;
- LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
- if (memAllocMaySleep) {
- blk = afs_osi_Alloc(memCacheBlkSize);
- } else {
- blk = afs_osi_Alloc_NoSleep(memCacheBlkSize);
- }
- if (blk == NULL)
- goto nomem;
- (memCache + index)->data = blk;
- memset((memCache + index)->data, 0, memCacheBlkSize);
- }
-#if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS)
- afs_InitDualFSCacheOps((struct vnode *)0);
-#endif
-
- return 0;
-
- nomem:
- printf("afsd: memCache allocation failure at %d KB.\n",
- (index * memCacheBlkSize) / 1024);
- while (--index >= 0) {
- afs_osi_Free((memCache + index)->data, memCacheBlkSize);
- (memCache + index)->data = NULL;
- }
- return ENOMEM;
-
-}
-
-int
-afs_MemCacheClose(char *file)
-{
- return 0;
-}
-
-void *
-afs_MemCacheOpen(ino_t blkno)
-{
- struct memCacheEntry *mep;
-
- if (blkno < 0 || blkno > memMaxBlkNumber) {
- osi_Panic("afs_MemCacheOpen: invalid block #");
- }
- mep = (memCache + blkno);
- afs_Trace4(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, blkno,
- ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep->data,
- ICL_TYPE_STRING, mep->data);
- return (void *)mep;
-}
-
-/*
- * this routine simulates a read in the Memory Cache
- */
-int
-afs_MemReadBlk(register struct memCacheEntry *mceP, int offset, char *dest,
- int size)
-{
- int bytesRead;
-
- MObtainReadLock(&mceP->afs_memLock);
- AFS_STATCNT(afs_MemReadBlk);
- if (offset < 0) {
- MReleaseReadLock(&mceP->afs_memLock);
- return 0;
- }
- /* use min of bytes in buffer or requested size */
- bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
-
- if (bytesRead > 0) {
- AFS_GUNLOCK();
- memcpy(dest, mceP->data + offset, bytesRead);
- AFS_GLOCK();
- } else
- bytesRead = 0;
-
- MReleaseReadLock(&mceP->afs_memLock);
- return bytesRead;
-}
-
-/*
- * this routine simulates a readv in the Memory Cache
- */
-int
-afs_MemReadvBlk(register struct memCacheEntry *mceP, int offset,
- struct iovec *iov, int nio, int size)
-{
- int i;
- int bytesRead;
- int bytesToRead;
-
- MObtainReadLock(&mceP->afs_memLock);
- AFS_STATCNT(afs_MemReadBlk);
- if (offset < 0) {
- MReleaseReadLock(&mceP->afs_memLock);
- return 0;
- }
- /* use min of bytes in buffer or requested size */
- bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
-
- if (bytesRead > 0) {
- for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
- bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
- AFS_GUNLOCK();
- memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
- AFS_GLOCK();
- offset += bytesToRead;
- size -= bytesToRead;
- }
- bytesRead -= size;
- } else
- bytesRead = 0;
-
- MReleaseReadLock(&mceP->afs_memLock);
- return bytesRead;
-}
-
-int
-afs_MemReadUIO(ino_t blkno, struct uio *uioP)
-{
- register struct memCacheEntry *mceP =
- (struct memCacheEntry *)afs_MemCacheOpen(blkno);
- int length = mceP->size - uioP->uio_offset;
- afs_int32 code;
-
- AFS_STATCNT(afs_MemReadUIO);
- MObtainReadLock(&mceP->afs_memLock);
- length = (length < uioP->uio_resid) ? length : uioP->uio_resid;
- AFS_UIOMOVE(mceP->data + uioP->uio_offset, length, UIO_READ, uioP, code);
- MReleaseReadLock(&mceP->afs_memLock);
- return code;
-}
-
-/*XXX: this extends a block arbitrarily to support big directories */
-int
-afs_MemWriteBlk(register struct memCacheEntry *mceP, int offset, char *src,
- int size)
-{
- AFS_STATCNT(afs_MemWriteBlk);
- MObtainWriteLock(&mceP->afs_memLock, 560);
- if (size + offset > mceP->dataSize) {
- char *oldData = mceP->data;
-
- if (memAllocMaySleep) {
- mceP->data = afs_osi_Alloc(size + offset);
- } else {
- mceP->data = afs_osi_Alloc_NoSleep(size + offset);
- }
- if (mceP->data == NULL) { /* no available memory */
- mceP->data = oldData; /* revert back change that was made */
- MReleaseWriteLock(&mceP->afs_memLock);
- afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
- size + offset);
- return -ENOMEM;
- }
-
- /* may overlap, but this is OK */
- AFS_GUNLOCK();
- memcpy(mceP->data, oldData, mceP->size);
- AFS_GLOCK();
- afs_osi_Free(oldData, mceP->dataSize);
- mceP->dataSize = size + offset;
- }
- AFS_GUNLOCK();
- if (mceP->size < offset)
- memset(mceP->data + mceP->size, 0, offset - mceP->size);
- memcpy(mceP->data + offset, src, size);
- AFS_GLOCK();
- mceP->size = (size + offset < mceP->size) ? mceP->size : size + offset;
-
- MReleaseWriteLock(&mceP->afs_memLock);
- return size;
-}
-
-/*XXX: this extends a block arbitrarily to support big directories */
-int
-afs_MemWritevBlk(register struct memCacheEntry *mceP, int offset,
- struct iovec *iov, int nio, int size)
-{
- int i;
- int bytesWritten;
- int bytesToWrite;
- AFS_STATCNT(afs_MemWriteBlk);
- MObtainWriteLock(&mceP->afs_memLock, 561);
- if (offset + size > mceP->dataSize) {
- char *oldData = mceP->data;
-
- mceP->data = afs_osi_Alloc(size + offset);
-
- /* may overlap, but this is OK */
- AFS_GUNLOCK();
- memcpy(mceP->data, oldData, mceP->size);
- AFS_GLOCK();
- afs_osi_Free(oldData, mceP->dataSize);
- mceP->dataSize = size + offset;
- }
- AFS_GUNLOCK();
- if (mceP->size < offset)
- memset(mceP->data + mceP->size, 0, offset - mceP->size);
- for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
- bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
- memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
- offset += bytesToWrite;
- bytesWritten += bytesToWrite;
- size -= bytesToWrite;
- }
- mceP->size = (offset < mceP->size) ? mceP->size : offset;
- AFS_GLOCK();
-
- MReleaseWriteLock(&mceP->afs_memLock);
- return bytesWritten;
-}
-
-int
-afs_MemWriteUIO(ino_t blkno, struct uio *uioP)
-{
- register struct memCacheEntry *mceP =
- (struct memCacheEntry *)afs_MemCacheOpen(blkno);
- afs_int32 code;
-
- AFS_STATCNT(afs_MemWriteUIO);
- MObtainWriteLock(&mceP->afs_memLock, 312);
- if (uioP->uio_resid + uioP->uio_offset > mceP->dataSize) {
- char *oldData = mceP->data;
-
- mceP->data = afs_osi_Alloc(uioP->uio_resid + uioP->uio_offset);
-
- AFS_GUNLOCK();
- memcpy(mceP->data, oldData, mceP->size);
- AFS_GLOCK();
-
- afs_osi_Free(oldData, mceP->dataSize);
- mceP->dataSize = uioP->uio_resid + uioP->uio_offset;
- }
- if (mceP->size < uioP->uio_offset)
- memset(mceP->data + mceP->size, 0,
- (int)(uioP->uio_offset - mceP->size));
- AFS_UIOMOVE(mceP->data + uioP->uio_offset, uioP->uio_resid, UIO_WRITE,
- uioP, code);
- if (uioP->uio_offset > mceP->size)
- mceP->size = uioP->uio_offset;
-
- MReleaseWriteLock(&mceP->afs_memLock);
- return code;
-}
-
-int
-afs_MemCacheTruncate(register struct memCacheEntry *mceP, int size)
-{
- AFS_STATCNT(afs_MemCacheTruncate);
-
- MObtainWriteLock(&mceP->afs_memLock, 313);
- /* old directory entry; g.c. */
- if (size == 0 && mceP->dataSize > memCacheBlkSize) {
- afs_osi_Free(mceP->data, mceP->dataSize);
- mceP->data = afs_osi_Alloc(memCacheBlkSize);
- mceP->dataSize = memCacheBlkSize;
- }
-
- if (size < mceP->size)
- mceP->size = size;
-
- MReleaseWriteLock(&mceP->afs_memLock);
- return 0;
-}
-
-int
-afs_MemCacheStoreProc(register struct rx_call *acall,
- register struct memCacheEntry *mceP,
- register afs_int32 alen, struct vcache *avc,
- int *shouldWake, afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP, afs_int32 length)
-{
-
- register afs_int32 code;
- register int tlen;
- int offset = 0;
- struct iovec *tiov; /* no data copying with iovec */
- int tnio; /* temp for iovec size */
-
- AFS_STATCNT(afs_MemCacheStoreProc);
-#ifndef AFS_NOSTATS
- /*
- * In this case, alen is *always* the amount of data we'll be trying
- * to ship here.
- */
- *(abytesToXferP) = alen;
- *(abytesXferredP) = 0;
-#endif /* AFS_NOSTATS */
-
- /*
- * We need to alloc the iovecs on the heap so that they are "pinned" rather than
- * declare them on the stack - defect 11272
- */
- tiov =
- (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec) *
- RX_MAXIOVECS);
- if (!tiov) {
- osi_Panic
- ("afs_MemCacheStoreProc: osi_AllocSmallSpace for iovecs returned NULL\n");
- }
-#ifdef notdef
- /* do this at a higher level now -- it's a parameter */
- /* for now, only do 'continue from close' code if file fits in one
- * chunk. Could clearly do better: if only one modified chunk
- * then can still do this. can do this on *last* modified chunk */
- tlen = avc->m.Length - 1; /* byte position of last byte we'll store */
- if (shouldWake) {
- if (AFS_CHUNK(tlen) != 0)
- *shouldWake = 0;
- else
- *shouldWake = 1;
- }
-#endif /* notdef */
-
- while (alen > 0) {
- tlen = (alen > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : alen);
- RX_AFS_GUNLOCK();
- code = rx_WritevAlloc(acall, tiov, &tnio, RX_MAXIOVECS, tlen);
- RX_AFS_GLOCK();
- if (code <= 0) {
- osi_FreeSmallSpace(tiov);
- return -33;
- }
- tlen = code;
- code = afs_MemReadvBlk(mceP, offset, tiov, tnio, tlen);
- if (code != tlen) {
- osi_FreeSmallSpace(tiov);
- return -33;
- }
- RX_AFS_GUNLOCK();
- code = rx_Writev(acall, tiov, tnio, tlen);
- RX_AFS_GLOCK();
-#ifndef AFS_NOSTATS
- (*abytesXferredP) += code;
-#endif /* AFS_NOSTATS */
- if (code != tlen) {
- osi_FreeSmallSpace(tiov);
- return -33;
- }
- offset += tlen;
- alen -= tlen;
- /* if file has been locked on server, can allow store to continue */
- if (shouldWake && *shouldWake && (rx_GetRemoteStatus(acall) & 1)) {
- *shouldWake = 0; /* only do this once */
- afs_wakeup(avc);
- }
- }
- osi_FreeSmallSpace(tiov);
- return 0;
-}
-
-int
-afs_MemCacheFetchProc(register struct rx_call *acall,
- register struct memCacheEntry *mceP, afs_size_t abase,
- struct dcache *adc, struct vcache *avc,
- afs_size_t * abytesToXferP, afs_size_t * abytesXferredP,
- afs_int32 lengthFound)
-{
- register afs_int32 code;
- afs_int32 length;
- int moredata = 0;
- struct iovec *tiov; /* no data copying with iovec */
- register int tlen, offset = 0;
- int tnio; /* temp for iovec size */
-
- AFS_STATCNT(afs_MemCacheFetchProc);
- length = lengthFound;
- afs_Trace4(afs_iclSetp, CM_TRACE_MEMFETCH, ICL_TYPE_POINTER, avc,
- ICL_TYPE_POINTER, mceP, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(abase), ICL_TYPE_INT32, length);
-#ifndef AFS_NOSTATS
- (*abytesToXferP) = 0;
- (*abytesXferredP) = 0;
-#endif /* AFS_NOSTATS */
- /*
- * We need to alloc the iovecs on the heap so that they are "pinned" rather than
- * declare them on the stack - defect 11272
- */
- tiov =
- (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec) *
- RX_MAXIOVECS);
- if (!tiov) {
- osi_Panic
- ("afs_MemCacheFetchProc: osi_AllocSmallSpace for iovecs returned NULL\n");
- }
- adc->validPos = abase;
- do {
- if (moredata) {
- RX_AFS_GUNLOCK();
- code = rx_Read(acall, (char *)&length, sizeof(afs_int32));
- length = ntohl(length);
- RX_AFS_GLOCK();
- if (code != sizeof(afs_int32)) {
- code = rx_Error(acall);
- osi_FreeSmallSpace(tiov);
- return (code ? code : -1); /* try to return code, not -1 */
- }
- }
- /*
- * The fetch protocol is extended for the AFS/DFS translator
- * to allow multiple blocks of data, each with its own length,
- * to be returned. As long as the top bit is set, there are more
- * blocks expected.
- *
- * We do not do this for AFS file servers because they sometimes
- * return large negative numbers as the transfer size.
- */
- if (avc->states & CForeign) {
- moredata = length & 0x80000000;
- length &= ~0x80000000;
- } else {
- moredata = 0;
- }
-#ifndef AFS_NOSTATS
- (*abytesToXferP) += length;
-#endif /* AFS_NOSTATS */
- while (length > 0) {
- tlen = (length > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : length);
- RX_AFS_GUNLOCK();
- code = rx_Readv(acall, tiov, &tnio, RX_MAXIOVECS, tlen);
- RX_AFS_GLOCK();
-#ifndef AFS_NOSTATS
- (*abytesXferredP) += code;
-#endif /* AFS_NOSTATS */
- if (code <= 0) {
- afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64READ,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
- ICL_TYPE_INT32, length);
- osi_FreeSmallSpace(tiov);
- return -34;
- }
- tlen = code;
- afs_MemWritevBlk(mceP, offset, tiov, tnio, tlen);
- offset += tlen;
- abase += tlen;
- length -= tlen;
- adc->validPos = abase;
- if (afs_osi_Wakeup(&adc->validPos) == 0)
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, adc, ICL_TYPE_INT32,
- adc->dflags);
- }
- } while (moredata);
- /* max of two sizes */
- osi_FreeSmallSpace(tiov);
- return 0;
-}
-
-
-void
-shutdown_memcache(void)
-{
- register int index;
-
- if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
- return;
- memCacheBlkSize = 8192;
- for (index = 0; index < memMaxBlkNumber; index++) {
- LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
- afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
- }
- afs_osi_Free((char *)memCache,
- memMaxBlkNumber * sizeof(struct memCacheEntry));
- memMaxBlkNumber = 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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_nfsclnt.c,v 1.12 2004/03/17 06:43:34 shadow Exp $");
-
-#if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
-#ifndef AFS_DEC_ENV
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/nfsclient.h"
-
-int afs_nfsclient_reqhandler(), afs_nfsclient_hold(), afs_PutNfsClientPag();
-int afs_nfsclient_sysname(), afs_nfsclient_GC(), afs_nfsclient_stats();
-#ifdef AFS_AIX_IAUTH_ENV
-int afs_allnfsreqs, afs_nfscalls;
-#endif
-
-/* routines exported to the "AFS exporter" layer */
-struct exporterops nfs_exportops = {
- afs_nfsclient_reqhandler,
- afs_nfsclient_hold,
- afs_PutNfsClientPag, /* Used to be afs_nfsclient_rele */
- afs_nfsclient_sysname,
- afs_nfsclient_GC,
- afs_nfsclient_stats,
-};
-
-
-struct nfsclientpag *afs_nfspags[NNFSCLIENTS];
-afs_lock_t afs_xnfspag /*, afs_xnfsreq */ ;
-extern struct afs_exporter *afs_nfsexporter;
-
-/* Creates an nfsclientpag structure for the (uid, host) pair if one doesn't exist. RefCount is incremented and it's time stamped. */
-static struct nfsclientpag *
-afs_GetNfsClientPag(uid, host)
- register afs_int32 uid, host;
-{
- register struct nfsclientpag *np;
- register afs_int32 i, now;
-
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_GetNfsClientPag);
- i = NHash(host);
- now = osi_Time();
- MObtainWriteLock(&afs_xnfspag, 314);
- for (np = afs_nfspags[i]; np; np = np->next) {
- if (np->uid == uid && np->host == host) {
- np->refCount++;
- np->lastcall = now;
- MReleaseWriteLock(&afs_xnfspag);
- return np;
- }
- }
- /* next try looking for NOPAG dude, if we didn't find an exact match */
- for (np = afs_nfspags[i]; np; np = np->next) {
- if (np->uid == NOPAG && np->host == host) {
- np->refCount++;
- np->lastcall = now;
- MReleaseWriteLock(&afs_xnfspag);
- return np;
- }
- }
- np = (struct nfsclientpag *)afs_osi_Alloc(sizeof(struct nfsclientpag));
- memset((char *)np, 0, sizeof(struct nfsclientpag));
- /* Copy the necessary afs_exporter fields */
- memcpy((char *)np, (char *)afs_nfsexporter, sizeof(struct afs_exporter));
- np->next = afs_nfspags[i];
- afs_nfspags[i] = np;
- np->uid = uid;
- np->host = host;
- np->refCount = 1;
- np->lastcall = now;
- MReleaseWriteLock(&afs_xnfspag);
- return np;
-}
-
-
-/* Decrement refCount; must always match a previous afs_FindNfsClientPag/afs_GetNfsClientPag call .
-It's also called whenever a unixuser structure belonging to the remote user associated with the nfsclientpag structure, np, is garbage collected. */
-int
-afs_PutNfsClientPag(np)
- register struct nfsclientpag *np;
-{
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_PutNfsClientPag);
- --np->refCount;
-}
-
-
-/* Return the nfsclientpag structure associated with the (uid, host) or {pag, host} pair, if pag is nonzero. RefCount is incremented and it's time stamped. */
-static struct nfsclientpag *
-afs_FindNfsClientPag(uid, host, pag)
- register afs_int32 uid, host, pag;
-{
- register struct nfsclientpag *np;
- register afs_int32 i;
-
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_FindNfsClientPag);
- i = NHash(host);
- MObtainWriteLock(&afs_xnfspag, 315);
- for (np = afs_nfspags[i]; np; np = np->next) {
- if (np->host == host) {
- if ((pag && pag == np->pag) || (!pag && (uid == np->uid))) {
- np->refCount++;
- np->lastcall = osi_Time();
- MReleaseWriteLock(&afs_xnfspag);
- return np;
- }
- }
- }
- /* still not there, try looking for a wildcard dude */
- for (np = afs_nfspags[i]; np; np = np->next) {
- if (np->host == host) {
- if (np->uid == NOPAG) {
- np->refCount++;
- np->lastcall = osi_Time();
- MReleaseWriteLock(&afs_xnfspag);
- return np;
- }
- }
- }
- MReleaseWriteLock(&afs_xnfspag);
- return NULL;
-}
-
-
-/* routine to initialize the exporter, made global so we can call it
- * from pioctl calls.
- */
-struct afs_exporter *afs_nfsexported = 0;
-static afs_int32 init_nfsexporter = 0;
-afs_nfsclient_init()
-{
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- if (!init_nfsexporter) {
- extern struct afs_exporter *exporter_add();
-
- init_nfsexporter = 1;
- LOCK_INIT(&afs_xnfspag, "afs_xnfspag");
- afs_nfsexported =
- exporter_add(0, &nfs_exportops, EXP_EXPORTED, EXP_NFS, NULL);
- }
-}
-
-
-/* Main handler routine for the NFS exporter. It's called in the early
- * phases of any remote call (via the NFS server or pioctl).
- */
-int
-afs_nfsclient_reqhandler(exporter, cred, host, pagparam, outexporter)
- register struct afs_exporter *exporter, **outexporter;
- struct AFS_UCRED **cred;
- register afs_int32 host;
- afs_int32 *pagparam;
-{
- register struct nfsclientpag *np, *tnp;
- extern struct unixuser *afs_FindUser(), *afs_GetUser();
- register struct unixuser *au = 0;
- afs_int32 pag, code = 0;
-
- AFS_ASSERT_GLOCK();
- AFS_STATCNT(afs_nfsclient_reqhandler);
- if (!afs_nfsexporter)
- afs_nfsexporter = afs_nfsexported;
-
- afs_nfsexporter->exp_stats.calls++;
- if (!(afs_nfsexporter->exp_states & EXP_EXPORTED)) {
- /* No afs requests accepted as long as EXPORTED flag is turned 'off'. Set/Reset via a pioctl call (fs exportafs). Note that this is on top of the /etc/exports nfs requirement (i.e. /afs must be exported to all or whomever there too!)
- */
- afs_nfsexporter->exp_stats.rejectedcalls++;
- return EINVAL;
- }
-/* ObtainWriteLock(&afs_xnfsreq); */
- pag = PagInCred(*cred);
- if (pag != NOPAG) {
- /* Do some minimal pag verification */
- if (pag > getpag()) {
- pag = NOPAG; /* treat it as not paged since couldn't be good */
- } else {
- if (au = afs_FindUser(pag, -1, READ_LOCK)) {
- if (!au->exporter) {
- pag = NOPAG;
- afs_PutUser(au, READ_LOCK);
- au = NULL;
- }
- } else
- pag = NOPAG; /* No unixuser struct so pag not trusted */
- }
- }
- np = afs_FindNfsClientPag((*cred)->cr_uid, host, 0);
- afs_Trace4(afs_iclSetp, CM_TRACE_NFSREQH, ICL_TYPE_INT32, pag,
- ICL_TYPE_LONG, (*cred)->cr_uid, ICL_TYPE_INT32, host,
- ICL_TYPE_POINTER, np);
- if (!np) {
- /* Even if there is a "good" pag coming in we don't accept it if no nfsclientpag struct exists for the user since that would mean that the translator rebooted and therefore we ignore all older pag values */
-#ifdef AFS_OSF_ENV
- if (code = setpag(u.u_procp, cred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
-#else
- if (code = setpag(cred, -1, &pag, 1)) {
-#endif
- if (au)
- afs_PutUser(au, READ_LOCK);
-/* ReleaseWriteLock(&afs_xnfsreq); */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- return (code);
- }
- np = afs_GetNfsClientPag((*cred)->cr_uid, host);
- np->pag = pag;
- } else {
- if (pag == NOPAG) {
-#ifdef AFS_OSF_ENV
- if (code = setpag(u.u_procp, cred, np->pag, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
-#else
- if (code = setpag(cred, np->pag, &pag, 1)) {
-#endif
- afs_PutNfsClientPag(np);
-/* ReleaseWriteLock(&afs_xnfsreq); */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- return (code);
- }
- } else if (au->exporter
- && ((struct afs_exporter *)np != au->exporter)) {
- tnp = (struct nfsclientpag *)au->exporter;
- if (tnp->uid && (tnp->uid != (afs_int32) - 2)) { /* allow "root" initiators */
- /* Pag doesn't belong to caller; treat it as an unpaged call too */
-#ifdef AFS_OSF_ENV
- if (code = setpag(u.u_procp, cred, np->pag, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
-#else
- if (code = setpag(cred, np->pag, &pag, 1)) {
-#endif
- afs_PutNfsClientPag(np);
- afs_PutUser(au, READ_LOCK);
- /* ReleaseWriteLock(&afs_xnfsreq); */
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- return (code);
- }
- afs_nfsexporter->exp_stats.invalidpag++;
- }
- }
- }
- if (au)
- afs_PutUser(au, READ_LOCK);
- au = afs_GetUser(pag, -1, WRITE_LOCK);
- if (!(au->exporter)) { /* Created new unixuser struct */
- np->refCount++; /* so it won't disappear */
- au->exporter = (struct afs_exporter *)np;
- }
- *pagparam = pag;
- *outexporter = (struct afs_exporter *)np;
- afs_PutUser(au, WRITE_LOCK);
-#ifdef AFS_OSF_ENV
- (*cred)->cr_ruid = NFSXLATOR_CRED; /* Identify it as nfs xlator call */
-#else
- (*cred)->cr_rgid = NFSXLATOR_CRED; /* Identify it as nfs xlator call */
-#endif
-/* ReleaseWriteLock(&afs_xnfsreq); */
- return 0;
-}
-
-
-/* It's called whenever a new unixuser structure is created for the remote user associated with the nfsclientpag structure, np */
-int
-afs_nfsclient_hold(np)
- register struct nfsclientpag *np;
-{
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_nfsclient_hold);
- np->refCount++;
-}
-
-
-/* if inname is non-null, a new system name value is set for the remote user (inname contains the new sysname). In all cases, outname returns the current sysname value for this remote user */
-int
-afs_nfsclient_sysname(register struct nfsclientpag *np, char *inname,
- char **outname[], int *num)
-{
- char *cp;
- int count, t;
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_nfsclient_sysname);
- if (inname) {
- if (np->sysname) {
- for(count=0; count < np->sysnamecount;++count) {
- afs_osi_Free(np->sysname[count], MAXSYSNAME);
- }
- }
- for(count=0; count < *num;++count) {
- np->sysname[count]= afs_osi_Alloc(MAXSYSNAME);
- }
- cp = inname;
- for(count=0; count < *num;++count) {
- t = strlen(cp);
- memcpy(np->sysname[count], cp, t+1); /* include null */
- cp += t+1;
- }
- np->sysnamecount = *num;
- } else if (!np->sysname) {
- return ENODEV; /* XXX */
- }
- *outname = np->sysname;
- *num = np->sysnamecount;
- return 0;
-}
-
-
-/* Garbage collect routine for the nfs exporter. When pag is -1 then all entries are removed (used by the nfsclient_shutdown routine); else if it's non zero then only the entry with that pag is removed, else all "timedout" entries are removed. TimedOut entries are those who have no "unixuser" structures associated with them (i.e. unixusercnt == 0) and they haven't had any activity the last NFSCLIENTGC seconds */
-int
-afs_nfsclient_GC(exporter, pag)
- register struct afs_exporter *exporter;
- register afs_int32 pag;
-{
- register struct nfsclientpag *np, **tnp, *nnp;
- register afs_int32 i, delflag;
-
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_nfsclient_GC);
- MObtainWriteLock(&afs_xnfspag, 316);
- for (i = 0; i < NNFSCLIENTS; i++) {
- for (tnp = &afs_nfspags[i], np = *tnp; np; np = nnp) {
- nnp = np->next;
- delflag = 0;
- if (np->refCount == 0 && np->lastcall < osi_Time() - NFSCLIENTGC)
- delflag = 1;
- if ((pag == -1) || (!pag && delflag)
- || (pag && (np->refCount == 0) && (np->pag == pag))) {
- *tnp = np->next;
- if (np->sysname)
- afs_osi_Free(np->sysname, MAXSYSNAME);
- afs_osi_Free(np, sizeof(struct nfsclientpag));
- } else {
- tnp = &np->next;
- }
- }
- }
- MReleaseWriteLock(&afs_xnfspag);
-}
-
-
-int
-afs_nfsclient_stats(export)
- register struct afs_exporter *export;
-{
- /* Nothing much to do here yet since most important stats are collected directly in the afs_exporter structure itself */
- AFS_STATCNT(afs_nfsclient_stats);
- return 0;
-}
-
-#ifdef AFS_AIX41_ENV
-/* This is exposed so that vop_fid can test it, even if iauth is not
- * installed.
- */
-extern int afs_iauth_initd;
-#endif
-
-#ifdef AFS_AIX_IAUTH_ENV
-char *afs_nfs_id = "AFSNFSTRANS";
-/* afs_iauth_verify is the AFS authenticator for NFS.
- *
- * always returns 0.
- */
-int
-afs_iauth_verify(long id, fsid_t * fsidp, long host, int uid,
- struct AFS_UCRED *credp, struct exportinfo *exp)
-{
- int code;
- struct nfsclientpag *nfs_pag;
- afs_int32 dummypag;
- struct afs_exporter *outexporter = 0;
-
-
- /* Still needs basic test to see if exporter is on. And need to check the
- * whole no submounts bit.
- */
-
- if (id != (long)id)
- return 0; /* not us. */
-
- /* Only care if it's AFS */
- if ((fsidp->val[0] != AFS_VFSMAGIC) || (fsidp->val[1] != AFS_VFSFSID)) {
- return 0;
- }
-
- AFS_GLOCK();
- code =
- afs_nfsclient_reqhandler((struct afs_exporter *)0, &credp, host,
- &dummypag, &outexporter);
- if (!code && outexporter)
- EXP_RELE(outexporter);
-
- if (code) {
- /* ensure anonymous cred. */
- credp->cr_uid = credp->cr_ruid = (uid_t) - 2; /* anonymous */
- }
-
- /* Mark this thread as an NFS translator thread. */
- credp->cr_rgid = NFSXLATOR_CRED;
-
- AFS_GUNLOCK();
- return 0;
-}
-
-/* afs_iauth_register - register the iauth verify routine. Returns 0 on success
- * and -1 on failure. Can fail because DFS has already registered.
- */
-int
-afs_iauth_register()
-{
- if (nfs_iauth_register((unsigned long)afs_nfs_id, afs_iauth_verify))
- return -1;
- else {
- afs_iauth_initd = 1;
- return 0;
- }
-}
-
-/* afs_iauth_unregister - unregister the iauth verify routine. Called on shutdown.
- */
-void
-afs_iauth_unregister()
-{
- if (afs_iauth_initd)
- nfs_iauth_unregister((unsigned long)afs_nfs_id);
- afs_iauth_initd = 0;
-}
-#endif /* AFS_AIX_IAUTH_ENV */
-
-
-
-shutdown_nfsclnt()
-{
-#if 0
- extern int afs_allnfsreqs, afs_nfscalls;
-#endif
-
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(afs_nfsclient_shutdown);
-#ifdef AFS_AIX_IAUTH_ENV
- afs_iauth_register();
-#endif
- afs_nfsclient_GC(afs_nfsexporter, -1);
- init_nfsexporter = 0;
-#if 0
- /* The following are for the nfs/afs server */
- afs_allnfsreqs = afs_nfscalls = 0;
-#endif
-}
-#endif /* AFS_DEC_ENV */
-#endif /* AFS_NONFSTRANS */
+++ /dev/null
-/*
- * 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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_nfsdisp.c,v 1.18 2003/07/15 23:14:12 shadow Exp $");
-
-/* Ugly Ugly Ugly but precludes conflicting XDR macros; We want kernel xdr */
-#define __XDR_INCLUDE__
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#if defined(AFS_SUN55_ENV) && !defined(AFS_NONFSTRANS)
-#include "rpc/types.h"
-#include "rpc/auth.h"
-#include "rpc/auth_unix.h"
-#include "rpc/auth_des.h"
-#if !defined(AFS_SUN58_ENV)
-#include "rpc/auth_kerb.h"
-#endif
-#include "sys/tiuser.h"
-#include "rpc/xdr.h"
-#include "rpc/svc.h"
-#include "nfs/nfs.h"
-#include "nfs/export.h"
-#include "nfs/nfs_clnt.h"
-#include "nfs/nfs_acl.h"
-#include "afs/afsincludes.h"
-#include "afs/afs_stats.h"
-#include "afs/exporter.h"
-
-static int xlatorinit_v2_done = 0;
-static int xlatorinit_v3_done = 0;
-extern int afs_nobody;
-extern int afs_NFSRootOnly;
-
-struct rfs_disp_tbl {
- void (*dis_proc) ();
- xdrproc_t dis_xdrargs;
- xdrproc_t dis_fastxdrargs;
- int dis_argsz;
- xdrproc_t dis_xdrres;
- xdrproc_t dis_fastxdrres;
- int dis_ressz;
- void (*dis_resfree) ();
- int dis_flags;
- fhandle_t(*dis_getfh) ();
-};
-
-struct afs_nfs_disp_tbl {
- void (*afs_proc) ();
- void (*orig_proc) ();
-};
-struct afs_nfs2_resp {
- enum nfsstat status;
-};
-
-#ifndef ACL2_NPROC
-#define ACL2_NPROC 5
-#endif
-struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC];
-struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC];
-
-static int
-is_afs_fh(fhandle_t * fhp)
-{
- if ((fhp->fh_fsid.val[0] == AFS_VFSMAGIC)
- && (fhp->fh_fsid.val[1] == AFS_VFSFSID))
- return 1;
- return 0;
-}
-
-afs_int32
-nfs2_to_afs_call(int which, caddr_t * args, fhandle_t ** fhpp,
- fhandle_t ** fh2pp)
-{
- struct vnode *vp;
- fhandle_t *fhp1 = 0;
- fhandle_t *fhp2 = 0;
- int errorcode;
-
- afs_Trace1(afs_iclSetp, CM_TRACE_NFSIN, ICL_TYPE_INT32, which);
- *fh2pp = (fhandle_t *) 0;
- switch (which) {
- case RFS_GETATTR:
- case RFS_READLINK:
- case RFS_STATFS:
- fhp1 = (fhandle_t *) args;
- break;
- case RFS_SETATTR:
- {
- struct nfssaargs *sargs = (struct nfssaargs *)args;
- fhp1 = (fhandle_t *) & sargs->saa_fh;
- break;
- }
- case RFS_LOOKUP:
- {
- struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
- fhp1 = sargs->da_fhandle;
- break;
- }
- case RFS_READ:
- {
- struct nfsreadargs *sargs = (struct nfsreadargs *)args;
- fhp1 = (fhandle_t *) & sargs->ra_fhandle;
- break;
- }
- case RFS_WRITE:
- {
- struct nfswriteargs *sargs = (struct nfswriteargs *)args;
- fhp1 = (fhandle_t *) & sargs->wa_fhandle;
- break;
- }
- case RFS_CREATE:
- {
- struct nfscreatargs *sargs = (struct nfscreatargs *)args;
- fhp1 = sargs->ca_da.da_fhandle;
- break;
- }
- case RFS_REMOVE:
- {
- struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
- fhp1 = sargs->da_fhandle;
- break;
- }
- case RFS_RENAME:
- {
- struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
- fhp1 = sargs->rna_from.da_fhandle;
- fhp2 = sargs->rna_to.da_fhandle;
- break;
- }
- case RFS_LINK:
- {
- struct nfslinkargs *sargs = (struct nfslinkargs *)args;
- fhp1 = sargs->la_from;
- fhp2 = sargs->la_to.da_fhandle;
- break;
- }
- case RFS_SYMLINK:
- {
- struct nfsslargs *sargs = (struct nfsslargs *)args;
- fhp1 = sargs->sla_from.da_fhandle;
- break;
- }
- case RFS_MKDIR:
- {
- struct nfscreatargs *sargs = (struct nfscreatargs *)args;
- fhp1 = sargs->ca_da.da_fhandle;
- break;
- }
- case RFS_RMDIR:
- {
- struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
- fhp1 = sargs->da_fhandle;
- break;
- }
- case RFS_READDIR:
- {
- struct nfsrddirargs *sargs = (struct nfsrddirargs *)args;
- fhp1 = (fhandle_t *) & sargs->rda_fh;
- break;
- }
- default:
- return NULL;
- }
-
- /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
- if (is_afs_fh(fhp1)) {
- *fhpp = fhp1;
- if (fhp2)
- *fh2pp = fhp2;
- return 1;
- }
- if (fhp2 && is_afs_fh(fhp2)) {
- *fhpp = fhp1;
- *fh2pp = fhp2;
- return 1;
- }
- return NULL;
-}
-
-afs_int32
-acl2_to_afs_call(int which, caddr_t * args, fhandle_t ** fhpp)
-{
- fhandle_t *fhp;
-
- switch (which) {
- case ACLPROC2_NULL:
- {
- return NULL;
- }
- case ACLPROC2_GETACL:
- {
- struct GETACL2args *sargs = (struct GETACL2args *)args;
- fhp = &sargs->fh;
- break;
- }
- case ACLPROC2_SETACL:
- {
- struct SETACL2args *sargs = (struct SETACL2args *)args;
- fhp = &sargs->fh;
- break;
- }
- case ACLPROC2_GETATTR:
- {
- struct GETATTR2args *sargs = (struct GETATTR2args *)args;
- fhp = &sargs->fh;
- break;
- }
- case ACLPROC2_ACCESS:
- {
- struct ACCESS2args *sargs = (struct ACCESS2args *)args;
- fhp = &sargs->fh;
- break;
- }
- default:
- return NULL;
- }
-
- if (is_afs_fh(fhp)) {
- *fhpp = fhp;
- return 1;
- }
-
- return NULL;
-}
-
-int
-afs_nfs2_dispatcher(int type, afs_int32 which, char *argp,
- struct exportinfo **expp, struct svc_req *rp,
- struct AFS_UCRED *crp)
-{
- afs_int32 call = 0;
- afs_int32 code = 0;
- afs_int32 client = 0;
- struct sockaddr *sa;
- fhandle_t *fh = (fhandle_t *) argp;
- fhandle_t *fh2 = (fhandle_t *) 0;
-
- if (!xlatorinit_v2_done)
- return 2;
-
- sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
- if (sa->sa_family == AF_INET)
- client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
-
- AFS_GLOCK();
- code = 0;
- switch (type) {
- case 0:
- code = (client && nfs2_to_afs_call(which, argp, &fh, &fh2));
- break;
- case 1:
- code = (client && acl2_to_afs_call(which, argp, &fh));
- break;
- default:
- break;
- }
-
- if (code) {
- struct afs_exporter *out = 0;
- afs_int32 dummy;
- static int once = 0;
- struct SmallFid Sfid;
-
- memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
-
- afs_Trace2(afs_iclSetp, CM_TRACE_NFSIN1, ICL_TYPE_POINTER, client,
- ICL_TYPE_FID, &Sfid);
-
- /* We ran */
- call = 1;
- if (!once && *expp) {
- afs_nobody = (*expp)->exi_export.ex_anon;
- once = 1;
- }
- code =
- afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
- &dummy, &out);
-
- if (!code && out)
- EXP_RELE(out);
-
- if (code == EINVAL)
- call = 2;
- }
-
- AFS_GUNLOCK();
- return call;
-}
-
-void
-afs_nfs2_smallfidder(struct nfsdiropres *dr)
-{
- register fhandle_t *fhp = (fhandle_t *) & dr->dr_fhandle;
- afs_int32 addr[2];
- struct vcache *vcp;
-
-#if defined(AFS_SUN57_64BIT_ENV)
- /* See also afs_fid() */
- memcpy((char *)addr, fhp->fh_data, SIZEOF_SMALLFID);
- addr[1] = (addr[1] >> 48) & 0xffff;
-#else
- memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
-#endif
-
- AFS_GLOCK();
- vcp = VTOAFS((struct vnode *)addr[0]);
-
- if (addr[1] == AFS_XLATOR_MAGIC) {
- if (dr->dr_status == NFS_OK) {
- struct SmallFid Sfid;
- struct cell *tcell;
-
- /* Make up and copy out a SmallFid */
- tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
- Sfid.Volume = vcp->fid.Fid.Volume;
- Sfid.CellAndUnique =
- ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
- afs_PutCell(tcell, READ_LOCK);
- Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
- fhp->fh_len = SIZEOF_SMALLFID;
- memcpy(dr->dr_fhandle.fh_data, (char *)&Sfid, fhp->fh_len);
-
- afs_Trace3(afs_iclSetp, CM_TRACE_NFSOUT, ICL_TYPE_INT32, 0,
- ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
- }
-
- /* If we have a ref, release it */
- if (vcp->vrefCount >= 1)
- AFS_RELE(AFSTOV(vcp));
- }
- AFS_GUNLOCK();
-}
-
-void
-afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
-{
- resp->status = NFSERR_ACCES;
-}
-
-void
-afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
-{
-}
-
-void
-afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
-{
-}
-
-void
-afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
-{
-}
-
-void
-afs_nfs2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_GETATTR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_GETATTR].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_SETATTR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_SETATTR].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_LOOKUP, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else {
- (*afs_rfs_disp_tbl[RFS_LOOKUP].orig_proc) (args, xp, exp, rp, crp);
- if (afs_NFSRootOnly && call)
- afs_nfs2_smallfidder(xp);
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_READLINK, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_READLINK].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_read(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_READ, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_READ].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_write(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_WRITE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_WRITE].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_create(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_CREATE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else {
- (*afs_rfs_disp_tbl[RFS_CREATE].orig_proc) (args, xp, exp, rp, crp);
- if (afs_NFSRootOnly && call)
- afs_nfs2_smallfidder(xp);
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_remove(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_REMOVE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_REMOVE].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_rename(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_RENAME, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_RENAME].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_link(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_LINK, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_LINK].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_SYMLINK, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_SYMLINK].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_MKDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else {
- (*afs_rfs_disp_tbl[RFS_MKDIR].orig_proc) (args, xp, exp, rp, crp);
- if (afs_NFSRootOnly && call)
- afs_nfs2_smallfidder(xp);
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_RMDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_RMDIR].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_READDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_READDIR].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs2_statfs(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs2_dispatcher(0, RFS_STATFS, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_rfs_disp_tbl[RFS_STATFS].orig_proc) (args, xp, exp, rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
- {afs_nfs2_null},
- {afs_nfs2_getattr},
- {afs_nfs2_setattr},
- {afs_nfs2_root},
- {afs_nfs2_lookup},
- {afs_nfs2_readlink},
- {afs_nfs2_read},
- {afs_nfs2_writecache},
- {afs_nfs2_write},
- {afs_nfs2_create},
- {afs_nfs2_remove},
- {afs_nfs2_rename},
- {afs_nfs2_link},
- {afs_nfs2_symlink},
- {afs_nfs2_mkdir},
- {afs_nfs2_rmdir},
- {afs_nfs2_readdir},
- {afs_nfs2_statfs}
-};
-
-void
-afs_acl2_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs2_dispatcher(1, ACLPROC2_GETACL, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_acl_disp_tbl[ACLPROC2_GETACL].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_acl2_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs2_dispatcher(1, ACLPROC2_SETACL, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_acl_disp_tbl[ACLPROC2_SETACL].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_acl2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs2_dispatcher(1, ACLPROC2_GETATTR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_acl_disp_tbl[ACLPROC2_GETATTR].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_acl2_access(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs2_dispatcher(1, ACLPROC2_ACCESS, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
- else
- (*afs_acl_disp_tbl[ACLPROC2_ACCESS].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-struct afs_nfs_disp_tbl afs_acl_disp_tbl[5] = {
- {afs_nfs2_null},
- {afs_acl2_getacl},
- {afs_acl2_setacl},
- {afs_acl2_getattr},
- {afs_acl2_access}
-};
-
-/* Munge the dispatch tables to link us in first */
-void
-afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl,
- struct rfs_disp_tbl *_acl_tbl)
-{
- int i;
-
- if (xlatorinit_v2_done++)
- return;
-
- for (i = 0; i < RFS_NPROC; i++) {
- afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
- _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
- }
-
- for (i = 0; i < 5; i++) {
- afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
- _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
- }
-}
-
-#ifndef RFS3_NPROC
-#define RFS3_NPROC 22
-#endif
-
-#ifndef ACL3_NPROC
-#define ACL3_NPROC 3
-#endif
-
-struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
-struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
-
-struct afs_nfs3_resp {
- nfsstat3 status;
- bool_t flags;
-};
-typedef struct afs_nfs3_resp afs_nfs3_resp;
-
-static int
-is_afs_fh3(nfs_fh3 * fhp)
-{
- if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC)
- && (fhp->fh3_fsid.val[1] == AFS_VFSFSID))
- return 1;
- return 0;
-}
-
-void
-afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
-{
- resp->status = NFS3ERR_ACCES;
- resp->flags = FALSE;
-}
-
-afs_int32
-nfs3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp, nfs_fh3 ** fh2pp)
-{
- struct vnode *vp;
- nfs_fh3 *fhp1 = 0;
- nfs_fh3 *fhp2 = 0;
- int errorcode;
-
- afs_Trace1(afs_iclSetp, CM_TRACE_NFS3IN, ICL_TYPE_INT32, which);
- *fh2pp = (nfs_fh3 *) 0;
- switch (which) {
- case NFSPROC3_GETATTR:
- {
- GETATTR3args *arg = (GETATTR3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object;
- break;
- }
- case NFSPROC3_SETATTR:
- {
- SETATTR3args *arg = (SETATTR3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object;
- break;
- }
- case NFSPROC3_LOOKUP:
- {
- LOOKUP3args *arg = (LOOKUP3args *) args;
-#ifdef AFS_SUN58_ENV
- fhp1 = (nfs_fh3 *) arg->what.dirp;
-#else
- fhp1 = (nfs_fh3 *) & arg->what.dir;
-#endif
- break;
- }
- case NFSPROC3_ACCESS:
- {
- ACCESS3args *arg = (ACCESS3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object;
- break;
- }
- case NFSPROC3_READLINK:
- {
- READLINK3args *arg = (READLINK3args *) args;
- fhp1 = (nfs_fh3 *) & arg->symlink;
- break;
- }
- case NFSPROC3_READ:
- {
- READ3args *arg = (READ3args *) args;
- fhp1 = (nfs_fh3 *) & arg->file;
- break;
- }
- case NFSPROC3_WRITE:
- {
- WRITE3args *arg = (WRITE3args *) args;
- fhp1 = (nfs_fh3 *) & arg->file;
- break;
- }
- case NFSPROC3_CREATE:
- {
- CREATE3args *arg = (CREATE3args *) args;
- fhp1 = (nfs_fh3 *) & arg->where.dir;
- break;
- }
- case NFSPROC3_MKDIR:
- {
- MKDIR3args *arg = (MKDIR3args *) args;
- fhp1 = (nfs_fh3 *) & arg->where.dir;
- break;
- }
- case NFSPROC3_SYMLINK:
- {
- SYMLINK3args *arg = (SYMLINK3args *) args;
- fhp1 = (nfs_fh3 *) & arg->where.dir;
- break;
- }
- case NFSPROC3_MKNOD:
- {
- MKNOD3args *arg = (MKNOD3args *) args;
- fhp1 = (nfs_fh3 *) & arg->where.dir;
- break;
- }
- case NFSPROC3_REMOVE:
- {
- REMOVE3args *arg = (REMOVE3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object.dir;
- break;
- }
- case NFSPROC3_RMDIR:
- {
- RMDIR3args *arg = (RMDIR3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object.dir;
- break;
- }
- case NFSPROC3_RENAME:
- {
- RENAME3args *arg = (RENAME3args *) args;
- fhp1 = (nfs_fh3 *) & arg->from.dir;
- fhp2 = (nfs_fh3 *) & arg->to.dir;
- break;
- }
- case NFSPROC3_LINK:
- {
- LINK3args *arg = (LINK3args *) args;
- fhp1 = (nfs_fh3 *) & arg->file;
- fhp2 = (nfs_fh3 *) & arg->link.dir;
- break;
- }
- case NFSPROC3_READDIR:
- {
- READDIR3args *arg = (READDIR3args *) args;
- fhp1 = (nfs_fh3 *) & arg->dir;
- break;
- }
- case NFSPROC3_READDIRPLUS:
- {
- READDIRPLUS3args *arg = (READDIRPLUS3args *) args;
- fhp1 = (nfs_fh3 *) & arg->dir;
- break;
- }
- case NFSPROC3_FSSTAT:
- {
- FSSTAT3args *arg = (FSSTAT3args *) args;
- fhp1 = (nfs_fh3 *) & arg->fsroot;
- break;
- }
- case NFSPROC3_FSINFO:
- {
- FSINFO3args *arg = (FSINFO3args *) args;
- fhp1 = (nfs_fh3 *) & arg->fsroot;
- break;
- }
- case NFSPROC3_PATHCONF:
- {
- PATHCONF3args *arg = (PATHCONF3args *) args;
- fhp1 = (nfs_fh3 *) & arg->object;
- break;
- }
- case NFSPROC3_COMMIT:
- {
- COMMIT3args *arg = (COMMIT3args *) args;
- fhp1 = (nfs_fh3 *) & arg->file;
- break;
- }
- default:
- return NULL;
- }
-
- if (is_afs_fh3(fhp1)) {
- *fhpp = fhp1;
- if (fhp2)
- *fh2pp = fhp2;
- return 1;
- }
- if (fhp2 && is_afs_fh3(fhp2)) {
- *fhpp = fhp1;
- *fh2pp = fhp2;
- return 1;
- }
- return NULL;
-}
-
-afs_int32
-acl3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp)
-{
- nfs_fh3 *fhp;
-
- switch (which) {
- case ACLPROC3_GETACL:
- {
- struct GETACL3args *sargs = (struct GETACL3args *)args;
- fhp = &sargs->fh;
- break;
- }
- case ACLPROC3_SETACL:
- {
- struct SETACL3args *sargs = (struct SETACL3args *)args;
- fhp = &sargs->fh;
- break;
- }
- default:
- return NULL;
- }
-
- if (is_afs_fh3(fhp)) {
- *fhpp = fhp;
- return 1;
- }
-
- return NULL;
-}
-
-int
-afs_nfs3_dispatcher(int type, afs_int32 which, char *argp,
- struct exportinfo **expp, struct svc_req *rp,
- struct AFS_UCRED *crp)
-{
- afs_int32 call = 0;
- afs_int32 code = 0;
- afs_int32 client = 0;
- struct sockaddr *sa;
- nfs_fh3 *fh = (nfs_fh3 *) argp;
- nfs_fh3 *fh2 = (nfs_fh3 *) 0;
-
- if (!xlatorinit_v3_done)
- return 2;
-
- sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
- if (sa->sa_family == AF_INET)
- client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
-
- AFS_GLOCK();
- code = 0;
- switch (type) {
- case 0:
- code = (client && nfs3_to_afs_call(which, argp, &fh, &fh2));
- break;
- case 1:
- code = (client && acl3_to_afs_call(which, argp, &fh));
- break;
- default:
- break;
- }
-
- if (code) {
- struct afs_exporter *out = 0;
- afs_int32 dummy;
- static int once = 0;
- struct SmallFid Sfid;
-
- memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
-
- afs_Trace2(afs_iclSetp, CM_TRACE_NFS3IN1, ICL_TYPE_INT32, client,
- ICL_TYPE_FID, &Sfid);
-
- call = 1;
- if (!once && *expp) {
- afs_nobody = (*expp)->exi_export.ex_anon;
- once = 1;
- }
- code =
- afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
- &dummy, &out);
-
- if (!code && out)
- EXP_RELE(out);
-
-
- if (code == EINVAL)
- call = 2;
- }
-
- AFS_GUNLOCK();
- return call;
-}
-
-void
-afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
-{
- afs_int32 addr[2];
- struct vcache *vcp;
-
-#if defined(AFS_SUN57_64BIT_ENV)
- /* See also afs_fid() */
- memcpy((char *)addr, fhp->fh3_data, 10);
- addr[1] = (addr[1] >> 48) & 0xffff;
-#else
- memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
-#endif
-
- AFS_GLOCK();
- vcp = VTOAFS((struct vnode *)addr[0]);
-
- /* See also afs_osi_vget */
- if (addr[1] == AFS_XLATOR_MAGIC) {
- if (status == NFS_OK) {
- struct SmallFid Sfid;
- struct cell *tcell;
-
- /* Make up and copy out a SmallFid */
- tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
- Sfid.Volume = vcp->fid.Fid.Volume;
- Sfid.CellAndUnique =
- ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
- afs_PutCell(tcell, READ_LOCK);
- Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
- fhp->fh3_len = SIZEOF_SMALLFID;
- memcpy(fhp->fh3_data, (char *)&Sfid, fhp->fh3_len);
-
- afs_Trace3(afs_iclSetp, CM_TRACE_NFS3OUT, ICL_TYPE_INT32, status,
- ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
- }
-
- /* If we have a ref, release it */
- if (vcp->vrefCount >= 1)
- AFS_RELE(AFSTOV(vcp));
- }
- AFS_GUNLOCK();
-}
-
-void
-afs_nfs3_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_GETATTR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_GETATTR].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_SETATTR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_SETATTR].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_LOOKUP, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else {
- (*afs_rfs3_disp_tbl[NFSPROC3_LOOKUP].orig_proc) (args, xp, exp, rp,
- crp);
- if (afs_NFSRootOnly && call) {
- LOOKUP3res *resp = (LOOKUP3res *) xp;
- afs_nfs3_smallfidder(&resp->resok.object, resp->status);
- }
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_access(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_ACCESS, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_ACCESS].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_READLINK, (char *)args, &exp, rp,
- crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_READLINK].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_read(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs3_dispatcher(0, NFSPROC3_READ, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_READ].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_write(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_WRITE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_WRITE].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_create(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_CREATE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else {
- (*afs_rfs3_disp_tbl[NFSPROC3_CREATE].orig_proc) (args, xp, exp, rp,
- crp);
- if (afs_NFSRootOnly && call) {
- CREATE3res *resp = (CREATE3res *) xp;
- afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
- }
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_MKDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else {
- (*afs_rfs3_disp_tbl[NFSPROC3_MKDIR].orig_proc) (args, xp, exp, rp,
- crp);
- if (afs_NFSRootOnly && call) {
- MKDIR3res *resp = (MKDIR3res *) xp;
- afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
- }
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_SYMLINK, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else {
- (*afs_rfs3_disp_tbl[NFSPROC3_SYMLINK].orig_proc) (args, xp, exp, rp,
- crp);
- if (afs_NFSRootOnly && call) {
- SYMLINK3res *resp = (SYMLINK3res *) xp;
- afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
- }
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_mknod(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_MKNOD, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else {
- (*afs_rfs3_disp_tbl[NFSPROC3_MKNOD].orig_proc) (args, xp, exp, rp,
- crp);
- if (afs_NFSRootOnly && call) {
- MKNOD3res *resp = (MKNOD3res *) xp;
- afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
- }
- }
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_remove(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_REMOVE, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_REMOVE].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_RMDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_RMDIR].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_rename(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_RENAME, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_RENAME].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_link(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call = afs_nfs3_dispatcher(0, NFSPROC3_LINK, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_LINK].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_READDIR, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_READDIR].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_readdirplus(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_READDIRPLUS, (char *)args, &exp, rp,
- crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_READDIRPLUS].orig_proc) (args, xp, exp,
- rp, crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_fsstat(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_FSSTAT, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_FSSTAT].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_fsinfo(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_FSINFO, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_FSINFO].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_pathconf(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_PATHCONF, (char *)args, &exp, rp,
- crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_PATHCONF].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_nfs3_commit(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- afs_nfs3_resp dummy;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(0, NFSPROC3_COMMIT, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_rfs3_disp_tbl[NFSPROC3_COMMIT].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[22] = {
- {afs_nfs2_null},
- {afs_nfs3_getattr},
- {afs_nfs3_setattr},
- {afs_nfs3_lookup},
- {afs_nfs3_access},
- {afs_nfs3_readlink},
- {afs_nfs3_read},
- {afs_nfs3_write},
- {afs_nfs3_create},
- {afs_nfs3_mkdir},
- {afs_nfs3_symlink},
- {afs_nfs3_mknod},
- {afs_nfs3_remove},
- {afs_nfs3_rmdir},
- {afs_nfs3_rename},
- {afs_nfs3_link},
- {afs_nfs3_readdir},
- {afs_nfs3_readdirplus},
- {afs_nfs3_fsstat},
- {afs_nfs3_fsinfo},
- {afs_nfs3_pathconf},
- {afs_nfs3_commit}
-};
-
-void
-afs_acl3_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(1, ACLPROC3_GETACL, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_acl3_disp_tbl[ACLPROC3_GETACL].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-void
-afs_acl3_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
-{
- u_int call;
- struct cred *svcred = curthread->t_cred;
- curthread->t_cred = (struct cred *)crp;
- call =
- afs_nfs3_dispatcher(1, ACLPROC3_SETACL, (char *)args, &exp, rp, crp);
- if (call > 1)
- afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
- else
- (*afs_acl3_disp_tbl[ACLPROC3_SETACL].orig_proc) (args, xp, exp, rp,
- crp);
- curthread->t_cred = svcred;
- return;
-}
-
-struct afs_nfs_disp_tbl afs_acl3_disp_tbl[3] = {
- {afs_nfs2_null},
- {afs_acl3_getacl},
- {afs_acl3_setacl},
-};
-
-/* Munge the dispatch tables to link us in first */
-void
-afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl,
- struct rfs_disp_tbl *_acl_tbl)
-{
- int i;
-
- if (xlatorinit_v3_done++)
- return;
-
- for (i = 0; i < 22; i++) {
- afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
- _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
- }
-
- for (i = 0; i < 3; i++) {
- afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
- _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
- }
-}
-#endif /* !defined(AFS_NONFSTRANS) */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osi.c,v 1.44 2004/04/21 02:20:21 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#ifdef AFS_AIX_ENV
-#include <sys/adspace.h> /* for vm_att(), vm_det() */
-#endif
-
-static char memZero; /* address of 0 bytes for kmem_alloc */
-
-struct osimem {
- struct osimem *next;
-};
-
-/* osi_Init -- do once per kernel installation initialization.
- * -- On Solaris this is called from modload initialization.
- * -- On AIX called from afs_config.
- * -- On HP called from afsc_link.
- * -- On SGI called from afs_init. */
-
-#ifdef AFS_SGI53_ENV
-lock_t afs_event_lock;
-#endif
-
-#ifdef AFS_SGI64_ENV
-flid_t osi_flid;
-#endif
-
-struct AFS_UCRED *afs_osi_credp;
-
-void
-osi_Init(void)
-{
- static int once = 0;
- if (once++ > 0) /* just in case */
- return;
-#if defined(AFS_HPUX_ENV)
- osi_InitGlock();
-#else /* AFS_HPUX_ENV */
-#if defined(AFS_GLOBAL_SUNLOCK)
-#if defined(AFS_SGI62_ENV)
- mutex_init(&afs_global_lock, MUTEX_DEFAULT, "afs_global_lock");
-#elif defined(AFS_OSF_ENV)
- usimple_lock_init(&afs_global_lock);
- afs_global_owner = (thread_t) 0;
-#elif defined(AFS_FBSD50_ENV)
- mtx_init(&afs_global_mtx, "AFS global lock", NULL, MTX_DEF);
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- lockinit(&afs_global_lock, PLOCK, "afs global lock", 0, 0);
- afs_global_owner = 0;
-#elif defined(AFS_AIX41_ENV)
- lock_alloc((void *)&afs_global_lock, LOCK_ALLOC_PIN, 1, 1);
- simple_lock_init((void *)&afs_global_lock);
-#elif !defined(AFS_LINUX22_ENV)
- /* Linux initialization in osi directory. Should move the others. */
- mutex_init(&afs_global_lock, "afs_global_lock", MUTEX_DEFAULT, NULL);
-#endif
- /* afs_rxglobal_lock is initialized in rx_Init. */
-#endif /* AFS_GLOBAL_SUNLOCK */
-#endif /* AFS_HPUX_ENV */
-
- if (!afs_osicred_initialized) {
-#if defined(AFS_LINUX26_ENV)
- afs_osi_credp = crref();
-#elif defined(AFS_XBSD_ENV)
- /* Can't just invent one, must use crget() because of mutex */
- afs_osi_credp = crdup(osi_curcred());
-#else
- memset(&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
- crhold(&afs_osi_cred); /* don't let it evaporate */
- afs_osi_credp = &afs_osi_cred;
-#endif
- afs_osicred_initialized = 1;
- }
-#ifdef AFS_SGI64_ENV
- osi_flid.fl_pid = osi_flid.fl_sysid = 0;
-#endif
-
- init_et_to_sys_error();
-}
-
-int
-osi_Active(register struct vcache *avc)
-{
- AFS_STATCNT(osi_Active);
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || (AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if ((avc->opens > 0) || (avc->states & CMAPPED))
- return 1; /* XXX: Warning, verify this XXX */
-#elif defined(AFS_MACH_ENV)
- if (avc->opens > 0
- || ((avc->v.v_flag & VTEXT) && !inode_uncache_try(avc)))
- return 1;
-#elif defined(AFS_SGI_ENV)
- if ((avc->opens > 0) || AFS_VN_MAPPED(AFSTOV(avc)))
- return 1;
-#else
- if (avc->opens > 0 || (AFSTOV(avc)->v_flag & VTEXT))
- return (1);
-#endif
- return 0;
-}
-
-/* this call, unlike osi_FlushText, is supposed to discard caches that may
- contain invalid information if a file is written remotely, but that may
- contain valid information that needs to be written back if the file is
- being written locally. It doesn't subsume osi_FlushText, since the latter
- function may be needed to flush caches that are invalidated by local writes.
-
- avc->pvnLock is already held, avc->lock is guaranteed not to be held (by
- us, of course).
-*/
-void
-osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
-{
- afs_hyper_t origDV;
- ObtainReadLock(&avc->lock);
- /* If we've already purged this version, or if we're the ones
- * writing this version, don't flush it (could lose the
- * data we're writing). */
- if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0)
- || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
- ReleaseReadLock(&avc->lock);
- return;
- }
- ReleaseReadLock(&avc->lock);
- ObtainWriteLock(&avc->lock, 10);
- /* Check again */
- if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0)
- || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
- ReleaseWriteLock(&avc->lock);
- return;
- }
- if (hiszero(avc->mapDV)) {
- hset(avc->mapDV, avc->m.DataVersion);
- ReleaseWriteLock(&avc->lock);
- return;
- }
-
- AFS_STATCNT(osi_FlushPages);
- hset(origDV, avc->m.DataVersion);
- afs_Trace3(afs_iclSetp, CM_TRACE_FLUSHPAGES, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, origDV.low, ICL_TYPE_INT32, avc->m.Length);
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_VM_FlushPages(avc, credp);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 88);
-
- /* do this last, and to original version, since stores may occur
- * while executing above PUTPAGE call */
- hset(avc->mapDV, origDV);
- ReleaseWriteLock(&avc->lock);
-}
-
-afs_lock_t afs_ftf; /* flush text lock */
-
-#ifdef AFS_TEXT_ENV
-
-/* This call is supposed to flush all caches that might be invalidated
- * by either a local write operation or a write operation done on
- * another client. This call may be called repeatedly on the same
- * version of a file, even while a file is being written, so it
- * shouldn't do anything that would discard newly written data before
- * it is written to the file system. */
-
-void
-osi_FlushText_really(register struct vcache *vp)
-{
- afs_hyper_t fdv; /* version before which we'll flush */
-
- AFS_STATCNT(osi_FlushText);
- /* see if we've already flushed this data version */
- if (hcmp(vp->m.DataVersion, vp->flushDV) <= 0)
- return;
-
-#ifdef AFS_DEC_ENV
- {
- void afs_gfs_FlushText();
- afs_gfs_FlushText(vp);
- return;
- }
-#else
-
- MObtainWriteLock(&afs_ftf, 317);
- hset(fdv, vp->m.DataVersion);
-
- /* why this disgusting code below?
- * xuntext, called by xrele, doesn't notice when it is called
- * with a freed text object. Sun continually calls xrele or xuntext
- * without any locking, as long as VTEXT is set on the
- * corresponding vnode.
- * But, if the text object is locked when you check the VTEXT
- * flag, several processes can wait in xuntext, waiting for the
- * text lock; when the second one finally enters xuntext's
- * critical region, the text object is already free, but the check
- * was already done by xuntext's caller.
- * Even worse, it turns out that xalloc locks the text object
- * before reading or stating a file via the vnode layer. Thus, we
- * could end up in getdcache, being asked to bring in a new
- * version of a file, but the corresponding text object could be
- * locked. We can't flush the text object without causing
- * deadlock, so now we just don't try to lock the text object
- * unless it is guaranteed to work. And we try to flush the text
- * when we need to a bit more often at the vnode layer. Sun
- * really blew the vm-cache flushing interface.
- */
-
-#if defined (AFS_HPUX_ENV)
- if (vp->v.v_flag & VTEXT) {
- xrele(vp);
-
- if (vp->v.v_flag & VTEXT) { /* still has a text object? */
- MReleaseWriteLock(&afs_ftf);
- return;
- }
- }
-#endif
-
- /* next do the stuff that need not check for deadlock problems */
- mpurge(vp);
-
- /* finally, record that we've done it */
- hset(vp->flushDV, fdv);
- MReleaseWriteLock(&afs_ftf);
-
-#endif /* AFS_DEC_ENV */
-}
-
-#ifdef AFS_DEC_ENV
-/* I don't really like using xinval() here, because it kills processes
- * a bit aggressively. Previous incarnations of this functionality
- * used to use xrele() instead of xinval, and didn't invoke
- * cacheinval(). But they would panic. So it might be worth looking
- * into some middle ground...
- */
-static void
-afs_gfs_FlushText(register struct vcache *vp)
-{
- afs_hyper_t fdv; /* version before which we'll flush */
- register struct text *xp;
- struct gnode *gp;
-
- MObtainWriteLock(&afs_ftf, 318);
- hset(fdv, vp->m.DataVersion);
- gp = afs_vntogn(vp);
-
- if (!gp) {
- /* this happens frequently after cores are created. */
- MReleaseWriteLock(&afs_ftf);
- return;
- }
-
- if (gp->g_flag & GTEXT) {
- if (gp->g_textp) {
- xp = (struct text *)gp->g_textp;
- /* if text object is locked, give up */
- if (xp && (xp->x_flag & XLOCK)) {
- MReleaseWriteLock(&afs_ftf);
- return;
- }
- } else
- xp = NULL;
-
- if (gp->g_flag & GTEXT) { /* still has a text object? */
- xinval(gp);
- }
- }
-
- /* next do the stuff that need not check for deadlock problems */
- /* maybe xinval(gp); here instead of above */
- binval(NODEV, gp);
- cacheinval(gp);
- /* finally, record that we've done it */
- hset(vp->flushDV, fdv);
-
- MReleaseWriteLock(&afs_ftf);
-}
-#endif /* AFS_DEC_ENV */
-
-#endif /* AFS_TEXT_ENV */
-
-/* mask signals in afsds */
-void
-afs_osi_MaskSignals(void)
-{
-#ifdef AFS_LINUX22_ENV
- osi_linux_mask();
-#endif
-}
-
-/* unmask signals in rxk listener */
-void
-afs_osi_UnmaskRxkSignals(void)
-{
-}
-
-/* register rxk listener proc info */
-void
-afs_osi_RxkRegister(void)
-{
-#ifdef AFS_LINUX22_ENV
- osi_linux_rxkreg();
-#endif
-}
-
-/* procedure for making our processes as invisible as we can */
-void
-afs_osi_Invisible(void)
-{
-#ifdef AFS_LINUX22_ENV
- afs_osi_MaskSignals();
-#elif defined(AFS_DEC_ENV)
- u.u_procp->p_type |= SSYS;
-#elif defined(AFS_SUN5_ENV)
- curproc->p_flag |= SSYS;
-#elif defined(AFS_HPUX101_ENV) && !defined(AFS_HPUX1123_ENV)
- set_system_proc(u.u_procp);
-#elif defined(AFS_DARWIN_ENV)
- /* maybe call init_process instead? */
- current_proc()->p_flag |= P_SYSTEM;
-#elif defined(AFS_XBSD_ENV)
- curproc->p_flag |= P_SYSTEM;
-#elif defined(AFS_SGI_ENV)
- vrelvm();
-#endif
-
- AFS_STATCNT(osi_Invisible);
-}
-
-
-#if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
-/* set the real time */
-void
-afs_osi_SetTime(osi_timeval_t * atv)
-{
-#if defined(AFS_AIX32_ENV)
- struct timestruc_t t;
-
- t.tv_sec = atv->tv_sec;
- t.tv_nsec = atv->tv_usec * 1000;
- ksettimer(&t); /* Was -> settimer(TIMEOFDAY, &t); */
-#elif defined(AFS_SUN55_ENV)
- stime(atv->tv_sec);
-#elif defined(AFS_SUN5_ENV)
- /*
- * To get more than second resolution we can use adjtime. The problem
- * is that the usecs from the server are wrong (by now) so it isn't
- * worth complicating the following code.
- */
- struct stimea {
- time_t time;
- } sta;
-
- sta.time = atv->tv_sec;
-
- stime(&sta, NULL);
-#elif defined(AFS_SGI_ENV)
- struct stimea {
- sysarg_t time;
- } sta;
-
- AFS_GUNLOCK();
- sta.time = atv->tv_sec;
- stime(&sta);
- AFS_GLOCK();
-#elif defined(AFS_DARWIN_ENV)
- AFS_GUNLOCK();
- setthetime(atv);
- AFS_GLOCK();
-#else
- /* stolen from kern_time.c */
-#ifndef AFS_AUX_ENV
- boottime.tv_sec += atv->tv_sec - time.tv_sec;
-#endif
-#ifdef AFS_HPUX_ENV
- {
-#if !defined(AFS_HPUX1122_ENV)
- /* drop the setting of the clock for now. spl7 is not
- * known on hpux11.22
- */
- register ulong_t s;
- struct timeval t;
- t.tv_sec = atv->tv_sec;
- t.tv_usec = atv->tv_usec;
- s = spl7();
- time = t;
- (void)splx(s);
- resettodr(atv);
-#endif
- }
-#else
- {
- register int s;
- s = splclock();
- time = *atv;
- (void)splx(s);
- }
- resettodr();
-#endif
-#ifdef AFS_AUX_ENV
- logtchg(atv->tv_sec);
-#endif
-#endif /* AFS_DARWIN_ENV */
- AFS_STATCNT(osi_SetTime);
-}
-#endif /* AFS_LINUX20_ENV */
-
-
-void *
-afs_osi_Alloc(size_t x)
-{
- register struct osimem *tm = NULL;
- register int size;
-
- AFS_STATCNT(osi_Alloc);
- /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
- * things so that NULL returned iff an error occurred */
- if (x == 0)
- return &memZero;
-
- AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
- AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
-#ifdef AFS_LINUX20_ENV
- return osi_linux_alloc(x, 1);
-#elif defined(AFS_FBSD_ENV)
- return osi_fbsd_alloc(x, 1);
-#else
- size = x;
- tm = (struct osimem *)AFS_KALLOC(size);
-#ifdef AFS_SUN_ENV
- if (!tm)
- osi_Panic("osi_Alloc: Couldn't allocate %d bytes; out of memory!\n",
- size);
-#endif
- return (void *)tm;
-#endif
-}
-
-#if defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV)
-
-void *
-afs_osi_Alloc_NoSleep(size_t x)
-{
- register struct osimem *tm;
- register int size;
-
- AFS_STATCNT(osi_Alloc);
- /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
- * things so that NULL returned iff an error occurred */
- if (x == 0)
- return &memZero;
-
- size = x;
- AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
- AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
- tm = (struct osimem *)AFS_KALLOC_NOSLEEP(size);
- return (void *)tm;
-}
-
-#endif /* SUN || SGI */
-
-void
-afs_osi_Free(void *x, size_t asize)
-{
- AFS_STATCNT(osi_Free);
- if (x == &memZero)
- return; /* check for putting memZero back */
-
- AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
- AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
-#if defined(AFS_LINUX20_ENV)
- osi_linux_free(x);
-#elif defined(AFS_FBSD_ENV)
- osi_fbsd_free(x);
-#else
- AFS_KFREE((struct osimem *)x, asize);
-#endif
-}
-
-void
-afs_osi_FreeStr(char *x)
-{
- afs_osi_Free(x, strlen(x) + 1);
-}
-
-/* ? is it moderately likely that there are dirty VM pages associated with
- * this vnode?
- *
- * Prereqs: avc must be write-locked
- *
- * System Dependencies: - *must* support each type of system for which
- * memory mapped files are supported, even if all
- * it does is return TRUE;
- *
- * NB: this routine should err on the side of caution for ProcessFS to work
- * correctly (or at least, not to introduce worse bugs than already exist)
- */
-#ifdef notdef
-int
-osi_VMDirty_p(struct vcache *avc)
-{
- int dirtyPages;
-
- if (avc->execsOrWriters <= 0)
- return 0; /* can't be many dirty pages here, I guess */
-
-#if defined (AFS_AIX32_ENV)
-#ifdef notdef
- /* because of the level of hardware involvment with VM and all the
- * warnings about "This routine must be called at VMM interrupt
- * level", I thought it would be safest to disable interrupts while
- * looking at the software page fault table. */
-
- /* convert vm handle into index into array: I think that stoinio is
- * always zero... Look into this XXX */
-#define VMHASH(handle) ( \
- ( ((handle) & ~vmker.stoinio) \
- ^ ((((handle) & ~vmker.stoinio) & vmker.stoimask) << vmker.stoihash) \
- ) & 0x000fffff)
-
- if (avc->segid) {
- unsigned int pagef, pri, index, next;
-
- index = VMHASH(avc->segid);
- if (scb_valid(index)) { /* could almost be an ASSERT */
-
- pri = disable_ints();
- for (pagef = scb_sidlist(index); pagef >= 0; pagef = next) {
- next = pft_sidfwd(pagef);
- if (pft_modbit(pagef)) { /* has page frame been modified? */
- enable_ints(pri);
- return 1;
- }
- }
- enable_ints(pri);
- }
- }
-#undef VMHASH
-#endif
-#endif /* AFS_AIX32_ENV */
-
-#if defined (AFS_SUN_ENV)
- if (avc->states & CMAPPED) {
- struct page *pg;
- for (pg = avc->v.v_s.v_Pages; pg; pg = pg->p_vpnext) {
- if (pg->p_mod) {
- return 1;
- }
- }
- }
-#endif
- return 0;
-}
-#endif /* notdef */
-
-
-/*
- * Solaris osi_ReleaseVM should not drop and re-obtain the vcache entry lock.
- * This leads to bad races when osi_ReleaseVM() is called from
- * afs_InvalidateAllSegments().
-
- * We can do this because Solaris osi_VM_Truncate() doesn't care whether the
- * vcache entry lock is held or not.
- *
- * For other platforms, in some cases osi_VM_Truncate() doesn't care, but
- * there may be cases where it does care. If so, it would be good to fix
- * them so they don't care. Until then, we assume the worst.
- *
- * Locking: the vcache entry lock is held. It is dropped and re-obtained.
- */
-void
-osi_ReleaseVM(struct vcache *avc, struct AFS_UCRED *acred)
-{
-#ifdef AFS_SUN5_ENV
- AFS_GUNLOCK();
- osi_VM_Truncate(avc, 0, acred);
- AFS_GLOCK();
-#else
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- osi_VM_Truncate(avc, 0, acred);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 80);
-#endif
-}
-
-
-void
-shutdown_osi(void)
-{
- AFS_STATCNT(shutdown_osi);
- if (afs_cold_shutdown) {
- LOCK_INIT(&afs_ftf, "afs_ftf");
- }
-}
-
-#ifndef AFS_OBSD_ENV
-int
-afs_osi_suser(void *credp)
-{
-#if defined(AFS_SUN5_ENV)
- return afs_suser(credp);
-#else
- return afs_suser();
-#endif
-}
-#endif
-
-#if AFS_GCPAGS
-
-/* afs_osi_TraverseProcTable() - Walk through the systems process
- * table, calling afs_GCPAGs_perproc_func() for each process.
- */
-
-#if defined(AFS_SUN5_ENV)
-void
-afs_osi_TraverseProcTable(void)
-{
- struct proc *prp;
- for (prp = practive; prp != NULL; prp = prp->p_next) {
- afs_GCPAGs_perproc_func(prp);
- }
-}
-#endif
-
-#if defined(AFS_HPUX_ENV)
-
-/*
- * NOTE: h/proc_private.h gives the process table locking rules
- * It indicates that access to p_cred must be protected by
- * mp_mtproc_lock(p);
- * mp_mtproc_unlock(p);
- *
- * The code in sys/pm_prot.c uses pcred_lock() to protect access to
- * the process creds, and uses mp_mtproc_lock() only for audit-related
- * changes. To be safe, we use both.
- */
-
-void
-afs_osi_TraverseProcTable(void)
-{
- register proc_t *p;
- int endchain = 0;
-
- MP_SPINLOCK(activeproc_lock);
- MP_SPINLOCK(sched_lock);
- pcred_lock();
-
- /*
- * Instead of iterating through all of proc[], traverse only
- * the list of active processes. As an example of this,
- * see foreach_process() in sys/vm_sched.c.
- *
- * We hold the locks for the entire scan in order to get a
- * consistent view of the current set of creds.
- */
-
- for (p = proc; endchain == 0; p = &proc[p->p_fandx]) {
- if (p->p_fandx == 0) {
- endchain = 1;
- }
-
- if (system_proc(p))
- continue;
-
- mp_mtproc_lock(p);
- afs_GCPAGs_perproc_func(p);
- mp_mtproc_unlock(p);
- }
-
- pcred_unlock();
- MP_SPINUNLOCK(sched_lock);
- MP_SPINUNLOCK(activeproc_lock);
-}
-#endif
-
-#if defined(AFS_SGI_ENV)
-
-#ifdef AFS_SGI65_ENV
-/* TODO: Fix this later. */
-static int
-SGI_ProcScanFunc(void *p, void *arg, int mode)
-{
- return 0;
-}
-#else /* AFS_SGI65_ENV */
-static int
-SGI_ProcScanFunc(proc_t * p, void *arg, int mode)
-{
- afs_int32(*perproc_func) (struct proc *) = arg;
- int code = 0;
- /* we pass in the function pointer for arg,
- * mode ==0 for startup call, ==1 for each valid proc,
- * and ==2 for terminate call.
- */
- if (mode == 1) {
- code = perproc_func(p);
- }
- return code;
-}
-#endif /* AFS_SGI65_ENV */
-
-void
-afs_osi_TraverseProcTable(void)
-{
- procscan(SGI_ProcScanFunc, afs_GCPAGs_perproc_func);
-}
-#endif /* AFS_SGI_ENV */
-
-#if defined(AFS_AIX_ENV)
-#ifdef AFS_AIX51_ENV
-#define max_proc v.ve_proc
-#endif
-void
-afs_osi_TraverseProcTable(void)
-{
- struct proc *p;
- int i;
-
- /*
- * For binary compatibility, on AIX we need to be careful to use the
- * proper size of a struct proc, even if it is different from what
- * we were compiled with.
- */
- if (!afs_gcpags_procsize)
- return;
-
-#ifndef AFS_AIX51_ENV
- simple_lock(&proc_tbl_lock);
-#endif
- for (p = (struct proc *)v.vb_proc, i = 0; p < max_proc;
- p = (struct proc *)((char *)p + afs_gcpags_procsize), i++) {
-
-#ifdef AFS_AIX51_ENV
- if (p->p_pvprocp->pv_stat == SNONE)
- continue;
- if (p->p_pvprocp->pv_stat == SIDL)
- continue;
- if (p->p_pvprocp->pv_stat == SEXIT)
- continue;
-#else
- if (p->p_stat == SNONE)
- continue;
- if (p->p_stat == SIDL)
- continue;
- if (p->p_stat == SEXIT)
- continue;
-#endif
-
- /* sanity check */
-
- if (PROCMASK(p->p_pid) != i) {
- afs_gcpags = AFS_GCPAGS_EPIDCHECK;
- break;
- }
-
- /* sanity check */
-
- if ((p->p_nice < P_NICE_MIN) || (P_NICE_MAX < p->p_nice)) {
- afs_gcpags = AFS_GCPAGS_ENICECHECK;
- break;
- }
-
- afs_GCPAGs_perproc_func(p);
- }
-#ifndef AFS_AIX51_ENV
- simple_unlock(&proc_tbl_lock);
-#endif
-}
-#endif
-
-#if defined(AFS_OSF_ENV)
-void
-afs_osi_TraverseProcTable(void)
-{
- struct pid_entry *pe;
-#ifdef AFS_DUX50_ENV
-#define pidNPID (pidtab + npid)
-#define PID_LOCK()
-#define PID_UNLOCK()
-#endif
- PID_LOCK();
- for (pe = pidtab; pe < pidNPID; ++pe) {
- if (pe->pe_proc != PROC_NULL)
- afs_GCPAGs_perproc_func(pe->pe_proc);
- }
- PID_UNLOCK();
-}
-#endif
-
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-void
-afs_osi_TraverseProcTable(void)
-{
- struct proc *p;
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_stat == SIDL)
- continue;
- if (p->p_stat == SZOMB)
- continue;
- if (p->p_flag & P_SYSTEM)
- continue;
- afs_GCPAGs_perproc_func(p);
- }
-}
-#endif
-
-#if defined(AFS_LINUX22_ENV)
-void
-afs_osi_TraverseProcTable()
-{
- struct task_struct *p;
-
-#ifdef EXPORTED_TASKLIST_LOCK
- read_lock(&tasklist_lock);
-#endif
-#ifdef DEFINED_FOR_EACH_PROCESS
- for_each_process(p) if (p->pid) {
- if (p->state & TASK_ZOMBIE)
- continue;
- afs_GCPAGs_perproc_func(p);
- }
-#else
- for_each_task(p) if (p->pid) {
- if (p->state & TASK_ZOMBIE)
- continue;
- afs_GCPAGs_perproc_func(p);
- }
-#endif
-#ifdef EXPORTED_TASKLIST_LOCK
- read_unlock(&tasklist_lock);
-#endif
-}
-#endif
-
-/* return a pointer (sometimes a static copy ) to the cred for a
- * given AFS_PROC.
- * subsequent calls may overwrite the previously returned value.
- */
-
-#if defined(AFS_SGI65_ENV)
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * p)
-{
- return NULL;
-}
-#elif defined(AFS_HPUX_ENV)
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * p)
-{
- if (!p)
- return;
-
- /*
- * Cannot use afs_warnuser() here, as the code path
- * eventually wants to grab sched_lock, which is
- * already held here
- */
-
- return p_cred(p);
-}
-#elif defined(AFS_AIX_ENV)
-
-/* GLOBAL DECLARATIONS */
-
-/*
- * LOCKS: the caller must do
- * simple_lock(&proc_tbl_lock);
- * simple_unlock(&proc_tbl_lock);
- * around calls to this function.
- */
-
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * pproc)
-{
- struct AFS_UCRED *pcred = 0;
-
- /*
- * pointer to process user structure valid in *our*
- * address space
- *
- * The user structure for a process is stored in the user
- * address space (as distinct from the kernel address
- * space), and so to refer to the user structure of a
- * different process we must employ special measures.
- *
- * I followed the example used in the AIX getproc() system
- * call in bos/kernel/proc/getproc.c
- */
- struct user *xmem_userp;
-
- struct xmem dp; /* ptr to xmem descriptor */
- int xm; /* xmem result */
-
- if (!pproc) {
- return pcred;
- }
-
- /*
- * The process private segment in which the user
- * area is located may disappear. We need to increment
- * its use count. Therefore we
- * - get the proc_tbl_lock to hold the segment.
- * - get the p_lock to lockout vm_cleardata.
- * - vm_att to load the segment register (no check)
- * - xmattach to bump its use count.
- * - release the p_lock.
- * - release the proc_tbl_lock.
- * - do whatever we need.
- * - xmdetach to decrement the use count.
- * - vm_det to free the segment register (no check)
- */
-
- xmem_userp = NULL;
- xm = XMEM_FAIL;
- /* simple_lock(&proc_tbl_lock); */
-#ifdef __64BIT__
- if (pproc->p_adspace != vm_handle(NULLSEGID, (int32long64_t) 0)) {
-#else
- if (pproc->p_adspace != NULLSEGVAL) {
-#endif
-
-#ifdef AFS_AIX51_ENV
- simple_lock(&pproc->p_pvprocp->pv_lock);
-#else
- simple_lock(&pproc->p_lock);
-#endif
-
- if (pproc->p_threadcount &&
-#ifdef AFS_AIX51_ENV
- pproc->p_pvprocp->pv_threadlist) {
-#else
- pproc->p_threadlist) {
-#endif
-
- /*
- * arbitrarily pick the first thread in pproc
- */
- struct thread *pproc_thread =
-#ifdef AFS_AIX51_ENV
- pproc->p_pvprocp->pv_threadlist;
-#else
- pproc->p_threadlist;
-#endif
-
- /*
- * location of 'struct user' in pproc's
- * address space
- */
- struct user *pproc_userp = pproc_thread->t_userp;
-
- /*
- * create a pointer valid in my own address space
- */
-
- xmem_userp = (struct user *)vm_att(pproc->p_adspace, pproc_userp);
-
- dp.aspace_id = XMEM_INVAL;
- xm = xmattach(xmem_userp, sizeof(*xmem_userp), &dp, SYS_ADSPACE);
- }
-
-#ifdef AFS_AIX51_ENV
- simple_unlock(&pproc->p_pvprocp->pv_lock);
-#else
- simple_unlock(&pproc->p_lock);
-#endif
- }
- /* simple_unlock(&proc_tbl_lock); */
- if (xm == XMEM_SUCC) {
-
- static struct AFS_UCRED cred;
-
- /*
- * What locking should we use to protect access to the user
- * area? If needed also change the code in AIX/osi_groups.c.
- */
-
- /* copy cred to local address space */
- cred = *xmem_userp->U_cred;
- pcred = &cred;
-
- xmdetach(&dp);
- }
- if (xmem_userp) {
- vm_det((void *)xmem_userp);
- }
-
- return pcred;
-}
-
-#elif defined(AFS_OSF_ENV)
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * pr)
-{
- struct AFS_UCRED *rv = NULL;
-
- if (pr == NULL) {
- return NULL;
- }
-
- if ((pr->p_stat == SSLEEP) || (pr->p_stat == SRUN)
- || (pr->p_stat == SSTOP))
- rv = pr->p_rcred;
-
- return rv;
-}
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * pr)
-{
- struct AFS_UCRED *rv = NULL;
- static struct AFS_UCRED cr;
-
- if (pr == NULL) {
- return NULL;
- }
-
- if ((pr->p_stat == SSLEEP) || (pr->p_stat == SRUN)
- || (pr->p_stat == SSTOP)) {
- pcred_readlock(pr);
- cr.cr_ref = 1;
- cr.cr_uid = pr->p_cred->pc_ucred->cr_uid;
- cr.cr_ngroups = pr->p_cred->pc_ucred->cr_ngroups;
- memcpy(cr.cr_groups, pr->p_cred->pc_ucred->cr_groups,
- NGROUPS * sizeof(gid_t));
- pcred_unlock(pr);
- rv = &cr;
- }
-
- return rv;
-}
-#elif defined(AFS_LINUX22_ENV)
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * pr)
-{
- struct AFS_UCRED *rv = NULL;
- static struct AFS_UCRED cr;
-
- if (pr == NULL) {
- return NULL;
- }
-
- if ((pr->state == TASK_RUNNING) || (pr->state == TASK_INTERRUPTIBLE)
- || (pr->state == TASK_UNINTERRUPTIBLE)
- || (pr->state == TASK_STOPPED)) {
- cr.cr_ref = 1;
- cr.cr_uid = pr->uid;
-#if defined(AFS_LINUX26_ENV)
- get_group_info(pr->group_info);
- cr.cr_group_info = pr->group_info;
-#else
- cr.cr_ngroups = pr->ngroups;
- memcpy(cr.cr_groups, pr->groups, NGROUPS * sizeof(gid_t));
-#endif
- rv = &cr;
- }
-
- return rv;
-}
-#else
-const struct AFS_UCRED *
-afs_osi_proc2cred(AFS_PROC * pr)
-{
- struct AFS_UCRED *rv = NULL;
-
- if (pr == NULL) {
- return NULL;
- }
- rv = pr->p_cred;
-
- return rv;
-}
-#endif
-
-#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
- */
-
-#ifndef _AFS_OSI_
-#define _AFS_OSI_
-
-#include "h/types.h"
-#include "h/param.h"
-
-#ifdef AFS_FBSD50_ENV
-#include <sys/condvar.h>
-#endif
-
-#ifdef AFS_LINUX20_ENV
-#ifndef _LINUX_CODA_FS_I
-#define _LINUX_CODA_FS_I
-#define _CODA_HEADER_
-struct coda_inode_info {
-};
-#endif
-#ifndef _LINUX_XFS_FS_I
-#define _LINUX_XFS_FS_I
-struct xfs_inode_info {
-};
-#endif
-#include "h/fs.h"
-#include "h/mm.h"
-#endif
-
-
-/* this is just a dummy type decl, we're really using struct sockets here */
-struct osi_socket {
- int junk;
-};
-
-struct osi_stat {
- afs_int32 size; /* file size in bytes */
- afs_int32 blksize; /* optimal transfer size in bytes */
- afs_int32 mtime; /* modification date */
- afs_int32 atime; /* access time */
-};
-
-struct osi_file {
- afs_int32 size; /* file size in bytes XXX Must be first field XXX */
-#ifdef AFS_LINUX22_ENV
- struct dentry dentry; /* merely to hold the pointer to the inode. */
- struct file file; /* May need this if we really open the file. */
-#else
- struct vnode *vnode;
-#endif
-#if defined(AFS_HPUX102_ENV)
- k_off_t offset;
-#else
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- afs_offs_t offset;
-#else
- afs_int32 offset;
-#endif
-#endif
- int (*proc) (struct osi_file * afile, afs_int32 code); /* proc, which, if not null, is called on writes */
- char *rock; /* rock passed to proc */
- ino_t inum; /* guarantee validity of hint */
-#if defined(UKERNEL)
- int fd; /* file descriptor for user space files */
-#endif /* defined(UKERNEL) */
-};
-
-struct osi_dev {
-#if defined(AFS_XBSD_ENV)
- struct mount *mp;
- struct vnode *held_vnode;
-#elif defined(AFS_AIX42_ENV)
- dev_t dev;
-#else
- afs_int32 dev;
-#endif
-};
-
-struct afs_osi_WaitHandle {
-#ifdef AFS_FBSD50_ENV
- struct cv wh_condvar;
- int wh_inited; /* XXX */
-#else
- caddr_t proc; /* process waiting */
-#endif
-};
-
-#define osi_SetFileProc(x,p) ((x)->proc=(p))
-#define osi_SetFileRock(x,r) ((x)->rock=(r))
-#define osi_GetFileProc(x) ((x)->proc)
-#define osi_GetFileRock(x) ((x)->rock)
-
-#ifdef AFS_TEXT_ENV
-#define osi_FlushText(vp) if (hcmp((vp)->m.DataVersion, (vp)->flushDV) > 0) \
- osi_FlushText_really(vp)
-#else
-#define osi_FlushText(vp)
-#endif
-
-
-#define AFSOP_STOP_RXEVENT 214 /* stop rx event deamon */
-#define AFSOP_STOP_COMPLETE 215 /* afs has been shutdown */
-#define AFSOP_STOP_RXK_LISTENER 217 /* stop rx listener daemon */
-
-
-#define osi_NPACKETS 20 /* number of cluster pkts to alloc */
-
-/*
- * Alloc declarations.
- */
-#define afs_osi_Alloc_NoSleep afs_osi_Alloc
-
-/*
- * Vnode related macros
- */
-#ifndef AFS_OBSD_ENV
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-extern int (**afs_vnodeop_p) ();
-#define IsAfsVnode(vc) ((vc)->v_op == afs_vnodeop_p)
-#define SetAfsVnode(vc) (vc)->v_op = afs_vnodeop_p
-#else
-extern struct vnodeops *afs_ops;
-#define IsAfsVnode(vc) ((vc)->v_op == afs_ops)
-#define SetAfsVnode(vc) (vc)->v_op = afs_ops
-#endif
-#define vType(vc) (vc)->v.v_type
-#define vSetType(vc,type) (vc)->v.v_type = (type)
-#define vSetVfsp(vc,vfsp) (vc)->v.v_vfsp = (vfsp)
-#endif
-
-#ifdef AFS_SGI65_ENV
-#define gop_lookupname(fnamep,segflg,followlink,dirvpp,compvpp) \
- lookupname((fnamep),(segflg),(followlink),(dirvpp),(compvpp),\
- NULL)
-#else
-#ifndef AFS_OBSD_ENV
-#define gop_lookupname(fnamep,segflg,followlink,dirvpp,compvpp) \
- lookupname((fnamep),(segflg),(followlink),(dirvpp),(compvpp))
-#endif
-#endif
-
-/*
- * In IRIX 6.5 we cannot have DEBUG turned on since certain
- * system-defined structures are a different size with DEBUG on, the
- * kernel is compiled without DEBUG on, and the resulting differences
- * would break our ability to interact with the rest of the kernel.
- *
- * Is DEBUG only for turning the ASSERT() macro? If so, we should
- * be able to eliminate DEBUG entirely.
- */
-#if !defined(AFS_SGI65_ENV)
-#ifndef DEBUG
-#define DEBUG 1 /* Default is to enable debugging/logging */
-#endif
-#endif
-
-/*
- * Time related macros
- */
-#define osi_GetuTime(x) osi_GetTime(x)
-
-/* osi_timeval_t exists because SGI 6.x has two sizes of timeval. */
-/** In 64 bit Solaris the timeval structure has members that are 64 bit
- * In the GetTime() interface we expect pointers to afs_int32. So the need to
- * define osi_timeval_t to have 32 bit members. To make this less ambiguous
- * we now use 32 bit quantities consistently all over the code.
- * In 64 bit HP-UX the timeval structure has a 64 bit member.
- */
-
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_LINUX_64BIT_KERNEL) || (defined(AFS_SGI61_ENV) && defined(KERNEL) && defined(_K64U64))
-typedef struct {
- afs_int32 tv_sec;
- afs_int32 tv_usec;
-} osi_timeval_t;
-#else
-typedef struct timeval osi_timeval_t;
-#endif /* AFS_SGI61_ENV */
-
-/*
- * The following three routines provide the fid routines used by the buffer
- * and directory packages.
- */
-#define dirp_Zap(afid) (*(afid) = -1)
-#define dirp_Eq(afid, bfid) (*(afid) == *(bfid))
-#define dirp_Cpy(dfid,sfid) (*(dfid) = *(sfid))
-
-
-/*
- * osi_ThreadUnique() should yield a value that can be found in ps
- * output in order to draw correspondences between ICL traces and what
- * is going on in the system. So if ps cannot show thread IDs it is
- * likely to be the process ID instead.
- */
-#ifdef AFS_FBSD50_ENV
-/* should use curthread, but 'ps' can't display it */
-#define osi_ThreadUnique() curproc
-#else
-#define osi_ThreadUnique() getpid()
-#endif
-
-
-
-#ifdef AFS_GLOBAL_SUNLOCK
-#define AFS_ASSERT_GLOCK() \
- (ISAFS_GLOCK() || (osi_Panic("afs global lock not held at %s:%d\n", __FILE__, __LINE__), 0))
-#define AFS_ASSERT_RXGLOCK() \
- (ISAFS_RXGLOCK() || (osi_Panic("rx global lock not held at %s:%d\n", __FILE__, __LINE__), 0))
-#endif /* AFS_GLOBAL_SUNLOCK */
-
-#ifdef RX_ENABLE_LOCKS
-#define RX_AFS_GLOCK() AFS_GLOCK()
-#define RX_AFS_GUNLOCK() AFS_GUNLOCK()
-#else
-#define RX_AFS_GLOCK()
-#define RX_AFS_GUNLOCK()
-#endif
-
-
-
-#ifndef KERNEL
-#define AFS_GLOCK()
-#define AFS_GUNLOCK()
-#define ISAFS_GLOCK() 1
-#define AFS_ASSERT_GLOCK()
-#define AFS_RXGLOCK()
-#define AFS_RXGUNLOCK()
-#define ISAFS_RXGLOCK() 1
-#define AFS_ASSERT_RXGLOCK()
-#endif
-
-/* On an MP that uses multithreading, splnet is not sufficient to provide
- * mutual exclusion because the other processors will not see it. On some
- * early multiprocessors (SunOS413 & SGI5.2) splnet actually obtains a global
- * mutex, which this works in the UP expected way, it means that the whole MP
- * can only take one interrupt at a time; a serious performance penalty. */
-
-#if ((defined(AFS_GLOBAL_SUNLOCK) || defined(RX_ENABLE_LOCKS)) && !defined(AFS_HPUX_ENV)) || !defined(KERNEL)
-#define SPLVAR
-#define NETPRI
-#define USERPRI
-#endif
-
-/*
- * vnode/vcache ref count manipulation
- */
-#if defined(UKERNEL)
-#define AFS_RELE(vp) do { VN_RELE(vp); } while (0)
-#else /* defined(UKERNEL) */
-#define AFS_RELE(vp) do { AFS_GUNLOCK(); VN_RELE(vp); AFS_GLOCK(); } while (0)
-#endif /* defined(UKERNEL) */
-
-/*
- * For some reason we do bare refcount manipulation in some places, for some
- * platforms. The assumption is apparently that either we wouldn't call
- * afs_inactive anyway (because we know the ref count is high), or that it's
- * OK not to call it (because we don't expect CUnlinked or CDirty).
- * (Also, of course, the vnode is assumed to be one of ours. Can't use this
- * macro for V-file vnodes.)
- */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-/* Bare refcount manipulation would probably work on this platform, but just
- calling VREF does not */
-#define AFS_FAST_HOLD(vp) osi_vnhold((vp),0)
-#else
-#define AFS_FAST_HOLD(vp) VN_HOLD(&(vp)->v)
-#endif
-#define AFS_FAST_RELE(vp) AFS_RELE(AFSTOV(vp))
-
-/*
- * MP safe versions of routines to copy memory between user space
- * and kernel space. Call these to avoid taking page faults while
- * holding the global lock.
- */
-#ifdef AFS_GLOBAL_SUNLOCK
-
-#define AFS_COPYIN(SRC,DST,LEN,CODE) \
- do { \
- int haveGlock = ISAFS_GLOCK(); \
- if (haveGlock) \
- AFS_GUNLOCK(); \
- CODE = copyin((SRC),(DST),(LEN)); \
- if (haveGlock) \
- AFS_GLOCK(); \
- } while(0)
-
-#define AFS_COPYINSTR(SRC,DST,LEN,CNT,CODE) \
- do { \
- int haveGlock = ISAFS_GLOCK(); \
- if (haveGlock) \
- AFS_GUNLOCK(); \
- CODE = copyinstr((SRC),(DST),(LEN),(CNT)); \
- if (haveGlock) \
- AFS_GLOCK(); \
- } while(0)
-
-#define AFS_COPYOUT(SRC,DST,LEN,CODE) \
- do { \
- int haveGlock = ISAFS_GLOCK(); \
- if (haveGlock) \
- AFS_GUNLOCK(); \
- CODE = copyout((SRC),(DST),(LEN)); \
- if (haveGlock) \
- AFS_GLOCK(); \
- } while(0)
-
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#define AFS_UIOMOVE(SRC,LEN,RW,UIO,CODE) \
- do { \
- int haveGlock = ISAFS_GLOCK(); \
- if (haveGlock) \
- AFS_GUNLOCK(); \
- (UIO)->uio_rw = (RW); \
- CODE = uiomove((SRC),(LEN),(UIO)); \
- if (haveGlock) \
- AFS_GLOCK(); \
- } while(0)
-#else
-#define AFS_UIOMOVE(SRC,LEN,RW,UIO,CODE) \
- do { \
- int haveGlock = ISAFS_GLOCK(); \
- if (haveGlock) \
- AFS_GUNLOCK(); \
- CODE = uiomove((SRC),(LEN),(RW),(UIO)); \
- if (haveGlock) \
- AFS_GLOCK(); \
- } while(0)
-#endif
-
-#else /* AFS_GLOBAL_SUNLOCK */
-
-#define AFS_COPYIN(SRC,DST,LEN,CODE) \
- do { \
- CODE = copyin((SRC),(DST),(LEN)); \
- } while(0)
-
-#define AFS_COPYINSTR(SRC,DST,LEN,CNT,CODE) \
- do { \
- CODE = copyinstr((SRC),(DST),(LEN),(CNT)); \
- } while(0)
-
-#define AFS_COPYOUT(SRC,DST,LEN,CODE) \
- do { \
- CODE = copyout((SRC),(DST),(LEN)); \
- } while(0)
-
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#define AFS_UIOMOVE(SRC,LEN,RW,UIO,CODE) \
- do { \
- (UIO)->uio_rw = (RW); \
- CODE = uiomove((SRC),(LEN),(UIO)); \
- } while(0)
-#else /* AFS_OSF_ENV || AFS_FBSD_ENV */
-#define AFS_UIOMOVE(SRC,LEN,RW,UIO,CODE) \
- do { \
- CODE = uiomove((SRC),(LEN),(RW),(UIO)); \
- } while(0)
-#endif /* AFS_OSF_ENV || AFS_FBSD_ENV */
-
-#endif /* AFS_GLOBAL_SUNLOCK */
-
-/*
- * encapsulation of kernel data structure accesses
- */
-#define setuerror(erval) u.u_error = (erval)
-#define getuerror() u.u_error
-
-/* Macros for vcache/vnode and vfs arguments to vnode and vfs ops.
- * These are required for IRIX 6.4 and later, which pass behavior pointers.
- * Note that the _CONVERT routines get the ";" here so that argument lists
- * can have arguments after the OSI_x_CONVERT macro is called.
- */
-#define OSI_VN_ARG(V) V
-#define OSI_VN_DECL(V) struct vnode *V
-#define OSI_VN_CONVERT(V)
-#define OSI_VC_ARG(V) V
-#define OSI_VC_DECL(V) struct vcache *V
-#define OSI_VC_CONVERT(V)
-#define OSI_VFS_ARG(V) V
-#define OSI_VFS_DECL(V) struct vfs *V
-#define OSI_VFS_CONVERT(V)
-
-
-/*
-** Macro for Solaris 2.6 returns 1 if file is larger than 2GB; else returns 0
-*/
-#define AfsLargeFileUio(uio) 0
-#define AfsLargeFileSize(pos, off) 0
-
-/* Now include system specific OSI header file. It will redefine macros
- * defined here as required by the OS.
- */
-#include "osi_machdep.h"
-
-/* Declare any structures which use these macros after the OSI implementation
- * has had the opportunity to redefine them.
- */
-extern struct AFS_UCRED afs_osi_cred, *afs_osi_credp;
-
-#ifndef osi_curcred
-#define osi_curcred() (u.u_cred)
-#endif
-
-#endif /* _AFS_OSI_ */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osi_alloc.c,v 1.10 2004/03/10 23:01:51 rees Exp $");
-
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#ifndef AFS_FBSD_ENV
-#ifdef AFS_AIX41_ENV
-#include "sys/lockl.h"
-#include "sys/sleep.h"
-#include "sys/syspest.h"
-#include "sys/lock_def.h"
-/*lock_t osi_fsplock = LOCK_AVAIL;*/
-#else
-afs_lock_t osi_fsplock;
-#endif
-
-
-
-static struct osi_packet {
- struct osi_packet *next;
-} *freePacketList = NULL, *freeSmallList;
-afs_lock_t osi_flplock;
-
-
-afs_int32 afs_preallocs = 512; /* Reserve space for all small allocs! */
-void
-osi_AllocMoreSSpace(register afs_int32 preallocs)
-{
- register int i;
- char *p;
-
- p = (char *)afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
-#ifdef KERNEL_HAVE_PIN
- pin(p, AFS_SMALLOCSIZ * preallocs); /* XXXX */
-#endif
- for (i = 0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
-#ifdef AFS_AIX32_ENV
- *p = '\0'; /* page fault it in. */
-#endif
- osi_FreeSmallSpace((char *)p);
- }
- afs_stats_cmperf.SmallBlocksAlloced += preallocs;
- afs_stats_cmperf.SmallBlocksActive += preallocs;
-}
-
-
-
-/* free space allocated by AllocLargeSpace. Also called by mclput when freeing
- * a packet allocated by osi_NetReceive. */
-
-void
-osi_FreeLargeSpace(void *adata)
-{
-
- AFS_ASSERT_GLOCK();
-
- AFS_STATCNT(osi_FreeLargeSpace);
- afs_stats_cmperf.LargeBlocksActive--;
- MObtainWriteLock(&osi_flplock, 322);
- ((struct osi_packet *)adata)->next = freePacketList;
- freePacketList = adata;
- MReleaseWriteLock(&osi_flplock);
-}
-
-void
-osi_FreeSmallSpace(void *adata)
-{
-
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- AFS_ASSERT_GLOCK();
-
- AFS_STATCNT(osi_FreeSmallSpace);
- afs_stats_cmperf.SmallBlocksActive--;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
-#else
- MObtainWriteLock(&osi_fsplock, 323);
-#endif
- ((struct osi_packet *)adata)->next = freeSmallList;
- freeSmallList = adata;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- splx(x); /*unlockl(&osi_fsplock); */
-#else
- MReleaseWriteLock(&osi_fsplock);
-#endif
-}
-
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-static struct osi_packet *freeMediumList;
-
-osi_AllocMoreMSpace(register afs_int32 preallocs)
-{
- register int i;
- char *p;
-
- p = (char *)afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
-#ifdef KERNEL_HAVE_PIN
- pin(p, AFS_MDALLOCSIZ * preallocs); /* XXXX */
-#endif
- for (i = 0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
-#ifdef AFS_AIX32_ENV
- *p = '\0'; /* page fault it in. */
-#endif
- osi_FreeMediumSpace((char *)p);
- }
- afs_stats_cmperf.MediumBlocksAlloced += preallocs;
- afs_stats_cmperf.MediumBlocksActive += preallocs;
-}
-
-
-void *
-osi_AllocMediumSpace(size_t size)
-{
- register struct osi_packet *tp;
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- afs_stats_cmperf.MediumBlocksActive++;
- retry:
- x = splnet();
- tp = freeMediumList;
- if (tp)
- freeMediumList = tp->next;
- splx(x);
- if (!tp) {
- osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER);
- goto retry;
- }
- return tp;
-}
-
-void
-osi_FreeMediumSpace(void *adata)
-{
-
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- afs_stats_cmperf.MediumBlocksActive--;
- x = splnet();
- ((struct osi_packet *)adata)->next = freeMediumList;
- freeMediumList = adata;
- splx(x);
-}
-#endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
-
-
-/* allocate space for sender */
-void *
-osi_AllocLargeSpace(size_t size)
-{
- register struct osi_packet *tp;
-
- AFS_ASSERT_GLOCK();
-
- AFS_STATCNT(osi_AllocLargeSpace);
- if (size > AFS_LRALLOCSIZ)
- osi_Panic("osi_AllocLargeSpace: size=%d\n", size);
- afs_stats_cmperf.LargeBlocksActive++;
- if (!freePacketList) {
- char *p;
-
- afs_stats_cmperf.LargeBlocksAlloced++;
- p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
-#ifdef KERNEL_HAVE_PIN
- /*
- * Need to pin this memory since under heavy conditions this memory
- * could be swapped out; the problem is that we could inside rx where
- * interrupts are disabled and thus we would panic if we don't pin it.
- */
- pin(p, AFS_LRALLOCSIZ);
-#endif
- return p;
- }
- MObtainWriteLock(&osi_flplock, 324);
- tp = freePacketList;
- if (tp)
- freePacketList = tp->next;
- MReleaseWriteLock(&osi_flplock);
- return (char *)tp;
-}
-
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-/*
- * XXX We could have used a macro around osi_AllocSmallSpace but it's
- * probably better like this so that we can remove this at some point.
- */
-/* morespace 1 - means we called at splnet level */
-char *
-osi_AllocSmall(register afs_int32 size, register afs_int32 morespace)
-{
- register struct osi_packet *tp;
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- AFS_ASSERT_GLOCK();
-
- AFS_STATCNT(osi_AllocSmallSpace);
- if (size > AFS_SMALLOCSIZ)
- osi_Panic("osi_AllocSmall, size=%d", size);
- if ((!morespace
- &&
- ((afs_stats_cmperf.SmallBlocksAlloced -
- afs_stats_cmperf.SmallBlocksActive)
- <= AFS_SALLOC_LOW_WATER))
- || !freeSmallList) {
- osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
- }
- afs_stats_cmperf.SmallBlocksActive++;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
-#else
- MObtainWriteLock(&osi_fsplock, 325);
-#endif
- tp = freeSmallList;
- if (tp)
- freeSmallList = tp->next;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- splx(x); /*unlockl(&osi_fsplock); */
-#else
- MReleaseWriteLock(&osi_fsplock);
-#endif
-
- return (char *)tp;
-}
-
-int
-osi_FreeSmall(register struct osi_packet *adata)
-{
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- AFS_STATCNT(osi_FreeSmallSpace);
- afs_stats_cmperf.SmallBlocksActive--;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
-#else
- MObtainWriteLock(&osi_fsplock, 326);
-#endif
- adata->next = freeSmallList;
- freeSmallList = adata;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- splx(x); /*unlockl(&osi_fsplock); */
-#else
- MReleaseWriteLock(&osi_fsplock);
-#endif
- return 0;
-}
-#endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
-
-/* allocate space for sender */
-void *
-osi_AllocSmallSpace(size_t size)
-{
- register struct osi_packet *tp;
-#if defined(AFS_AIX32_ENV)
- int x;
-#endif
-#if defined(AFS_HPUX_ENV)
- ulong_t x;
-#endif
-
- AFS_STATCNT(osi_AllocSmallSpace);
- if (size > AFS_SMALLOCSIZ)
- osi_Panic("osi_AllocSmallS: size=%d\n", size);
-
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- /*
- * We're running out of free blocks (< 50); get some more ourselves so that
- * when we don't run out of them when called under splnet() (from rx);
- */
- if (((afs_stats_cmperf.SmallBlocksAlloced -
- afs_stats_cmperf.SmallBlocksActive)
- <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
- osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
- }
-#else
- if (!freeSmallList) {
- afs_stats_cmperf.SmallBlocksAlloced++;
- afs_stats_cmperf.SmallBlocksActive++;
- return afs_osi_Alloc(AFS_SMALLOCSIZ);
- }
-#endif
- afs_stats_cmperf.SmallBlocksActive++;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
-#else
- MObtainWriteLock(&osi_fsplock, 327);
-#endif
- tp = freeSmallList;
- if (tp)
- freeSmallList = tp->next;
-#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
- splx(x); /*unlockl(&osi_fsplock); */
-#else
- MReleaseWriteLock(&osi_fsplock);
-#endif
- return (char *)tp;
-}
-
-
-
-void
-shutdown_osinet(void)
-{
- extern int afs_cold_shutdown;
-
- AFS_STATCNT(shutdown_osinet);
- if (afs_cold_shutdown) {
- struct osi_packet *tp;
-
- while ((tp = freePacketList)) {
- freePacketList = tp->next;
- afs_osi_Free(tp, AFS_LRALLOCSIZ);
-#ifdef KERNEL_HAVE_PIN
- unpin(tp, AFS_LRALLOCSIZ);
-#endif
- }
-
- while ((tp = freeSmallList)) {
- freeSmallList = tp->next;
- afs_osi_Free(tp, AFS_SMALLOCSIZ);
-#ifdef KERNEL_HAVE_PIN
- unpin(tp, AFS_SMALLOCSIZ);
-#endif
- }
- afs_preallocs = 512;
-#ifndef AFS_AIX32_ENV
- LOCK_INIT(&osi_fsplock, "osi_fsplock");
-#endif
- LOCK_INIT(&osi_flplock, "osi_flplock");
- }
-}
-#endif
+++ /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
- */
-
-/*
- * Implements:
- * genpag
- * getpag
- * afs_setpag
- * AddPag
- * afs_InitReq
- * afs_get_pag_from_groups
- * afs_get_groups_from_pag
- * PagInCred
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osi_pag.c,v 1.20 2004/04/21 02:20:21 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-/* Imported variables */
-extern int afs_shuttingdown;
-
-/* Exported variables */
-afs_uint32 pag_epoch;
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
-afs_uint32 pagCounter = 1;
-#else
-afs_uint32 pagCounter = 0;
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
-
-/* Local variables */
-
-/*
- * Pags are implemented as follows: the set of groups whose long
- * representation is '41XXXXXX' hex are used to represent the pags.
- * Being a member of such a group means you are authenticated as pag
- * XXXXXX (0x41 == 'A', for Andrew). You are never authenticated as
- * multiple pags at once.
- *
- * The function afs_InitReq takes a credential field and formats the
- * corresponding venus request structure. The uid field in the
- * vrequest structure is set to the *pag* you are authenticated as, or
- * the uid, if you aren't authenticated with a pag.
- *
- * The basic motivation behind pags is this: just because your unix
- * uid is N doesn't mean that you should have the same privileges as
- * anyone logged in on the machine as user N, since this would enable
- * the superuser on the machine to sneak in and make use of anyone's
- * authentication info, even that which is only accidentally left
- * behind when someone leaves a public workstation.
- *
- * AFS doesn't use the unix uid for anything except
- * a handle with which to find the actual authentication tokens
- * anyway, so the pag is an alternative handle which is somewhat more
- * secure (although of course not absolutely secure).
-*/
-#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
-afs_uint32
-genpag(void)
-{
- AFS_STATCNT(genpag);
-#ifdef AFS_LINUX20_ENV
- /* Ensure unique PAG's (mod 200 days) when reloading the client. */
- return (('A' << 24) + ((pag_epoch + pagCounter++) & 0xffffff));
-#else /* AFS_LINUX20_ENV */
- return (('A' << 24) + (pagCounter++ & 0xffffff));
-#endif /* AFS_LINUX20_ENV */
-}
-
-afs_uint32
-getpag(void)
-{
- AFS_STATCNT(getpag);
-#ifdef AFS_LINUX20_ENV
- /* Ensure unique PAG's (mod 200 days) when reloading the client. */
- return (('A' << 24) + ((pag_epoch + pagCounter) & 0xffffff));
-#else
- return (('A' << 24) + (pagCounter & 0xffffff));
-#endif
-}
-
-#else
-
-/* Web enhancement: we don't need to restrict pags to 41XXXXXX since
- * we are not sharing the space with anyone. So we use the full 32 bits. */
-
-afs_uint32
-genpag(void)
-{
- AFS_STATCNT(genpag);
-#ifdef AFS_LINUX20_ENV
- return (pag_epoch + pagCounter++);
-#else
- return (pagCounter++);
-#endif /* AFS_LINUX20_ENV */
-}
-
-afs_uint32
-getpag(void)
-{
- AFS_STATCNT(getpag);
-#ifdef AFS_LINUX20_ENV
- /* Ensure unique PAG's (mod 200 days) when reloading the client. */
- return (pag_epoch + pagCounter);
-#else
- return (pagCounter);
-#endif
-}
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
-
-/* used to require 10 seconds between each setpag to guarantee that
- * PAGs never wrap - which would be a security hole. If we presume
- * that in ordinary operation, the average rate of PAG allocation
- * will not exceed one per second, the 24 bits provided will be
- * sufficient for ~200 days. Unfortunately, if we merely assume that,
- * there will be an opportunity for attack. So we must enforce it.
- * If we need to increase the average rate of PAG allocation, we
- * should increase the number of bits in a PAG, and/or reduce our
- * window in which we guarantee that the PAG counter won't wrap.
- * By permitting an average of one new PAG per second, new PAGs can
- * be allocated VERY frequently over a short period relative to total uptime.
- * Of course, there's only an issue here if one user stays logged (and re-
- * activates tokens repeatedly) for that entire period.
- */
-
-int
-#if defined(AFS_SUN5_ENV)
-afs_setpag(struct AFS_UCRED **credpp)
-#elif defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_setpag(struct proc *p, void *args, int *retval)
-#else
-afs_setpag(void)
-#endif
-{
- int code = 0;
-
-#if defined(AFS_SGI53_ENV) && defined(MP)
- /* This is our first chance to get the global lock. */
- AFS_GLOCK();
-#endif /* defined(AFS_SGI53_ENV) && defined(MP) */
-
- AFS_STATCNT(afs_setpag);
-#if defined(AFS_SUN5_ENV)
- if (!afs_suser(*credpp))
-#elif defined(AFS_OBSD_ENV)
- if (!afs_osi_suser(p->p_ucred))
-#else
- if (!afs_suser())
-#endif
- {
- while (osi_Time() - pag_epoch < pagCounter) {
- afs_osi_Wait(1000, (struct afs_osi_WaitHandle *)0, 0);
- }
- }
-#if defined(AFS_SUN5_ENV)
- code = AddPag(genpag(), credpp);
-#elif defined(AFS_OSF_ENV) || defined(AFS_XBSD_ENV)
- code = AddPag(p, genpag(), &p->p_rcred);
-#elif defined(AFS_AIX41_ENV)
- {
- struct ucred *credp;
- struct ucred *credp0;
-
- credp = crref();
- credp0 = credp;
- code = AddPag(genpag(), &credp);
- /* If AddPag() didn't make a new cred, then free our cred ref */
- if (credp == credp0) {
- crfree(credp);
- }
- }
-#elif defined(AFS_HPUX110_ENV)
- {
- struct ucred *credp = p_cred(u.u_procp);
- code = AddPag(genpag(), &credp);
- }
-#elif defined(AFS_SGI_ENV)
- {
- cred_t *credp;
- credp = OSI_GET_CURRENT_CRED();
- code = AddPag(genpag(), &credp);
- }
-#elif defined(AFS_LINUX20_ENV)
- {
- struct AFS_UCRED *credp = crref();
- code = AddPag(genpag(), &credp);
- crfree(credp);
- }
-#elif defined(AFS_DARWIN_ENV)
- {
- struct ucred *credp = crdup(p->p_cred->pc_ucred);
- code = AddPag(p, genpag(), &credp);
- crfree(credp);
- }
-#else
- code = AddPag(genpag(), &u.u_cred);
-#endif
-
- afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
-#if defined(KERNEL_HAVE_UERROR)
- if (!getuerror())
- setuerror(code);
-#endif
-#if defined(AFS_SGI53_ENV) && defined(MP)
- AFS_GUNLOCK();
-#endif /* defined(AFS_SGI53_ENV) && defined(MP) */
- return (code);
-}
-
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
-/*
- * afs_setpag_val
- * This function is like setpag but sets the current thread's pag id to a
- * caller-provided value instead of calling genpag(). This implements a
- * form of token caching since the caller can recall a particular pag value
- * for the thread to restore tokens, rather than reauthenticating.
- */
-int
-#if defined(AFS_SUN5_ENV)
-afs_setpag_val(struct AFS_UCRED **credpp, int pagval)
-#elif defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_setpag_val(struct proc *p, void *args, int *retval, int pagval)
-#else
-afs_setpag_val(int pagval)
-#endif
-{
- int code = 0;
-
-#if defined(AFS_SGI53_ENV) && defined(MP)
- /* This is our first chance to get the global lock. */
- AFS_GLOCK();
-#endif /* defined(AFS_SGI53_ENV) && defined(MP) */
-
- AFS_STATCNT(afs_setpag);
-#ifdef AFS_SUN5_ENV
- if (!afs_suser(*credpp))
-#else
- if (!afs_suser())
-#endif
- {
- while (osi_Time() - pag_epoch < pagCounter) {
- afs_osi_Wait(1000, (struct afs_osi_WaitHandle *)0, 0);
- }
- }
-#if defined(AFS_SUN5_ENV)
- code = AddPag(pagval, credpp);
-#elif defined(AFS_OSF_ENV) || defined(AFS_XBSD_ENV)
- code = AddPag(p, pagval, &p->p_rcred);
-#elif defined(AFS_AIX41_ENV)
- {
- struct ucred *credp;
- struct ucred *credp0;
-
- credp = crref();
- credp0 = credp;
- code = AddPag(pagval, &credp);
- /* If AddPag() didn't make a new cred, then free our cred ref */
- if (credp == credp0) {
- crfree(credp);
- }
- }
-#elif defined(AFS_HPUX110_ENV)
- {
- struct ucred *credp = p_cred(u.u_procp);
- code = AddPag(pagval, &credp);
- }
-#elif defined(AFS_SGI_ENV)
- {
- cred_t *credp;
- credp = OSI_GET_CURRENT_CRED();
- code = AddPag(pagval, &credp);
- }
-#elif defined(AFS_LINUX20_ENV)
- {
- struct AFS_UCRED *credp = crref();
- code = AddPag(pagval, &credp);
- crfree(credp);
- }
-#elif defined(AFS_DARWIN_ENV)
- {
- struct ucred *credp = crdup(p->p_cred->pc_ucred);
- code = AddPag(p, pagval, &credp);
- crfree(credp);
- }
-#else
- code = AddPag(pagval, &u.u_cred);
-#endif
-
- afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
-#if defined(KERNEL_HAVE_UERROR)
- if (!getuerror())
- setuerror(code);
-#endif
-#if defined(AFS_SGI53_ENV) && defined(MP)
- AFS_GUNLOCK();
-#endif /* defined(AFS_SGI53_ENV) && defined(MP) */
- return (code);
-}
-
-int
-afs_getpag_val()
-{
- int pagvalue;
- struct AFS_UCRED *credp = u.u_cred;
- int gidset0, gidset1;
-
- gidset0 = credp->cr_groups[0];
- gidset1 = credp->cr_groups[1];
- pagvalue = afs_get_pag_from_groups(gidset0, gidset1);
- return pagvalue;
-}
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
-
-
-/* Note - needs to be available on AIX, others can be static - rework this */
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-int
-AddPag(struct proc *p, afs_int32 aval, struct AFS_UCRED **credpp)
-#else
-int
-AddPag(afs_int32 aval, struct AFS_UCRED **credpp)
-#endif
-{
- afs_int32 newpag, code;
-
- AFS_STATCNT(AddPag);
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if ((code = setpag(p, credpp, aval, &newpag, 0)))
-#else
- if ((code = setpag(credpp, aval, &newpag, 0)))
-#endif
-#if defined(KERNEL_HAVE_UERROR)
- return (setuerror(code), code);
-#else
- return (code);
-#endif
- return 0;
-}
-
-
-int
-afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred)
-{
- AFS_STATCNT(afs_InitReq);
- if (afs_shuttingdown)
- return EIO;
- av->uid = PagInCred(acred);
- if (av->uid == NOPAG) {
- /* Afs doesn't use the unix uid for anuthing except a handle
- * with which to find the actual authentication tokens so I
- * think it's ok to use the real uid to make setuid
- * programs (without setpag) to work properly.
- */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if (acred == NOCRED)
- av->uid = -2; /* XXX nobody... ? */
- else
- av->uid = acred->cr_uid; /* bsd creds don't have ruid */
-#else
- av->uid = acred->cr_ruid; /* default when no pag is set */
-#endif
- }
- av->initd = 0;
- return 0;
-}
-
-
-
-afs_uint32
-afs_get_pag_from_groups(gid_t g0a, gid_t g1a)
-{
- afs_uint32 g0 = g0a;
- afs_uint32 g1 = g1a;
- afs_uint32 h, l, ret;
-
- AFS_STATCNT(afs_get_pag_from_groups);
- g0 -= 0x3f00;
- g1 -= 0x3f00;
- if (g0 < 0xc000 && g1 < 0xc000) {
- l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
- h = (g0 >> 14);
- h = (g1 >> 14) + h + h + h;
- ret = ((h << 28) | l);
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
- return ret;
-#else
- /* Additional testing */
- if (((ret >> 24) & 0xff) == 'A')
- return ret;
- else
- return NOPAG;
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
- }
- return NOPAG;
-}
-
-
-void
-afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p)
-{
- unsigned short g0, g1;
-
-
- AFS_STATCNT(afs_get_groups_from_pag);
-#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
- pag &= 0x7fffffff;
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
- g0 = 0x3fff & (pag >> 14);
- g1 = 0x3fff & pag;
- g0 |= ((pag >> 28) / 3) << 14;
- g1 |= ((pag >> 28) % 3) << 14;
- *g0p = g0 + 0x3f00;
- *g1p = g1 + 0x3f00;
-}
-
-
-afs_int32
-PagInCred(const struct AFS_UCRED *cred)
-{
- afs_int32 pag;
- gid_t g0, g1;
-
- AFS_STATCNT(PagInCred);
- if (cred == NULL) {
- return NOPAG;
- }
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- if (cred == NOCRED || cred == FSCRED) {
- return NOPAG;
- }
- if (cred->cr_ngroups < 3)
- return NOPAG;
- /* gid is stored in cr_groups[0] */
- g0 = cred->cr_groups[1];
- g1 = cred->cr_groups[2];
-#else
-#if defined(AFS_AIX51_ENV)
- if (kcred_getpag(cred, PAG_AFS, &pag) < 0 || pag == 0)
- pag = NOPAG;
- return pag;
-#elif defined(AFS_AIX_ENV)
- if (cred->cr_ngrps < 2) {
- return NOPAG;
- }
-#elif defined(AFS_LINUX26_ENV)
- if (cred->cr_group_info->ngroups < 2)
- return NOPAG;
-#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DUX40_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
- if (cred->cr_ngroups < 2)
- return NOPAG;
-#endif
-#if defined(AFS_AIX51_ENV)
- g0 = cred->cr_groupset.gs_union.un_groups[0];
- g1 = cred->cr_groupset.gs_union.un_groups[1];
-#elif defined(AFS_LINUX26_ENV)
- g0 = GROUP_AT(cred->cr_group_info, 0);
- g1 = GROUP_AT(cred->cr_group_info, 1);
-#else
- g0 = cred->cr_groups[0];
- g1 = cred->cr_groups[1];
-#endif
-#endif
- pag = (afs_int32) afs_get_pag_from_groups(g0, g1);
- return pag;
-}
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osi_uio.c,v 1.8 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/nfsclient.h"
-#include "afs/afs_osidnlc.h"
-
-
-/*
- * UIO routines
- */
-
-/* routine to make copy of uio structure in ainuio, using aoutvec for space */
-int
-afsio_copy(struct uio *ainuio, struct uio *aoutuio,
- register struct iovec *aoutvec)
-{
- register int i;
- register struct iovec *tvec;
-
- AFS_STATCNT(afsio_copy);
- if (ainuio->afsio_iovcnt > AFS_MAXIOVCNT)
- return EINVAL;
- memcpy((char *)aoutuio, (char *)ainuio, sizeof(struct uio));
- tvec = ainuio->afsio_iov;
- aoutuio->afsio_iov = aoutvec;
- for (i = 0; i < ainuio->afsio_iovcnt; i++) {
- memcpy((char *)aoutvec, (char *)tvec, sizeof(struct iovec));
- tvec++; /* too many compiler bugs to do this as one expr */
- aoutvec++;
- }
- return 0;
-}
-
-/* trim the uio structure to the specified size */
-int
-afsio_trim(register struct uio *auio, register afs_int32 asize)
-{
- register int i;
- register struct iovec *tv;
-
- AFS_STATCNT(afsio_trim);
- auio->afsio_resid = asize;
- tv = auio->afsio_iov;
- /* It isn't clear that multiple iovecs work ok (hasn't been tested!) */
- for (i = 0;; i++, tv++) {
- if (i >= auio->afsio_iovcnt || asize <= 0) {
- /* we're done */
- auio->afsio_iovcnt = i;
- break;
- }
- if (tv->iov_len <= asize)
- /* entire iovec is included */
- asize -= tv->iov_len; /* this many fewer bytes */
- else {
- /* this is the last one */
- tv->iov_len = asize;
- auio->afsio_iovcnt = i + 1;
- break;
- }
- }
- return 0;
-}
-
-/* skip asize bytes in the current uio structure */
-int
-afsio_skip(register struct uio *auio, register afs_int32 asize)
-{
- register struct iovec *tv; /* pointer to current iovec */
- register int cnt;
-
- AFS_STATCNT(afsio_skip);
- /* It isn't guaranteed that multiple iovecs work ok (hasn't been tested!) */
- while (asize > 0 && auio->afsio_resid) {
- tv = auio->afsio_iov;
- cnt = tv->iov_len;
- if (cnt == 0) {
- auio->afsio_iov++;
- auio->afsio_iovcnt--;
- continue;
- }
- if (cnt > asize)
- cnt = asize;
- tv->iov_base = (char *)(tv->iov_base) + cnt;
- tv->iov_len -= cnt;
- auio->uio_resid -= cnt;
- auio->uio_offset += cnt;
- asize -= cnt;
- }
- 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
- */
-
-/*
- * System independent part of vget VFS call.
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osi_vget.c,v 1.10 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* statistics stuff */
-
-
-
-#if !defined(AFS_LINUX20_ENV)
-/* This is the common part of the vget VFS call. */
-int
-afs_osi_vget(struct vcache **avcpp, struct fid *afidp, struct vrequest *areqp)
-{
- struct VenusFid vfid;
- struct SmallFid Sfid;
- register struct cell *tcell;
- struct vrequest treq;
- register afs_int32 code = 0, cellindex;
- afs_int32 ret;
-
- memcpy((char *)&Sfid, afidp->fid_data, SIZEOF_SMALLFID);
-#ifdef AFS_OSF_ENV
- Sfid.Vnode = afidp->fid_reserved;
-#endif
-
- /* Need to extract fid from SmallFid. Will need a wild card option for
- * finding the right vcache entry.
- */
- cellindex = (Sfid.CellAndUnique >> 24) & 0xff;
- tcell = afs_GetCellByIndex(cellindex, READ_LOCK);
- if (!tcell)
- return ENOENT;
- vfid.Cell = tcell->cellNum;
- afs_PutCell(tcell, WRITE_LOCK);
- vfid.Fid.Volume = Sfid.Volume;
- vfid.Fid.Vnode = Sfid.Vnode;
- vfid.Fid.Unique = Sfid.CellAndUnique & 0xffffff;
-
- /* First attempt to find in cache using wildcard. If that fails,
- * try the usual route to try to get the vcache from the server.
- * This could be done better by splitting out afs_FindVCache from
- * afs_GetVCache.
- */
-
- ret = afs_NFSFindVCache(avcpp, &vfid);
- if (ret > 1) {
- /* More than one entry matches. */
- code = ENOENT;
- } else if (ret == 0) {
- /* didn't find an entry. */
- *avcpp = afs_GetVCache(&vfid, &treq, NULL, NULL);
- }
- if (!*avcpp) {
- code = ENOENT;
- }
-
- return code;
-}
-#endif /* AFS_LINUX20_ENV */
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_osidnlc.c,v 1.8 2003/07/15 23:14:12 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs.h"
-#include "afs/lock.h"
-#include "afs/afs_stats.h"
-#include "afs/afs_osidnlc.h"
-
-/* Things to do:
- * also cache failed lookups.
- * look into interactions of dnlc and readdir.
- * cache larger names, perhaps by using a better,longer key (SHA) and discarding
- * the actual name itself.
- * precompute a key and stuff for @sys, and combine the HandleAtName function with
- * this, since we're looking at the name anyway.
- */
-
-struct afs_lock afs_xdnlc;
-extern struct afs_lock afs_xvcache;
-
-dnlcstats_t dnlcstats;
-
-#define NCSIZE 300
-#define NHSIZE 256 /* must be power of 2. == NHASHENT in dir package */
-struct nc *ncfreelist = NULL;
-static struct nc nameCache[NCSIZE];
-struct nc *nameHash[NHSIZE];
-/* Hash table invariants:
- * 1. If nameHash[i] is NULL, list is empty
- * 2. A single element in a hash bucket has itself as prev and next.
- */
-
-typedef enum { osi_dnlc_enterT, InsertEntryT, osi_dnlc_lookupT,
- ScavengeEntryT, osi_dnlc_removeT, RemoveEntryT, osi_dnlc_purgedpT,
- osi_dnlc_purgevpT, osi_dnlc_purgeT
-} traceevt;
-
-int afs_usednlc = 1;
-
-struct dt {
- traceevt event;
- unsigned char slot;
-};
-
-struct dt dnlctracetable[256];
-int dnlct;
-
-#define TRACE(e,s) /* if (dnlct == 256) dnlct = 0; dnlctracetable[dnlct].event = e; dnlctracetable[dnlct++].slot = s; */
-
-#define dnlcHash(ts, hval) for (hval=0; *ts; ts++) { hval *= 173; hval += *ts; }
-
-static struct nc *
-GetMeAnEntry(void)
-{
- static unsigned int nameptr = 0; /* next bucket to pull something from */
- struct nc *tnc;
- int j;
-
- if (ncfreelist) {
- tnc = ncfreelist;
- ncfreelist = tnc->next;
- return tnc;
- }
-
- for (j = 0; j < NHSIZE + 2; j++, nameptr++) {
- if (nameptr >= NHSIZE)
- nameptr = 0;
- if (nameHash[nameptr])
- break;
- }
-
- TRACE(ScavengeEntryT, nameptr);
- tnc = nameHash[nameptr];
- if (!tnc) /* May want to consider changing this to return 0 */
- osi_Panic("null tnc in GetMeAnEntry");
-
- if (tnc->prev == tnc) { /* only thing in list, don't screw around */
- nameHash[nameptr] = NULL;
- return (tnc);
- }
-
- tnc = tnc->prev; /* grab oldest one in this bucket */
- /* remove it from list */
- tnc->next->prev = tnc->prev;
- tnc->prev->next = tnc->next;
-
- return (tnc);
-}
-
-static void
-InsertEntry(struct nc *tnc)
-{
- unsigned int key;
- key = tnc->key & (NHSIZE - 1);
-
- TRACE(InsertEntryT, key);
- if (!nameHash[key]) {
- nameHash[key] = tnc;
- tnc->next = tnc->prev = tnc;
- } else {
- tnc->next = nameHash[key];
- tnc->prev = tnc->next->prev;
- tnc->next->prev = tnc;
- tnc->prev->next = tnc;
- nameHash[key] = tnc;
- }
-}
-
-
-int
-osi_dnlc_enter(struct vcache *adp, char *aname, struct vcache *avc,
- afs_hyper_t * avno)
-{
- struct nc *tnc;
- unsigned int key, skey;
- char *ts = aname;
- int safety;
-
- if (!afs_usednlc)
- return 0;
-
- TRACE(osi_dnlc_enterT, 0);
- dnlcHash(ts, key); /* leaves ts pointing at the NULL */
- if (ts - aname >= AFSNCNAMESIZE) {
- return 0;
- }
- skey = key & (NHSIZE - 1);
- dnlcstats.enters++;
-
- retry:
- ObtainWriteLock(&afs_xdnlc, 222);
-
- /* Only cache entries from the latest version of the directory */
- if (!(adp->states & CStatd) || !hsame(*avno, adp->m.DataVersion)) {
- ReleaseWriteLock(&afs_xdnlc);
- return 0;
- }
-
- /*
- * Make sure each directory entry gets cached no more than once.
- */
- for (tnc = nameHash[skey], safety = 0; tnc; tnc = tnc->next, safety++) {
- if ((tnc->dirp == adp) && (!strcmp((char *)tnc->name, aname))) {
- /* duplicate entry */
- break;
- } else if (tnc->next == nameHash[skey]) { /* end of list */
- tnc = NULL;
- break;
- } else if (safety > NCSIZE) {
- afs_warn("DNLC cycle");
- dnlcstats.cycles++;
- ReleaseWriteLock(&afs_xdnlc);
- osi_dnlc_purge();
- goto retry;
- }
- }
-
- if (tnc == NULL) {
- tnc = GetMeAnEntry();
-
- tnc->dirp = adp;
- tnc->vp = avc;
- tnc->key = key;
- memcpy((char *)tnc->name, aname, ts - aname + 1); /* include the NULL */
-
- InsertEntry(tnc);
- } else {
- /* duplicate */
- tnc->vp = avc;
- }
- ReleaseWriteLock(&afs_xdnlc);
-
- return 0;
-}
-
-
-struct vcache *
-osi_dnlc_lookup(struct vcache *adp, char *aname, int locktype)
-{
- struct vcache *tvc;
- int LRUme;
- unsigned int key, skey;
- char *ts = aname;
- struct nc *tnc, *tnc1 = 0;
- int safety;
-
- if (!afs_usednlc)
- return 0;
-
- dnlcHash(ts, key); /* leaves ts pointing at the NULL */
- if (ts - aname >= AFSNCNAMESIZE) {
- return 0;
- }
- skey = key & (NHSIZE - 1);
-
- TRACE(osi_dnlc_lookupT, skey);
- dnlcstats.lookups++;
-
- ObtainReadLock(&afs_xvcache);
- ObtainReadLock(&afs_xdnlc);
-
- for (tvc = NULL, tnc = nameHash[skey], safety = 0; tnc;
- tnc = tnc->next, safety++) {
- if ( /* (tnc->key == key) && */ (tnc->dirp == adp)
- && (!strcmp((char *)tnc->name, aname))) {
- tvc = tnc->vp;
- tnc1 = tnc;
- break;
- } else if (tnc->next == nameHash[skey]) { /* end of list */
- break;
- } else if (safety > NCSIZE) {
- afs_warn("DNLC cycle");
- dnlcstats.cycles++;
- ReleaseReadLock(&afs_xdnlc);
- ReleaseReadLock(&afs_xvcache);
- osi_dnlc_purge();
- return (0);
- }
- }
-
- LRUme = 0; /* (tnc != nameHash[skey]); */
- ReleaseReadLock(&afs_xdnlc);
-
- if (!tvc) {
- ReleaseReadLock(&afs_xvcache);
- dnlcstats.misses++;
- } else {
-#ifdef AFS_OSF_ENV
- VN_HOLD((vnode_t *) tvc);
-#else
- osi_vnhold(tvc, 0);
-#endif
- ReleaseReadLock(&afs_xvcache);
-
-#ifdef notdef
- /*
- * XX If LRUme ever is non-zero change the if statement around because
- * aix's cc with optimizer on won't necessarily check things in order XX
- */
- if (LRUme && (0 == NBObtainWriteLock(&afs_xdnlc))) {
- /* don't block to do this */
- /* tnc might have been moved during race condition, */
- /* but it's always in a legit hash chain when a lock is granted,
- * or else it's on the freelist so prev == NULL,
- * so at worst this is redundant */
- /* Now that we've got it held, and a lock on the dnlc, we
- * should check to be sure that there was no race, and
- * bail out if there was. */
- if (tnc->prev) {
- /* special case for only two elements on list - relative ordering
- * doesn't change */
- if (tnc->prev != tnc->next) {
- /* remove from old location */
- tnc->prev->next = tnc->next;
- tnc->next->prev = tnc->prev;
- /* insert into new location */
- tnc->next = nameHash[skey];
- tnc->prev = tnc->next->prev;
- tnc->next->prev = tnc;
- tnc->prev->next = tnc;
- }
- nameHash[skey] = tnc;
- }
- ReleaseWriteLock(&afs_xdnlc);
- }
-#endif
- }
-
- return tvc;
-}
-
-
-static void
-RemoveEntry(struct nc *tnc, unsigned int key)
-{
- if (!tnc->prev) /* things on freelist always have null prev ptrs */
- osi_Panic("bogus free list");
-
- TRACE(RemoveEntryT, key);
- if (tnc == tnc->next) { /* only one in list */
- nameHash[key] = NULL;
- } else {
- if (tnc == nameHash[key])
- nameHash[key] = tnc->next;
- tnc->prev->next = tnc->next;
- tnc->next->prev = tnc->prev;
- }
-
- tnc->prev = NULL; /* everything not in hash table has 0 prev */
- tnc->key = 0; /* just for safety's sake */
-}
-
-
-int
-osi_dnlc_remove(struct vcache *adp, char *aname, struct vcache *avc)
-{
- unsigned int key, skey;
- char *ts = aname;
- struct nc *tnc;
-
- if (!afs_usednlc)
- return 0;
-
- TRACE(osi_dnlc_removeT, skey);
- dnlcHash(ts, key); /* leaves ts pointing at the NULL */
- if (ts - aname >= AFSNCNAMESIZE) {
- return 0;
- }
- skey = key & (NHSIZE - 1);
- TRACE(osi_dnlc_removeT, skey);
- dnlcstats.removes++;
- ObtainReadLock(&afs_xdnlc);
-
- for (tnc = nameHash[skey]; tnc; tnc = tnc->next) {
- if ((tnc->dirp == adp) && (tnc->key == key)
- && (!strcmp((char *)tnc->name, aname))) {
- tnc->dirp = NULL; /* now it won't match anything */
- break;
- } else if (tnc->next == nameHash[skey]) { /* end of list */
- tnc = NULL;
- break;
- }
- }
- ReleaseReadLock(&afs_xdnlc);
-
- if (!tnc)
- return 0;
-
- /* there is a little race condition here, but it's relatively
- * harmless. At worst, I wind up removing a mapping that I just
- * created. */
- if (EWOULDBLOCK == NBObtainWriteLock(&afs_xdnlc, 1)) {
- return 0; /* no big deal, tnc will get recycled eventually */
- }
- RemoveEntry(tnc, skey);
- tnc->next = ncfreelist;
- ncfreelist = tnc;
- ReleaseWriteLock(&afs_xdnlc);
-
- return 0;
-}
-
-/* remove anything pertaining to this directory. I can invalidate
- * things without the lock, since I am just looking through the array,
- * but to move things off the lists or into the freelist, I need the
- * write lock */
-int
-osi_dnlc_purgedp(struct vcache *adp)
-{
- int i;
- int writelocked;
-
- if (!afs_usednlc)
- return 0;
-
- dnlcstats.purgeds++;
- TRACE(osi_dnlc_purgedpT, 0);
- writelocked = (0 == NBObtainWriteLock(&afs_xdnlc, 2));
-
- for (i = 0; i < NCSIZE; i++) {
- if ((nameCache[i].dirp == adp) || (nameCache[i].vp == adp)) {
- nameCache[i].dirp = nameCache[i].vp = NULL;
- if (writelocked && nameCache[i].prev) {
- RemoveEntry(&nameCache[i], nameCache[i].key & (NHSIZE - 1));
- nameCache[i].next = ncfreelist;
- ncfreelist = &nameCache[i];
- }
- }
- }
- if (writelocked)
- ReleaseWriteLock(&afs_xdnlc);
-
- return 0;
-}
-
-/* remove anything pertaining to this file */
-int
-osi_dnlc_purgevp(struct vcache *avc)
-{
- int i;
- int writelocked;
-
- if (!afs_usednlc)
- return 0;
-
- dnlcstats.purgevs++;
- TRACE(osi_dnlc_purgevpT, 0);
- writelocked = (0 == NBObtainWriteLock(&afs_xdnlc, 3));
-
- for (i = 0; i < NCSIZE; i++) {
- if ((nameCache[i].vp == avc)) {
- nameCache[i].dirp = nameCache[i].vp = NULL;
- /* can't simply break; because of hard links -- might be two */
- /* different entries with same vnode */
- if (writelocked && nameCache[i].prev) {
- RemoveEntry(&nameCache[i], nameCache[i].key & (NHSIZE - 1));
- nameCache[i].next = ncfreelist;
- ncfreelist = &nameCache[i];
- }
- }
- }
- if (writelocked)
- ReleaseWriteLock(&afs_xdnlc);
-
- return 0;
-}
-
-/* remove everything */
-int
-osi_dnlc_purge(void)
-{
- int i;
-
- dnlcstats.purges++;
- TRACE(osi_dnlc_purgeT, 0);
- if (EWOULDBLOCK == NBObtainWriteLock(&afs_xdnlc, 4)) { /* couldn't get lock */
- for (i = 0; i < NCSIZE; i++)
- nameCache[i].dirp = nameCache[i].vp = NULL;
- } else { /* did get the lock */
- ncfreelist = NULL;
- memset((char *)nameCache, 0, sizeof(struct nc) * NCSIZE);
- memset((char *)nameHash, 0, sizeof(struct nc *) * NHSIZE);
- for (i = 0; i < NCSIZE; i++) {
- nameCache[i].next = ncfreelist;
- ncfreelist = &nameCache[i];
- }
- ReleaseWriteLock(&afs_xdnlc);
- }
-
- return 0;
-}
-
-/* remove everything referencing a specific volume */
-int
-osi_dnlc_purgevol(struct VenusFid *fidp)
-{
-
- dnlcstats.purgevols++;
- osi_dnlc_purge();
-
- return 0;
-}
-
-int
-osi_dnlc_init(void)
-{
- int i;
-
- Lock_Init(&afs_xdnlc);
- memset((char *)&dnlcstats, 0, sizeof(dnlcstats));
- memset((char *)dnlctracetable, 0, sizeof(dnlctracetable));
- dnlct = 0;
- ObtainWriteLock(&afs_xdnlc, 223);
- ncfreelist = NULL;
- memset((char *)nameCache, 0, sizeof(struct nc) * NCSIZE);
- memset((char *)nameHash, 0, sizeof(struct nc *) * NHSIZE);
- for (i = 0; i < NCSIZE; i++) {
- nameCache[i].next = ncfreelist;
- ncfreelist = &nameCache[i];
- }
- ReleaseWriteLock(&afs_xdnlc);
-
- return 0;
-}
-
-int
-osi_dnlc_shutdown(void)
-{
- 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
- */
-
-#define AFSNCNAMESIZE 36 /* multiple of 4 */
-struct nc {
- unsigned int key;
- struct nc *next, *prev;
- struct vcache *dirp, *vp;
- unsigned char name[AFSNCNAMESIZE];
- /* I think that we can avoid wasting a byte for NULL, with a
- * a little bit of thought.
- */
-};
-
-typedef struct {
- unsigned int enters, lookups, misses, removes;
- unsigned int purgeds, purgevs, purgevols, purges;
- unsigned int cycles, lookuprace;
-} dnlcstats_t;
+++ /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"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_pioctl.c,v 1.78 2004/04/18 06:13:47 kolya Exp $");
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#ifdef AFS_OBSD_ENV
-#include "h/syscallargs.h"
-#endif
-#ifdef AFS_FBSD50_ENV
-#include "h/sysproto.h"
-#endif
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "afs/vice.h"
-#include "rx/rx_globals.h"
-
-struct VenusFid afs_rootFid;
-afs_int32 afs_waitForever = 0;
-short afs_waitForeverCount = 0;
-afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
-
-#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
- char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
- struct AFS_UCRED **acred)
-
-/* Prototypes for pioctl routines */
-DECL_PIOCTL(PGetFID);
-DECL_PIOCTL(PSetAcl);
-DECL_PIOCTL(PStoreBehind);
-DECL_PIOCTL(PGCPAGs);
-DECL_PIOCTL(PGetAcl);
-DECL_PIOCTL(PNoop);
-DECL_PIOCTL(PBogus);
-DECL_PIOCTL(PGetFileCell);
-DECL_PIOCTL(PGetWSCell);
-DECL_PIOCTL(PGetUserCell);
-DECL_PIOCTL(PSetTokens);
-DECL_PIOCTL(PGetVolumeStatus);
-DECL_PIOCTL(PSetVolumeStatus);
-DECL_PIOCTL(PFlush);
-DECL_PIOCTL(PNewStatMount);
-DECL_PIOCTL(PGetTokens);
-DECL_PIOCTL(PUnlog);
-DECL_PIOCTL(PMariner);
-DECL_PIOCTL(PCheckServers);
-DECL_PIOCTL(PCheckVolNames);
-DECL_PIOCTL(PCheckAuth);
-DECL_PIOCTL(PFindVolume);
-DECL_PIOCTL(PViceAccess);
-DECL_PIOCTL(PSetCacheSize);
-DECL_PIOCTL(PGetCacheSize);
-DECL_PIOCTL(PRemoveCallBack);
-DECL_PIOCTL(PNewCell);
-DECL_PIOCTL(PNewAlias);
-DECL_PIOCTL(PListCells);
-DECL_PIOCTL(PListAliases);
-DECL_PIOCTL(PRemoveMount);
-DECL_PIOCTL(PVenusLogging);
-DECL_PIOCTL(PGetCellStatus);
-DECL_PIOCTL(PSetCellStatus);
-DECL_PIOCTL(PFlushVolumeData);
-DECL_PIOCTL(PGetVnodeXStatus);
-DECL_PIOCTL(PSetSysName);
-DECL_PIOCTL(PSetSPrefs);
-DECL_PIOCTL(PSetSPrefs33);
-DECL_PIOCTL(PGetSPrefs);
-DECL_PIOCTL(PExportAfs);
-DECL_PIOCTL(PGag);
-DECL_PIOCTL(PTwiddleRx);
-DECL_PIOCTL(PGetInitParams);
-DECL_PIOCTL(PGetRxkcrypt);
-DECL_PIOCTL(PSetRxkcrypt);
-DECL_PIOCTL(PGetCPrefs);
-DECL_PIOCTL(PSetCPrefs);
-DECL_PIOCTL(PFlushMount);
-DECL_PIOCTL(PRxStatProc);
-DECL_PIOCTL(PRxStatPeer);
-DECL_PIOCTL(PPrefetchFromTape);
-DECL_PIOCTL(PResidencyCmd);
-
-/*
- * A macro that says whether we're going to need HandleClientContext().
- * This is currently used only by the nfs translator.
- */
-#if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
-#define AFS_NEED_CLIENTCONTEXT
-#endif
-
-/* Prototypes for private routines */
-#ifdef AFS_NEED_CLIENTCONTEXT
-static int HandleClientContext(struct afs_ioctl *ablob, int *com,
- struct AFS_UCRED **acred,
- struct AFS_UCRED *credp);
-#endif
-int HandleIoctl(register struct vcache *avc, register afs_int32 acom,
- struct afs_ioctl *adata);
-int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
- register struct afs_ioctl *ablob, int afollow,
- struct AFS_UCRED **acred);
-static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
- struct AFS_UCRED *acred);
-
-
-static int (*(VpioctlSw[])) () = {
- PBogus, /* 0 */
- PSetAcl, /* 1 */
- PGetAcl, /* 2 */
- PSetTokens, /* 3 */
- PGetVolumeStatus, /* 4 */
- PSetVolumeStatus, /* 5 */
- PFlush, /* 6 */
- PBogus, /* 7 */
- PGetTokens, /* 8 */
- PUnlog, /* 9 */
- PCheckServers, /* 10 */
- PCheckVolNames, /* 11 */
- PCheckAuth, /* 12 */
- PBogus, /* 13 -- used to be quick check time */
- PFindVolume, /* 14 */
- PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
- PBogus, /* 16 -- used to be testing code */
- PNoop, /* 17 -- used to be enable group */
- PNoop, /* 18 -- used to be disable group */
- PBogus, /* 19 -- used to be list group */
- PViceAccess, /* 20 */
- PUnlog, /* 21 -- unlog *is* unpag in this system */
- PGetFID, /* 22 -- get file ID */
- PBogus, /* 23 -- used to be waitforever */
- PSetCacheSize, /* 24 */
- PRemoveCallBack, /* 25 -- flush only the callback */
- PNewCell, /* 26 */
- PListCells, /* 27 */
- PRemoveMount, /* 28 -- delete mount point */
- PNewStatMount, /* 29 -- new style mount point stat */
- PGetFileCell, /* 30 -- get cell name for input file */
- PGetWSCell, /* 31 -- get cell name for workstation */
- PMariner, /* 32 - set/get mariner host */
- PGetUserCell, /* 33 -- get cell name for user */
- PVenusLogging, /* 34 -- Enable/Disable logging */
- PGetCellStatus, /* 35 */
- PSetCellStatus, /* 36 */
- PFlushVolumeData, /* 37 -- flush all data from a volume */
- PSetSysName, /* 38 - Set system name */
- PExportAfs, /* 39 - Export Afs to remote nfs clients */
- PGetCacheSize, /* 40 - get cache size and usage */
- PGetVnodeXStatus, /* 41 - get vcache's special status */
- PSetSPrefs33, /* 42 - Set CM Server preferences... */
- PGetSPrefs, /* 43 - Get CM Server preferences... */
- PGag, /* 44 - turn off/on all CM messages */
- PTwiddleRx, /* 45 - adjust some RX params */
- PSetSPrefs, /* 46 - Set CM Server preferences... */
- PStoreBehind, /* 47 - set degree of store behind to be done */
- PGCPAGs, /* 48 - disable automatic pag gc-ing */
- PGetInitParams, /* 49 - get initial cm params */
- PGetCPrefs, /* 50 - get client interface addresses */
- PSetCPrefs, /* 51 - set client interface addresses */
- PFlushMount, /* 52 - flush mount symlink data */
- PRxStatProc, /* 53 - control process RX statistics */
- PRxStatPeer, /* 54 - control peer RX statistics */
- PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
- PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
- PBogus, /* 57 -- arla: set file prio */
- PBogus, /* 58 -- arla: fallback getfh */
- PBogus, /* 59 -- arla: fallback fhopen */
- PBogus, /* 60 -- arla: controls xfsdebug */
- PBogus, /* 61 -- arla: controls arla debug */
- PBogus, /* 62 -- arla: debug interface */
- PBogus, /* 63 -- arla: print xfs status */
- PBogus, /* 64 -- arla: force cache check */
- PBogus, /* 65 -- arla: break callback */
- PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
- PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
- PBogus, /* 68 -- arla: fetch stats */
-};
-
-static int (*(CpioctlSw[])) () = {
- PBogus, /* 0 */
- PNewAlias, /* 1 -- create new cell alias */
- PListAliases, /* 2 -- list cell aliases */
-};
-
-#define PSetClientContext 99 /* Special pioctl to setup caller's creds */
-int afs_nobody = NFS_NOBODY;
-
-static void
-afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
-{
- dst->in = (char *)(unsigned long)src->in;
- dst->out = (char *)(unsigned long)src->out;
- dst->in_size = src->in_size;
- dst->out_size = src->out_size;
-}
-
-/*
- * If you need to change copyin_afs_ioctl(), you may also need to change
- * copyin_iparam().
- */
-
-static int
-copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
-{
- int code;
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- struct afs_ioctl32 dst32;
-
- if (!(IS64U)) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
-
-
-#if defined(AFS_HPUX_64BIT_ENV)
- struct afs_ioctl32 dst32;
-
- if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_HPUX_64BIT_ENV) */
-
-#if defined(AFS_SUN57_64BIT_ENV)
- struct afs_ioctl32 dst32;
-
- if (get_udatamodel() == DATAMODEL_ILP32) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_SUN57_64BIT_ENV) */
-
-#if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
- struct afs_ioctl32 dst32;
-
- if (!ABI_IS_64BIT(get_current_abi())) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
-
-#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) && !defined(AFS_AMD64_LINUX20_ENV)
- struct afs_ioctl32 dst32;
-
-#ifdef AFS_SPARC64_LINUX24_ENV
- if (current->thread.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_SPARC64_LINUX20_ENV)
- if (current->tss.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_AMD64_LINUX20_ENV)
- if (current->thread.flags & THREAD_IA32)
-#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
-#else
-#error Not done for this linux type
-#endif
- {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_LINUX_64BIT_KERNEL) */
-
- AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
- return code;
-}
-
-int
-HandleIoctl(register struct vcache *avc, register afs_int32 acom,
- struct afs_ioctl *adata)
-{
- register afs_int32 code;
-
- code = 0;
- AFS_STATCNT(HandleIoctl);
-
- switch (acom & 0xff) {
- case 1:
- avc->states |= CSafeStore;
- avc->asynchrony = 0;
- break;
-
- /* case 2 used to be abort store, but this is no longer provided,
- * since it is impossible to implement under normal Unix.
- */
-
- case 3:{
- /* return the name of the cell this file is open on */
- register struct cell *tcell;
- register afs_int32 i;
-
- tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
- if (tcell) {
- i = strlen(tcell->cellName) + 1; /* bytes to copy out */
-
- if (i > adata->out_size) {
- /* 0 means we're not interested in the output */
- if (adata->out_size != 0)
- code = EFAULT;
- } else {
- /* do the copy */
- AFS_COPYOUT(tcell->cellName, adata->out, i, code);
- }
- afs_PutCell(tcell, READ_LOCK);
- } else
- code = ENOTTY;
- }
- break;
-
- case 49: /* VIOC_GETINITPARAMS */
- if (adata->out_size < sizeof(struct cm_initparams)) {
- code = EFAULT;
- } else {
- AFS_COPYOUT(&cm_initParams, adata->out,
- sizeof(struct cm_initparams), code);
- }
- break;
-
- default:
-
- code = EINVAL;
-#ifdef AFS_AIX51_ENV
- code = ENOSYS;
-#endif
- break;
- }
- return code; /* so far, none implemented */
-}
-
-
-#ifdef AFS_AIX_ENV
-/* For aix we don't temporarily bypass ioctl(2) but rather do our
- * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
- * is now called from afs_gn_ioctl.
- */
-int
-afs_ioctl(struct vcache *tvc, int cmd, int arg)
-{
- struct afs_ioctl data;
- int error = 0;
-
- AFS_STATCNT(afs_ioctl);
- if (((cmd >> 8) & 0xff) == 'V') {
- /* This is a VICEIOCTL call */
- AFS_COPYIN(arg, (caddr_t) & data, sizeof(data), error);
- if (error)
- return (error);
- error = HandleIoctl(tvc, cmd, &data);
- return (error);
- } else {
- /* No-op call; just return. */
- return (ENOTTY);
- }
-}
-#endif /* AFS_AIX_ENV */
-
-#if defined(AFS_SGI_ENV)
-afs_ioctl(OSI_VN_DECL(tvc), int cmd, void *arg, int flag, cred_t * cr,
- rval_t * rvalp
-#ifdef AFS_SGI65_ENV
- , struct vopbd * vbds
-#endif
- )
-{
- struct afs_ioctl data;
- int error = 0;
- int locked;
-
- OSI_VN_CONVERT(tvc);
-
- AFS_STATCNT(afs_ioctl);
- if (((cmd >> 8) & 0xff) == 'V') {
- /* This is a VICEIOCTL call */
- error = copyin_afs_ioctl(arg, &data);
- if (error)
- return (error);
- locked = ISAFS_GLOCK();
- if (!locked)
- AFS_GLOCK();
- error = HandleIoctl(tvc, cmd, &data);
- if (!locked)
- AFS_GUNLOCK();
- return (error);
- } else {
- /* No-op call; just return. */
- return (ENOTTY);
- }
-}
-#endif /* AFS_SGI_ENV */
-
-/* unlike most calls here, this one uses u.u_error to return error conditions,
- since this is really an intercepted chapter 2 call, rather than a vnode
- interface call.
- */
-/* AFS_HPUX102 and up uses VNODE ioctl instead */
-#ifndef AFS_HPUX102_ENV
-#if !defined(AFS_SGI_ENV)
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX51_ENV
-#ifdef __64BIT__
-kioctl(fdes, com, arg, ext, arg2, arg3)
-#else /* __64BIT__ */
-kioctl32(fdes, com, arg, ext, arg2, arg3)
-#endif /* __64BIT__ */
- caddr_t arg2, arg3;
-#else
-kioctl(fdes, com, arg, ext)
-#endif
- int fdes, com;
- caddr_t arg, ext;
-{
- struct a {
- int fd, com;
- caddr_t arg, ext;
-#ifdef AFS_AIX51_ENV
- caddr_t arg2, arg3;
-#endif
- } u_uap, *uap = &u_uap;
-#else
-#if defined(AFS_SUN5_ENV)
-
-struct afs_ioctl_sys {
- int fd;
- int com;
- int arg;
-};
-
-afs_xioctl(uap, rvp)
- struct afs_ioctl_sys *uap;
- rval_t *rvp;
-{
-#elif defined(AFS_OSF_ENV)
-afs_xioctl(p, args, retval)
- struct proc *p;
- void *args;
- long *retval;
-{
- struct a {
- long fd;
- u_long com;
- caddr_t arg;
- } *uap = (struct a *)args;
-#elif defined(AFS_FBSD50_ENV)
-#define arg data
-int
-afs_xioctl(td, uap, retval)
- struct thread *td;
- register struct ioctl_args *uap;
- register_t *retval;
-{
- struct proc *p = td->td_proc;
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-struct ioctl_args {
- int fd;
- u_long com;
- caddr_t arg;
-};
-
-int
-afs_xioctl(p, uap, retval)
- struct proc *p;
- register struct ioctl_args *uap;
- register_t *retval;
-{
-#elif defined(AFS_LINUX22_ENV)
-struct afs_ioctl_sys {
- unsigned int com;
- unsigned long arg;
-};
-asmlinkage int
-afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
- unsigned long arg)
-{
- struct afs_ioctl_sys ua, *uap = &ua;
-#else
-int
-afs_xioctl(void)
-{
- register struct a {
- int fd;
- int com;
- caddr_t arg;
- } *uap = (struct a *)u.u_ap;
-#endif /* AFS_SUN5_ENV */
-#endif
-#if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
- struct file *fd;
-#elif !defined(AFS_LINUX22_ENV)
- register struct file *fd;
-#endif
-#if defined(AFS_XBSD_ENV)
- register struct filedesc *fdp;
-#endif
- register struct vcache *tvc;
- register int ioctlDone = 0, code = 0;
-
- AFS_STATCNT(afs_xioctl);
-#if defined(AFS_XBSD_ENV)
- fdp = p->p_fd;
- if ((u_int) uap->fd >= fdp->fd_nfiles
- || (fd = fdp->fd_ofiles[uap->fd]) == NULL)
- return EBADF;
- if ((fd->f_flag & (FREAD | FWRITE)) == 0)
- return EBADF;
-#elif defined(AFS_DARWIN_ENV)
- if ((code = fdgetf(p, uap->fd, &fd)))
- return code;
-#elif defined(AFS_LINUX22_ENV)
- ua.com = com;
- ua.arg = arg;
-#elif defined(AFS_AIX32_ENV)
- uap->fd = fdes;
- uap->com = com;
- uap->arg = arg;
-#ifdef AFS_AIX51_ENV
- uap->arg2 = arg2;
- uap->arg3 = arg3;
-#endif
- if (setuerror(getf(uap->fd, &fd))) {
- return -1;
- }
-#elif defined(AFS_OSF_ENV)
- fd = NULL;
- if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
- return code;
-#elif defined(AFS_SUN5_ENV)
-# if defined(AFS_SUN57_ENV)
- fd = getf(uap->fd);
- if (!fd)
- return (EBADF);
-# elif defined(AFS_SUN54_ENV)
- fd = GETF(uap->fd);
- if (!fd)
- return (EBADF);
-# else
- if (code = getf(uap->fd, &fd)) {
- return (code);
- }
-# endif /* AFS_SUN57_ENV */
-#else
- fd = getf(uap->fd);
- if (!fd)
- return (EBADF);
-#endif
- /* first determine whether this is any sort of vnode */
-#if defined(AFS_LINUX22_ENV)
- tvc = VTOAFS(ip);
- {
-#else
-#ifdef AFS_SUN5_ENV
- if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
-#else
- if (fd->f_type == DTYPE_VNODE) {
-#endif
- /* good, this is a vnode; next see if it is an AFS vnode */
-#if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
- tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
-#elif defined(AFS_OBSD_ENV)
- tvc =
- IsAfsVnode((struct vnode *)fd->
- f_data) ? VTOAFS((struct vnode *)fd->f_data) : NULL;
-#else
- tvc = VTOAFS((struct vnode *)fd->f_data); /* valid, given a vnode */
-#endif
-#endif /* AFS_LINUX22_ENV */
- if (tvc && IsAfsVnode(AFSTOV(tvc))) {
-#ifdef AFS_DEC_ENV
- tvc = VTOAFS(afs_gntovn((struct gnode *)tvc));
- if (!tvc) { /* shouldn't happen with held gnodes */
- u.u_error = ENOENT;
- return;
- }
-#endif
- /* This is an AFS vnode */
- if (((uap->com >> 8) & 0xff) == 'V') {
- register struct afs_ioctl *datap;
- AFS_GLOCK();
- datap =
- (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
- AFS_COPYIN((char *)uap->arg, (caddr_t) datap,
- sizeof(struct afs_ioctl), code);
- if (code) {
- osi_FreeSmallSpace(datap);
- AFS_GUNLOCK();
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- return code;
-#else
-#if defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN54_ENV
- releasef(uap->fd);
-#else
- releasef(fd);
-#endif
- return (EFAULT);
-#else
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
- FP_UNREF_ALWAYS(fd);
-#else
- FP_UNREF(fd);
-#endif
- return code;
-#else /* AFS_OSF_ENV */
-#ifdef AFS_AIX41_ENV
- ufdrele(uap->fd);
-#endif
-#ifdef AFS_LINUX22_ENV
- return -code;
-#else
- setuerror(code);
- return;
-#endif
-#endif
-#endif
-#endif
- }
- code = HandleIoctl(tvc, uap->com, datap);
- osi_FreeSmallSpace(datap);
- AFS_GUNLOCK();
- ioctlDone = 1;
-#ifdef AFS_AIX41_ENV
- ufdrele(uap->fd);
-#endif
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
- FP_UNREF_ALWAYS(fd);
-#else
- FP_UNREF(fd);
-#endif
-#endif
- }
-#if defined(AFS_LINUX22_ENV)
- else
- code = EINVAL;
-#endif
- }
- }
-
- if (!ioctlDone) {
-#ifdef AFS_AIX41_ENV
- ufdrele(uap->fd);
-#ifdef AFS_AIX51_ENV
-#ifdef __64BIT__
- code = okioctl(fdes, com, arg, ext, arg2, arg3);
-#else /* __64BIT__ */
- code = okioctl32(fdes, com, arg, ext, arg2, arg3);
-#endif /* __64BIT__ */
-#else /* !AFS_AIX51_ENV */
- code = okioctl(fdes, com, arg, ext);
-#endif /* AFS_AIX51_ENV */
- return code;
-#else /* !AFS_AIX41_ENV */
-#ifdef AFS_AIX32_ENV
- okioctl(fdes, com, arg, ext);
-#elif defined(AFS_SUN5_ENV)
-#if defined(AFS_SUN57_ENV)
- releasef(uap->fd);
-#elif defined(AFS_SUN54_ENV)
- RELEASEF(uap->fd);
-#else
- releasef(fd);
-#endif
- code = ioctl(uap, rvp);
-#elif defined(AFS_FBSD50_ENV)
- return ioctl(td, uap);
-#elif defined(AFS_FBSD_ENV)
- return ioctl(p, uap);
-#elif defined(AFS_OBSD_ENV)
- code = sys_ioctl(p, uap, retval);
-#elif defined(AFS_DARWIN_ENV)
- return ioctl(p, uap, retval);
-#elif defined(AFS_OSF_ENV)
- code = ioctl(p, args, retval);
-#ifdef AFS_OSF30_ENV
- FP_UNREF_ALWAYS(fd);
-#else
- FP_UNREF(fd);
-#endif
- return code;
-#elif !defined(AFS_LINUX22_ENV)
- ioctl();
-#endif
-#endif
- }
-#ifdef AFS_SUN5_ENV
- if (ioctlDone)
-#ifdef AFS_SUN54_ENV
- releasef(uap->fd);
-#else
- releasef(fd);
-#endif
- return (code);
-#else
-#ifdef AFS_LINUX22_ENV
- return -code;
-#else
-#if defined(KERNEL_HAVE_UERROR)
- if (!getuerror())
- setuerror(code);
-#if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
- return (getuerror()? -1 : u.u_ioctlrv);
-#else
- return getuerror()? -1 : 0;
-#endif
-#endif
-#endif /* AFS_LINUX22_ENV */
-#endif /* AFS_SUN5_ENV */
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- return (code);
-#endif
-}
-#endif /* AFS_SGI_ENV */
-#endif /* AFS_HPUX102_ENV */
-
-#if defined(AFS_SGI_ENV)
- /* "pioctl" system call entry point; just pass argument to the parameterized
- * call below */
-struct pioctlargs {
- char *path;
- sysarg_t cmd;
- caddr_t cmarg;
- sysarg_t follow;
-};
-int
-afs_pioctl(struct pioctlargs *uap, rval_t * rvp)
-{
- int code;
-
- AFS_STATCNT(afs_pioctl);
- AFS_GLOCK();
- code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
- AFS_GUNLOCK();
-#ifdef AFS_SGI64_ENV
- return code;
-#else
- return u.u_error;
-#endif
-}
-
-#elif defined(AFS_OSF_ENV)
-afs_pioctl(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
-{
- struct a {
- char *path;
- int cmd;
- caddr_t cmarg;
- int follow;
- } *uap = (struct a *)args;
-
- AFS_STATCNT(afs_pioctl);
- return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
-}
-
-#elif defined(AFS_FBSD50_ENV)
-int
-afs_pioctl(td, args, retval)
- struct thread *td;
- void *args;
- int *retval;
-{
- struct a {
- char *path;
- int cmd;
- caddr_t cmarg;
- int follow;
- } *uap = (struct a *)args;
-
- AFS_STATCNT(afs_pioctl);
- return (afs_syscall_pioctl
- (uap->path, uap->cmd, uap->cmarg, uap->follow, td->td_ucred));
-}
-
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-int
-afs_pioctl(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
-{
- struct a {
- char *path;
- int cmd;
- caddr_t cmarg;
- int follow;
- } *uap = (struct a *)args;
-
- AFS_STATCNT(afs_pioctl);
- return (afs_syscall_pioctl
- (uap->path, uap->cmd, uap->cmarg, uap->follow,
- p->p_cred->pc_ucred));
-}
-
-#endif
-
-/* macro to avoid adding any more #ifdef's to pioctl code. */
-#if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
-#define PIOCTL_FREE_CRED() crfree(credp)
-#else
-#define PIOCTL_FREE_CRED()
-#endif
-
-int
-#ifdef AFS_SUN5_ENV
-afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
- rval_t *rvp;
- struct AFS_UCRED *credp;
-#else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_syscall_pioctl(path, com, cmarg, follow, credp)
- struct AFS_UCRED *credp;
-#else
-afs_syscall_pioctl(path, com, cmarg, follow)
-#endif
-#endif
- char *path;
- unsigned int com;
- caddr_t cmarg;
- int follow;
-{
- struct afs_ioctl data;
- struct AFS_UCRED *tmpcred, *foreigncreds = NULL;
- register afs_int32 code = 0;
- struct vnode *vp;
-#ifdef AFS_DEC_ENV
- struct vnode *gp;
-#endif
-#ifdef AFS_AIX41_ENV
- struct ucred *credp = crref(); /* don't free until done! */
-#endif
-#ifdef AFS_LINUX22_ENV
- cred_t *credp = crref(); /* don't free until done! */
- struct dentry *dp;
-#endif
-
- AFS_STATCNT(afs_syscall_pioctl);
- if (follow)
- follow = 1; /* compat. with old venus */
- code = copyin_afs_ioctl(cmarg, &data);
- if (code) {
- PIOCTL_FREE_CRED();
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- return (code);
- }
- if ((com & 0xff) == PSetClientContext) {
-#ifdef AFS_NEED_CLIENTCONTEXT
-#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV)
- code = HandleClientContext(&data, &com, &foreigncreds, credp);
-#else
- code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
-#endif
- if (code) {
- if (foreigncreds) {
- crfree(foreigncreds);
- }
- PIOCTL_FREE_CRED();
-#if defined(KERNEL_HAVE_UERROR)
- return (setuerror(code), code);
-#else
- return (code);
-#endif
- }
-#else /* AFS_NEED_CLIENTCONTEXT */
- return EINVAL;
-#endif /* AFS_NEED_CLIENTCONTEXT */
- }
-#ifdef AFS_NEED_CLIENTCONTEXT
- if (foreigncreds) {
- /*
- * We could have done without temporary setting the u.u_cred below
- * (foreigncreds could be passed as param the pioctl modules)
- * but calls such as afs_osi_suser() doesn't allow that since it
- * references u.u_cred directly. We could, of course, do something
- * like afs_osi_suser(cred) which, I think, is better since it
- * generalizes and supports multi cred environments...
- */
-#ifdef AFS_SUN5_ENV
- tmpcred = credp;
- credp = foreigncreds;
-#elif defined(AFS_AIX41_ENV)
- tmpcred = crref(); /* XXX */
- crset(foreigncreds);
-#elif defined(AFS_HPUX101_ENV)
- tmpcred = p_cred(u.u_procp);
- set_p_cred(u.u_procp, foreigncreds);
-#elif defined(AFS_SGI_ENV)
- tmpcred = OSI_GET_CURRENT_CRED();
- OSI_SET_CURRENT_CRED(foreigncreds);
-#else
- tmpcred = u.u_cred;
- u.u_cred = foreigncreds;
-#endif
- }
-#endif /* AFS_NEED_CLIENTCONTEXT */
- if ((com & 0xff) == 15) {
- /* special case prefetch so entire pathname eval occurs in helper process.
- * otherwise, the pioctl call is essentially useless */
-#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- code =
- Prefetch(path, &data, follow,
- foreigncreds ? foreigncreds : credp);
-#else
- code = Prefetch(path, &data, follow, osi_curcred());
-#endif
- vp = NULL;
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- goto rescred;
- }
- if (path) {
- AFS_GUNLOCK();
-#ifdef AFS_AIX41_ENV
- code =
- lookupname(path, USR, follow, NULL, &vp,
- foreigncreds ? foreigncreds : credp);
-#else
-#ifdef AFS_LINUX22_ENV
- code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
- if (!code)
- vp = (struct vnode *)dp->d_inode;
-#else
- code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
-#endif /* AFS_LINUX22_ENV */
-#endif /* AFS_AIX41_ENV */
- AFS_GLOCK();
- if (code) {
- vp = NULL;
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(code);
-#endif
- goto rescred;
- }
- } else
- vp = NULL;
-
- /* now make the call if we were passed no file, or were passed an AFS file */
- if (!vp || IsAfsVnode(vp)) {
-#if defined(AFS_DEC_ENV)
- /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
- * So, we must test in this part of the code. Also, must arrange to
- * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
- * we hold gnodes, whose references hold our vcache entries.
- */
- if (vp) {
- gp = vp; /* remember for "put" */
- vp = (struct vnode *)afs_gntovn(vp); /* get vcache from gp */
- } else
- gp = NULL;
-#elif defined(AFS_SUN5_ENV)
- code = afs_HandlePioctl(vp, com, &data, follow, &credp);
-#elif defined(AFS_AIX41_ENV)
- {
- struct ucred *cred1, *cred2;
-
- if (foreigncreds) {
- cred1 = cred2 = foreigncreds;
- } else {
- cred1 = cred2 = credp;
- }
- code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
- if (cred1 != cred2) {
- /* something changed the creds */
- crset(cred1);
- }
- }
-#elif defined(AFS_HPUX101_ENV)
- {
- struct ucred *cred = p_cred(u.u_procp);
- code = afs_HandlePioctl(vp, com, &data, follow, &cred);
- }
-#elif defined(AFS_SGI_ENV)
- {
- struct cred *credp;
- credp = OSI_GET_CURRENT_CRED();
- code = afs_HandlePioctl(vp, com, &data, follow, &credp);
- }
-#elif defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- code = afs_HandlePioctl(vp, com, &data, follow, &credp);
-#else
- code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
-#endif
- } else {
-#if defined(KERNEL_HAVE_UERROR)
- setuerror(EINVAL);
-#else
- code = EINVAL; /* not in /afs */
-#endif
-#ifdef AFS_DEC_ENV
- if (vp) {
- GRELE(vp);
- vp = NULL;
- }
-#endif
- }
-
- rescred:
-#if defined(AFS_NEED_CLIENTCONTEXT)
- if (foreigncreds) {
-#ifdef AFS_AIX41_ENV
- crset(tmpcred); /* restore original credentials */
-#else
-#if defined(AFS_HPUX101_ENV)
- set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
-#elif defined(AFS_SGI_ENV)
- OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
-#elif !defined(AFS_SUN5_ENV)
- osi_curcred() = tmpcred; /* restore original credentials */
-#endif /* AFS_HPUX101_ENV */
- crfree(foreigncreds);
-#endif /* AIX41 */
- }
-#endif /* AFS_NEED_CLIENTCONTEXT */
- if (vp) {
-#ifdef AFS_LINUX22_ENV
- dput(dp);
-#else
- AFS_RELE(vp); /* put vnode back */
-#endif
- }
- PIOCTL_FREE_CRED();
-#if defined(KERNEL_HAVE_UERROR)
- if (!getuerror())
- setuerror(code);
- return (getuerror());
-#else
- return (code);
-#endif
-}
-
-#define MAXPIOCTLTOKENLEN \
-(3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
-
-int
-afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
- register struct afs_ioctl *ablob, int afollow,
- struct AFS_UCRED **acred)
-{
- struct vcache *avc;
- struct vrequest treq;
- register afs_int32 code;
- register afs_int32 function, device;
- afs_int32 inSize, outSize, outSizeMax;
- char *inData, *outData;
- int (*(*pioctlSw)) ();
- int pioctlSwSize;
- struct afs_fakestat_state fakestate;
-
- avc = avp ? VTOAFS(avp) : NULL;
- afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
- AFS_STATCNT(HandlePioctl);
- if ((code = afs_InitReq(&treq, *acred)))
- return code;
- afs_InitFakeStat(&fakestate);
- if (avc) {
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- return code;
- }
- }
- device = (acom & 0xff00) >> 8;
- switch (device) {
- case 'V': /* Original pioctls */
- pioctlSw = VpioctlSw;
- pioctlSwSize = sizeof(VpioctlSw);
- break;
- case 'C': /* Coordinated/common pioctls */
- pioctlSw = CpioctlSw;
- pioctlSwSize = sizeof(CpioctlSw);
- break;
- default:
- afs_PutFakeStat(&fakestate);
- return EINVAL;
- }
- function = acom & 0xff;
- if (function >= (pioctlSwSize / sizeof(char *))) {
- afs_PutFakeStat(&fakestate);
- return EINVAL; /* out of range */
- }
- inSize = ablob->in_size;
-
- /* Do all range checking before continuing */
- if (inSize > MAXPIOCTLTOKENLEN || inSize < 0 || ablob->out_size < 0)
- return E2BIG;
-
- if (inSize > AFS_LRALLOCSIZ) {
- inData = osi_AllocLargeSpace(inSize+1);
- } else {
- inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- }
- if (!inData)
- return ENOMEM;
- if (inSize > 0) {
- AFS_COPYIN(ablob->in, inData, inSize, code);
- inData[inSize] = '\0';
- } else
- code = 0;
- if (code) {
- if (inSize > AFS_LRALLOCSIZ) {
- osi_Free(inData, inSize+1);
- } else {
- osi_FreeLargeSpace(inData);
- }
- afs_PutFakeStat(&fakestate);
- return code;
- }
- if (function == 8 && device == 'V') { /* PGetTokens */
- outSizeMax = MAXPIOCTLTOKENLEN;
- outData = osi_Alloc(outSizeMax);
- } else {
- outSizeMax = AFS_LRALLOCSIZ;
- outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- }
- if (!outData) {
- if (inSize > AFS_LRALLOCSIZ) {
- osi_Free(inData, inSize+1);
- } else {
- osi_FreeLargeSpace(inData);
- }
- return ENOMEM;
- }
- outSize = 0;
- code =
- (*pioctlSw[function]) (avc, function, &treq, inData, outData, inSize,
- &outSize, acred);
- if (inSize > AFS_LRALLOCSIZ) {
- osi_Free(inData, inSize+1);
- } else {
- osi_FreeLargeSpace(inData);
- }
- if (code == 0 && ablob->out_size > 0) {
- if (outSize > ablob->out_size) {
- code = E2BIG; /* data wont fit in user buffer */
- } else if (outSize) {
- AFS_COPYOUT(outData, ablob->out, outSize, code);
- }
- }
- if (outSizeMax > AFS_LRALLOCSIZ) {
- osi_Free(outData, outSizeMax);
- } else {
- osi_FreeLargeSpace(outData);
- }
- afs_PutFakeStat(&fakestate);
- return afs_CheckCode(code, &treq, 41);
-}
-
-DECL_PIOCTL(PGetFID)
-{
- AFS_STATCNT(PGetFID);
- if (!avc)
- return EINVAL;
- memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
- *aoutSize = sizeof(struct VenusFid);
- return 0;
-}
-
-DECL_PIOCTL(PSetAcl)
-{
- register afs_int32 code;
- struct conn *tconn;
- struct AFSOpaque acl;
- struct AFSVolSync tsync;
- struct AFSFetchStatus OutStatus;
- XSTATS_DECLS;
-
- AFS_STATCNT(PSetAcl);
- if (!avc)
- return EINVAL;
- if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
- return EINVAL;
-
- acl.AFSOpaque_val = ain;
- do {
- tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tconn) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
- &acl, &OutStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
- SHARED_LOCK, NULL));
-
- /* now we've forgotten all of the access info */
- ObtainWriteLock(&afs_xcbhash, 455);
- avc->callback = 0;
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- return code;
-}
-
-int afs_defaultAsynchrony = 0;
-
-DECL_PIOCTL(PStoreBehind)
-{
- afs_int32 code = 0;
- struct sbstruct *sbr;
-
- sbr = (struct sbstruct *)ain;
- if (sbr->sb_default != -1) {
- if (afs_osi_suser(*acred))
- afs_defaultAsynchrony = sbr->sb_default;
- else
- code = EPERM;
- }
-
- if (avc && (sbr->sb_thisfile != -1)) {
- if (afs_AccessOK
- (avc, PRSFS_WRITE | PRSFS_ADMINISTER, areq, DONT_CHECK_MODE_BITS))
- avc->asynchrony = sbr->sb_thisfile;
- else
- code = EACCES;
- }
-
- *aoutSize = sizeof(struct sbstruct);
- sbr = (struct sbstruct *)aout;
- sbr->sb_default = afs_defaultAsynchrony;
- if (avc) {
- sbr->sb_thisfile = avc->asynchrony;
- }
-
- return code;
-}
-
-DECL_PIOCTL(PGCPAGs)
-{
- if (!afs_osi_suser(*acred)) {
- return EACCES;
- }
- afs_gcpags = AFS_GCPAGS_USERDISABLED;
- return 0;
-}
-
-DECL_PIOCTL(PGetAcl)
-{
- struct AFSOpaque acl;
- struct AFSVolSync tsync;
- struct AFSFetchStatus OutStatus;
- afs_int32 code;
- struct conn *tconn;
- struct AFSFid Fid;
- XSTATS_DECLS;
-
- AFS_STATCNT(PGetAcl);
- if (!avc)
- return EINVAL;
- Fid.Volume = avc->fid.Fid.Volume;
- Fid.Vnode = avc->fid.Fid.Vnode;
- Fid.Unique = avc->fid.Fid.Unique;
- if (avc->states & CForeign) {
- /*
- * For a dfs xlator acl we have a special hack so that the
- * xlator will distinguish which type of acl will return. So
- * we currently use the top 2-bytes (vals 0-4) to tell which
- * type of acl to bring back. Horrible hack but this will
- * cause the least number of changes to code size and interfaces.
- */
- if (Fid.Vnode & 0xc0000000)
- return ERANGE;
- Fid.Vnode |= (ainSize << 30);
- }
- acl.AFSOpaque_val = aout;
- do {
- tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tconn) {
- *aout = 0;
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
- RX_AFS_GUNLOCK();
- code = RXAFS_FetchACL(tconn->id, &Fid, &acl, &OutStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHACL,
- SHARED_LOCK, NULL));
-
- if (code == 0) {
- *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
- }
- return code;
-}
-
-DECL_PIOCTL(PNoop)
-{
- AFS_STATCNT(PNoop);
- return 0;
-}
-
-DECL_PIOCTL(PBogus)
-{
- AFS_STATCNT(PBogus);
- return EINVAL;
-}
-
-DECL_PIOCTL(PGetFileCell)
-{
- register struct cell *tcell;
-
- AFS_STATCNT(PGetFileCell);
- if (!avc)
- return EINVAL;
- tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
- if (!tcell)
- return ESRCH;
- strcpy(aout, tcell->cellName);
- afs_PutCell(tcell, READ_LOCK);
- *aoutSize = strlen(aout) + 1;
- return 0;
-}
-
-DECL_PIOCTL(PGetWSCell)
-{
- struct cell *tcell = NULL;
-
- AFS_STATCNT(PGetWSCell);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- tcell = afs_GetPrimaryCell(READ_LOCK);
- if (!tcell) /* no primary cell? */
- return ESRCH;
- strcpy(aout, tcell->cellName);
- *aoutSize = strlen(aout) + 1;
- afs_PutCell(tcell, READ_LOCK);
- return 0;
-}
-
-DECL_PIOCTL(PGetUserCell)
-{
- register afs_int32 i;
- register struct unixuser *tu;
- register struct cell *tcell;
-
- AFS_STATCNT(PGetUserCell);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- /* return the cell name of the primary cell for this user */
- i = UHash(areq->uid);
- ObtainWriteLock(&afs_xuser, 224);
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->uid == areq->uid && (tu->states & UPrimary)) {
- tu->refCount++;
- ReleaseWriteLock(&afs_xuser);
- break;
- }
- }
- if (tu) {
- tcell = afs_GetCell(tu->cell, READ_LOCK);
- afs_PutUser(tu, WRITE_LOCK);
- if (!tcell)
- return ESRCH;
- else {
- strcpy(aout, tcell->cellName);
- afs_PutCell(tcell, READ_LOCK);
- *aoutSize = strlen(aout) + 1; /* 1 for the null */
- }
- } else {
- ReleaseWriteLock(&afs_xuser);
- *aout = 0;
- *aoutSize = 1;
- }
- return 0;
-}
-
-DECL_PIOCTL(PSetTokens)
-{
- afs_int32 i;
- register struct unixuser *tu;
- struct ClearToken clear;
- register struct cell *tcell;
- char *stp;
- int stLen;
- struct vrequest treq;
- afs_int32 flag, set_parent_pag = 0;
-
- AFS_STATCNT(PSetTokens);
- if (!afs_resourceinit_flag) {
- return EIO;
- }
- memcpy((char *)&i, ain, sizeof(afs_int32));
- ain += sizeof(afs_int32);
- stp = ain; /* remember where the ticket is */
- if (i < 0 || i > MAXKTCTICKETLEN)
- return EINVAL; /* malloc may fail */
- stLen = i;
- ain += i; /* skip over ticket */
- memcpy((char *)&i, ain, sizeof(afs_int32));
- ain += sizeof(afs_int32);
- if (i != sizeof(struct ClearToken)) {
- return EINVAL;
- }
- memcpy((char *)&clear, ain, sizeof(struct ClearToken));
- if (clear.AuthHandle == -1)
- clear.AuthHandle = 999; /* more rxvab compat stuff */
- ain += sizeof(struct ClearToken);
- if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
- /* still stuff left? we've got primary flag and cell name. Set these */
- memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
- ain += sizeof(afs_int32); /* skip id field */
- /* rest is cell name, look it up */
- /* some versions of gcc appear to need != 0 in order to get this right */
- if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
- flag &= ~0x8000;
- set_parent_pag = 1;
- }
- tcell = afs_GetCellByName(ain, READ_LOCK);
- if (!tcell)
- goto nocell;
- } else {
- /* default to primary cell, primary id */
- flag = 1; /* primary id */
- tcell = afs_GetPrimaryCell(READ_LOCK);
- if (!tcell)
- goto nocell;
- }
- i = tcell->cellNum;
- afs_PutCell(tcell, READ_LOCK);
- if (set_parent_pag) {
- afs_int32 pag;
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#if defined(AFS_DARWIN_ENV)
- struct proc *p = current_proc(); /* XXX */
-#else
- struct proc *p = curproc; /* XXX */
-#endif
- uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
- p->p_pid, p->p_comm);
- if (!setpag(p, acred, -1, &pag, 1)) {
-#else
-#ifdef AFS_OSF_ENV
- if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
-#else
- if (!setpag(acred, -1, &pag, 1)) {
-#endif
-#endif
- afs_InitReq(&treq, *acred);
- areq = &treq;
- }
- }
- /* now we just set the tokens */
- tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
- tu->vid = clear.ViceId;
- if (tu->stp != NULL) {
- afs_osi_Free(tu->stp, tu->stLen);
- }
- tu->stp = (char *)afs_osi_Alloc(stLen);
- tu->stLen = stLen;
- memcpy(tu->stp, stp, stLen);
- tu->ct = clear;
-#ifndef AFS_NOSTATS
- afs_stats_cmfullperf.authent.TicketUpdates++;
- afs_ComputePAGStats();
-#endif /* AFS_NOSTATS */
- tu->states |= UHasTokens;
- tu->states &= ~UTokensBad;
- afs_SetPrimary(tu, flag);
- tu->tokenTime = osi_Time();
- afs_ResetUserConns(tu);
- afs_PutUser(tu, WRITE_LOCK);
-
- return 0;
-
- nocell:
- {
- int t1;
- t1 = afs_initState;
- if (t1 < 101)
- return EIO;
- else
- return ESRCH;
- }
-}
-
-DECL_PIOCTL(PGetVolumeStatus)
-{
- char volName[32];
- char *offLineMsg = afs_osi_Alloc(256);
- char *motd = afs_osi_Alloc(256);
- register struct conn *tc;
- register afs_int32 code = 0;
- struct VolumeStatus volstat;
- register char *cp;
- char *Name, *OfflineMsg, *MOTD;
- XSTATS_DECLS;
-
- AFS_STATCNT(PGetVolumeStatus);
- if (!avc) {
- code = EINVAL;
- goto out;
- }
- Name = volName;
- OfflineMsg = offLineMsg;
- MOTD = motd;
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
- &Name, &OfflineMsg, &MOTD);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
- SHARED_LOCK, NULL));
-
- if (code)
- goto out;
- /* Copy all this junk into msg->im_data, keeping track of the lengths. */
- cp = aout;
- memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
- cp += sizeof(VolumeStatus);
- strcpy(cp, volName);
- cp += strlen(volName) + 1;
- strcpy(cp, offLineMsg);
- cp += strlen(offLineMsg) + 1;
- strcpy(cp, motd);
- cp += strlen(motd) + 1;
- *aoutSize = (cp - aout);
- out:
- afs_osi_Free(offLineMsg, 256);
- afs_osi_Free(motd, 256);
- return code;
-}
-
-DECL_PIOCTL(PSetVolumeStatus)
-{
- char volName[32];
- char *offLineMsg = afs_osi_Alloc(256);
- char *motd = afs_osi_Alloc(256);
- register struct conn *tc;
- register afs_int32 code = 0;
- struct AFSFetchVolumeStatus volstat;
- struct AFSStoreVolumeStatus storeStat;
- register struct volume *tvp;
- register char *cp;
- XSTATS_DECLS;
-
- AFS_STATCNT(PSetVolumeStatus);
- if (!avc) {
- code = EINVAL;
- goto out;
- }
-
- tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
- if (tvp) {
- if (tvp->states & (VRO | VBackup)) {
- afs_PutVolume(tvp, READ_LOCK);
- code = EROFS;
- goto out;
- }
- afs_PutVolume(tvp, READ_LOCK);
- } else {
- code = ENODEV;
- goto out;
- }
- /* Copy the junk out, using cp as a roving pointer. */
- cp = ain;
- memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
- cp += sizeof(AFSFetchVolumeStatus);
- if (strlen(cp) >= sizeof(volName)) {
- code = E2BIG;
- goto out;
- }
- strcpy(volName, cp);
- cp += strlen(volName) + 1;
- if (strlen(cp) >= sizeof(offLineMsg)) {
- code = E2BIG;
- goto out;
- }
- strcpy(offLineMsg, cp);
- cp += strlen(offLineMsg) + 1;
- if (strlen(cp) >= sizeof(motd)) {
- code = E2BIG;
- goto out;
- }
- strcpy(motd, cp);
- storeStat.Mask = 0;
- if (volstat.MinQuota != -1) {
- storeStat.MinQuota = volstat.MinQuota;
- storeStat.Mask |= AFS_SETMINQUOTA;
- }
- if (volstat.MaxQuota != -1) {
- storeStat.MaxQuota = volstat.MaxQuota;
- storeStat.Mask |= AFS_SETMAXQUOTA;
- }
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume, &storeStat,
- volName, offLineMsg, motd);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
- SHARED_LOCK, NULL));
-
- if (code)
- goto out;
- /* we are sending parms back to make compat. with prev system. should
- * change interface later to not ask for current status, just set new status */
- cp = aout;
- memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
- cp += sizeof(VolumeStatus);
- strcpy(cp, volName);
- cp += strlen(volName) + 1;
- strcpy(cp, offLineMsg);
- cp += strlen(offLineMsg) + 1;
- strcpy(cp, motd);
- cp += strlen(motd) + 1;
- *aoutSize = cp - aout;
- out:
- afs_osi_Free(offLineMsg, 256);
- afs_osi_Free(motd, 256);
- return code;
-}
-
-DECL_PIOCTL(PFlush)
-{
- AFS_STATCNT(PFlush);
- if (!avc)
- return EINVAL;
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
- ObtainWriteLock(&avc->lock, 225);
- ObtainWriteLock(&afs_xcbhash, 456);
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
- ReleaseWriteLock(&afs_xcbhash);
- /* now find the disk cache entries */
- afs_TryToSmush(avc, *acred, 1);
- osi_dnlc_purgedp(avc);
- afs_symhint_inval(avc);
- if (avc->linkData && !(avc->states & CCore)) {
- afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
- avc->linkData = NULL;
- }
- ReleaseWriteLock(&avc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&avc->pvnLock, avc);
-#endif
- return 0;
-}
-
-DECL_PIOCTL(PNewStatMount)
-{
- register afs_int32 code;
- register struct vcache *tvc;
- register struct dcache *tdc;
- struct VenusFid tfid;
- char *bufp;
- struct sysname_info sysState;
- afs_size_t offset, len;
-
- AFS_STATCNT(PNewStatMount);
- if (!avc)
- return EINVAL;
- code = afs_VerifyVCache(avc, areq);
- if (code)
- return code;
- if (vType(avc) != VDIR) {
- return ENOTDIR;
- }
- tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
- if (!tdc)
- return ENOENT;
- Check_AtSys(avc, ain, &sysState, areq);
- ObtainReadLock(&tdc->lock);
- do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
- } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc); /* we're done with the data */
- bufp = sysState.name;
- if (code) {
- goto out;
- }
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = avc->fid.Fid.Volume;
- if (!tfid.Fid.Unique && (avc->states & CForeign)) {
- tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
- } else {
- tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
- }
- if (!tvc) {
- code = ENOENT;
- goto out;
- }
- if (tvc->mvstat != 1) {
- afs_PutVCache(tvc);
- code = EINVAL;
- goto out;
- }
- ObtainWriteLock(&tvc->lock, 226);
- code = afs_HandleLink(tvc, areq);
- if (code == 0) {
- if (tvc->linkData) {
- if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
- code = EINVAL;
- else {
- /* we have the data */
- strcpy(aout, tvc->linkData);
- *aoutSize = strlen(tvc->linkData) + 1;
- }
- } else
- code = EIO;
- }
- ReleaseWriteLock(&tvc->lock);
- afs_PutVCache(tvc);
- out:
- if (sysState.allocked)
- osi_FreeLargeSpace(bufp);
- return code;
-}
-
-DECL_PIOCTL(PGetTokens)
-{
- register struct cell *tcell;
- register afs_int32 i;
- register struct unixuser *tu;
- register char *cp;
- afs_int32 iterator;
- int newStyle;
-
- AFS_STATCNT(PGetTokens);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- /* weird interface. If input parameter is present, it is an integer and
- * we're supposed to return the parm'th tokens for this unix uid.
- * If not present, we just return tokens for cell 1.
- * If counter out of bounds, return EDOM.
- * If no tokens for the particular cell, return ENOTCONN.
- * Also, if this mysterious parm is present, we return, along with the
- * tokens, the primary cell indicator (an afs_int32 0) and the cell name
- * at the end, in that order.
- */
- if ((newStyle = (ainSize > 0))) {
- memcpy((char *)&iterator, ain, sizeof(afs_int32));
- }
- i = UHash(areq->uid);
- ObtainReadLock(&afs_xuser);
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (newStyle) {
- if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
- if (iterator-- == 0)
- break; /* are we done yet? */
- }
- } else {
- if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell))
- break;
- }
- }
- if (tu) {
- /*
- * No need to hold a read lock on each user entry
- */
- tu->refCount++;
- }
- ReleaseReadLock(&afs_xuser);
-
- if (!tu) {
- return EDOM;
- }
- if (((tu->states & UHasTokens) == 0)
- || (tu->ct.EndTimestamp < osi_Time())) {
- tu->states |= (UTokensBad | UNeedsReset);
- afs_PutUser(tu, READ_LOCK);
- return ENOTCONN;
- }
- /* use iterator for temp */
- cp = aout;
- iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
- if (iterator < 56)
- iterator = 56; /* # of bytes we're returning */
- memcpy(cp, (char *)&iterator, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- memcpy(cp, tu->stp, tu->stLen); /* copy out st */
- cp += iterator;
- iterator = sizeof(struct ClearToken);
- memcpy(cp, (char *)&iterator, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
- cp += sizeof(struct ClearToken);
- if (newStyle) {
- /* put out primary id and cell name, too */
- iterator = (tu->states & UPrimary ? 1 : 0);
- memcpy(cp, (char *)&iterator, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- tcell = afs_GetCell(tu->cell, READ_LOCK);
- if (tcell) {
- strcpy(cp, tcell->cellName);
- cp += strlen(tcell->cellName) + 1;
- afs_PutCell(tcell, READ_LOCK);
- } else
- *cp++ = 0;
- }
- *aoutSize = cp - aout;
- afs_PutUser(tu, READ_LOCK);
- return 0;
-}
-
-DECL_PIOCTL(PUnlog)
-{
- register afs_int32 i;
- register struct unixuser *tu;
-
- AFS_STATCNT(PUnlog);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- i = UHash(areq->uid);
- ObtainWriteLock(&afs_xuser, 227);
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->uid == areq->uid) {
- tu->vid = UNDEFVID;
- tu->states &= ~UHasTokens;
- /* security is not having to say you're sorry */
- memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
- tu->refCount++;
- ReleaseWriteLock(&afs_xuser);
- /* We have to drop the lock over the call to afs_ResetUserConns, since
- * it obtains the afs_xvcache lock. We could also keep the lock, and
- * modify ResetUserConns to take parm saying we obtained the lock
- * already, but that is overkill. By keeping the "tu" pointer
- * held over the released lock, we guarantee that we won't lose our
- * place, and that we'll pass over every user conn that existed when
- * we began this call.
- */
- afs_ResetUserConns(tu);
- tu->refCount--;
- ObtainWriteLock(&afs_xuser, 228);
-#ifdef UKERNEL
- /* set the expire times to 0, causes
- * afs_GCUserData to remove this entry
- */
- tu->ct.EndTimestamp = 0;
- tu->tokenTime = 0;
-#endif /* UKERNEL */
- }
- }
- ReleaseWriteLock(&afs_xuser);
- return 0;
-}
-
-DECL_PIOCTL(PMariner)
-{
- afs_int32 newHostAddr;
- afs_int32 oldHostAddr;
-
- AFS_STATCNT(PMariner);
- if (afs_mariner)
- memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost,
- sizeof(afs_int32));
- else
- oldHostAddr = 0xffffffff; /* disabled */
-
- memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
- if (newHostAddr == 0xffffffff) {
- /* disable mariner operations */
- afs_mariner = 0;
- } else if (newHostAddr) {
- afs_mariner = 1;
- afs_marinerHost = newHostAddr;
- }
- memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- return 0;
-}
-
-DECL_PIOCTL(PCheckServers)
-{
- register char *cp = 0;
- register int i;
- register struct server *ts;
- afs_int32 temp, *lp = (afs_int32 *) ain, havecell = 0;
- struct cell *cellp;
- struct chservinfo *pcheck;
-
- AFS_STATCNT(PCheckServers);
-
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- if (*lp == 0x12345678) { /* For afs3.3 version */
- pcheck = (struct chservinfo *)ain;
- if (pcheck->tinterval >= 0) {
- cp = aout;
- memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- if (pcheck->tinterval > 0) {
- if (!afs_osi_suser(*acred))
- return EACCES;
- PROBE_INTERVAL = pcheck->tinterval;
- }
- return 0;
- }
- if (pcheck->tsize)
- havecell = 1;
- temp = pcheck->tflags;
- cp = pcheck->tbuffer;
- } else { /* For pre afs3.3 versions */
- memcpy((char *)&temp, ain, sizeof(afs_int32));
- cp = ain + sizeof(afs_int32);
- if (ainSize > sizeof(afs_int32))
- havecell = 1;
- }
-
- /*
- * 1: fast check, don't contact servers.
- * 2: local cell only.
- */
- if (havecell) {
- /* have cell name, too */
- cellp = afs_GetCellByName(cp, READ_LOCK);
- if (!cellp)
- return ENOENT;
- } else
- cellp = NULL;
- if (!cellp && (temp & 2)) {
- /* use local cell */
- cellp = afs_GetPrimaryCell(READ_LOCK);
- }
- if (!(temp & 1)) { /* if not fast, call server checker routine */
- afs_CheckServers(1, cellp); /* check down servers */
- afs_CheckServers(0, cellp); /* check up servers */
- }
- /* now return the current down server list */
- cp = aout;
- ObtainReadLock(&afs_xserver);
- for (i = 0; i < NSERVERS; i++) {
- for (ts = afs_servers[i]; ts; ts = ts->next) {
- if (cellp && ts->cell != cellp)
- continue; /* cell spec'd and wrong */
- if ((ts->flags & SRVR_ISDOWN)
- && ts->addr->sa_portal != ts->cell->vlport) {
- memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- }
- }
- }
- ReleaseReadLock(&afs_xserver);
- if (cellp)
- afs_PutCell(cellp, READ_LOCK);
- *aoutSize = cp - aout;
- return 0;
-}
-
-DECL_PIOCTL(PCheckVolNames)
-{
- AFS_STATCNT(PCheckVolNames);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- afs_CheckRootVolume();
- afs_CheckVolumeNames(AFS_VOLCHECK_FORCE | AFS_VOLCHECK_EXPIRED |
- AFS_VOLCHECK_BUSY | AFS_VOLCHECK_MTPTS);
- return 0;
-}
-
-DECL_PIOCTL(PCheckAuth)
-{
- int i;
- struct srvAddr *sa;
- struct conn *tc;
- struct unixuser *tu;
- afs_int32 retValue;
-
- AFS_STATCNT(PCheckAuth);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- retValue = 0;
- tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
- if (!tu)
- retValue = EACCES;
- else {
- /* we have a user */
- ObtainReadLock(&afs_xsrvAddr);
- ObtainReadLock(&afs_xconn);
-
- /* any tokens set? */
- if ((tu->states & UHasTokens) == 0)
- retValue = EACCES;
- /* all connections in cell 1 working? */
- for (i = 0; i < NSERVERS; i++) {
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- for (tc = sa->conns; tc; tc = tc->next) {
- if (tc->user == tu && (tu->states & UTokensBad))
- retValue = EACCES;
- }
- }
- }
- ReleaseReadLock(&afs_xsrvAddr);
- ReleaseReadLock(&afs_xconn);
- afs_PutUser(tu, READ_LOCK);
- }
- memcpy(aout, (char *)&retValue, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- return 0;
-}
-
-static int
-Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
- struct AFS_UCRED *acred)
-{
- register char *tp;
- register afs_int32 code;
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- size_t bufferSize;
-#else
- u_int bufferSize;
-#endif
-
- AFS_STATCNT(Prefetch);
- if (!apath)
- return EINVAL;
- tp = osi_AllocLargeSpace(1024);
- AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
- if (code) {
- osi_FreeLargeSpace(tp);
- return code;
- }
- if (afs_BBusy()) { /* do this as late as possible */
- osi_FreeLargeSpace(tp);
- return EWOULDBLOCK; /* pretty close */
- }
- afs_BQueue(BOP_PATH, (struct vcache *)0, 0, 0, acred, (afs_size_t) 0,
- (afs_size_t) 0, tp);
- return 0;
-}
-
-DECL_PIOCTL(PFindVolume)
-{
- register struct volume *tvp;
- register struct server *ts;
- register afs_int32 i;
- register char *cp;
-
- AFS_STATCNT(PFindVolume);
- if (!avc)
- return EINVAL;
- tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
- if (tvp) {
- cp = aout;
- for (i = 0; i < MAXHOSTS; i++) {
- ts = tvp->serverHost[i];
- if (!ts)
- break;
- memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- }
- if (i < MAXHOSTS) {
- /* still room for terminating NULL, add it on */
- ainSize = 0; /* reuse vbl */
- memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- }
- *aoutSize = cp - aout;
- afs_PutVolume(tvp, READ_LOCK);
- return 0;
- }
- return ENODEV;
-}
-
-DECL_PIOCTL(PViceAccess)
-{
- register afs_int32 code;
- afs_int32 temp;
-
- AFS_STATCNT(PViceAccess);
- if (!avc)
- return EINVAL;
- code = afs_VerifyVCache(avc, areq);
- if (code)
- return code;
- memcpy((char *)&temp, ain, sizeof(afs_int32));
- code = afs_AccessOK(avc, temp, areq, CHECK_MODE_BITS);
- if (code)
- return 0;
- else
- return EACCES;
-}
-
-DECL_PIOCTL(PSetCacheSize)
-{
- afs_int32 newValue;
- int waitcnt = 0;
-
- AFS_STATCNT(PSetCacheSize);
- if (!afs_osi_suser(*acred))
- return EACCES;
- /* too many things are setup initially in mem cache version */
- if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
- return EROFS;
- memcpy((char *)&newValue, ain, sizeof(afs_int32));
- if (newValue == 0)
- afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
- else {
- if (newValue < afs_min_cache)
- afs_cacheBlocks = afs_min_cache;
- else
- afs_cacheBlocks = newValue;
- }
- afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
- afs_ComputeCacheParms(); /* recompute basic cache parameters */
- afs_MaybeWakeupTruncateDaemon();
- while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
- afs_osi_Wait(1000, 0, 0);
- afs_MaybeWakeupTruncateDaemon();
- }
- return 0;
-}
-
-#define MAXGCSTATS 16
-DECL_PIOCTL(PGetCacheSize)
-{
- afs_int32 results[MAXGCSTATS];
-
- AFS_STATCNT(PGetCacheSize);
- memset((char *)results, 0, sizeof(results));
- results[0] = afs_cacheBlocks;
- results[1] = afs_blocksUsed;
- memcpy(aout, (char *)results, sizeof(results));
- *aoutSize = sizeof(results);
- return 0;
-}
-
-DECL_PIOCTL(PRemoveCallBack)
-{
- register struct conn *tc;
- register afs_int32 code = 0;
- struct AFSCallBack CallBacks_Array[1];
- struct AFSCBFids theFids;
- struct AFSCBs theCBs;
- XSTATS_DECLS;
-
- AFS_STATCNT(PRemoveCallBack);
- if (!avc)
- return EINVAL;
- if (avc->states & CRO)
- return 0; /* read-only-ness can't change */
- ObtainWriteLock(&avc->lock, 229);
- theFids.AFSCBFids_len = 1;
- theCBs.AFSCBs_len = 1;
- theFids.AFSCBFids_val = (struct AFSFid *)&avc->fid.Fid;
- theCBs.AFSCBs_val = CallBacks_Array;
- CallBacks_Array[0].CallBackType = CB_DROPPED;
- if (avc->callback) {
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
- RX_AFS_GUNLOCK();
- code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- }
- /* don't set code on failure since we wouldn't use it */
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
-
- ObtainWriteLock(&afs_xcbhash, 457);
- afs_DequeueCallback(avc);
- avc->callback = 0;
- avc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- }
- ReleaseWriteLock(&avc->lock);
- return 0;
-}
-
-DECL_PIOCTL(PNewCell)
-{
- /* create a new cell */
- afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic = 0;
- char *newcell = 0, *linkedcell = 0, *tp = ain;
- register afs_int32 code, linkedstate = 0, ls;
- u_short fsport = 0, vlport = 0;
- afs_int32 scount;
-
- AFS_STATCNT(PNewCell);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- memcpy((char *)&magic, tp, sizeof(afs_int32));
- tp += sizeof(afs_int32);
- if (magic != 0x12345678)
- return EINVAL;
-
- /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
- * server addresses while the 3.5 fs newcell command passes
- * MAXHOSTS. To figure out which is which, check if the cellname
- * is good.
- */
- newcell = tp + (MAXCELLHOSTS + 3) * sizeof(afs_int32);
- scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
-
- /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
- memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
- tp += (scount * sizeof(afs_int32));
-
- lp = (afs_int32 *) tp;
- fsport = *lp++;
- vlport = *lp++;
- if (fsport < 1024)
- fsport = 0; /* Privileged ports not allowed */
- if (vlport < 1024)
- vlport = 0; /* Privileged ports not allowed */
- tp += (3 * sizeof(afs_int32));
- newcell = tp;
- if ((ls = *lp) & 1) {
- linkedcell = tp + strlen(newcell) + 1;
- linkedstate |= CLinkedCell;
- }
-
- linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
- code =
- afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
- vlport, (int)0);
- return code;
-}
-
-DECL_PIOCTL(PNewAlias)
-{
- /* create a new cell alias */
- char *tp = ain;
- register afs_int32 code;
- char *realName, *aliasName;
-
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- aliasName = tp;
- tp += strlen(aliasName) + 1;
- realName = tp;
-
- code = afs_NewCellAlias(aliasName, realName);
- *aoutSize = 0;
- return code;
-}
-
-DECL_PIOCTL(PListCells)
-{
- afs_int32 whichCell;
- register struct cell *tcell = 0;
- register afs_int32 i;
- register char *cp, *tp = ain;
-
- AFS_STATCNT(PListCells);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- memcpy((char *)&whichCell, tp, sizeof(afs_int32));
- tp += sizeof(afs_int32);
- tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
- if (tcell) {
- cp = aout;
- memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
- for (i = 0; i < MAXCELLHOSTS; i++) {
- if (tcell->cellHosts[i] == 0)
- break;
- memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip,
- sizeof(afs_int32));
- cp += sizeof(afs_int32);
- }
- cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
- strcpy(cp, tcell->cellName);
- cp += strlen(tcell->cellName) + 1;
- *aoutSize = cp - aout;
- afs_PutCell(tcell, READ_LOCK);
- }
- if (tcell)
- return 0;
- else
- return EDOM;
-}
-
-DECL_PIOCTL(PListAliases)
-{
- afs_int32 whichAlias;
- register struct cell_alias *tcalias = 0;
- register char *cp, *tp = ain;
-
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
- if (ainSize < sizeof(afs_int32))
- return EINVAL;
-
- memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
- tp += sizeof(afs_int32);
-
- tcalias = afs_GetCellAlias(whichAlias);
- if (tcalias) {
- cp = aout;
- strcpy(cp, tcalias->alias);
- cp += strlen(tcalias->alias) + 1;
- strcpy(cp, tcalias->cell);
- cp += strlen(tcalias->cell) + 1;
- *aoutSize = cp - aout;
- afs_PutCellAlias(tcalias);
- }
- if (tcalias)
- return 0;
- else
- return EDOM;
-}
-
-DECL_PIOCTL(PRemoveMount)
-{
- register afs_int32 code;
- char *bufp;
- struct sysname_info sysState;
- afs_size_t offset, len;
- register struct conn *tc;
- register struct dcache *tdc;
- register struct vcache *tvc;
- struct AFSFetchStatus OutDirStatus;
- struct VenusFid tfid;
- struct AFSVolSync tsync;
- XSTATS_DECLS;
-
-
- /* "ain" is the name of the file in this dir to remove */
-
- AFS_STATCNT(PRemoveMount);
- if (!avc)
- return EINVAL;
- code = afs_VerifyVCache(avc, areq);
- if (code)
- return code;
- if (vType(avc) != VDIR)
- return ENOTDIR;
-
- tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
- if (!tdc)
- return ENOENT;
- Check_AtSys(avc, ain, &sysState, areq);
- ObtainReadLock(&tdc->lock);
- do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
- } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
- ReleaseReadLock(&tdc->lock);
- bufp = sysState.name;
- if (code) {
- afs_PutDCache(tdc);
- goto out;
- }
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = avc->fid.Fid.Volume;
- if (!tfid.Fid.Unique && (avc->states & CForeign)) {
- tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
- } else {
- tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
- }
- if (!tvc) {
- code = ENOENT;
- afs_PutDCache(tdc);
- goto out;
- }
- if (tvc->mvstat != 1) {
- afs_PutDCache(tdc);
- afs_PutVCache(tvc);
- code = EINVAL;
- goto out;
- }
- ObtainWriteLock(&tvc->lock, 230);
- code = afs_HandleLink(tvc, areq);
- if (!code) {
- if (tvc->linkData) {
- if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
- code = EINVAL;
- } else
- code = EIO;
- }
- ReleaseWriteLock(&tvc->lock);
- osi_dnlc_purgedp(tvc);
- afs_PutVCache(tvc);
- if (code) {
- afs_PutDCache(tdc);
- goto out;
- }
- ObtainWriteLock(&avc->lock, 231);
- osi_dnlc_remove(avc, bufp, tvc);
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_RemoveFile(tc->id, (struct AFSFid *)&avc->fid.Fid, bufp,
- &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE,
- SHARED_LOCK, NULL));
-
- if (code) {
- if (tdc)
- afs_PutDCache(tdc);
- ReleaseWriteLock(&avc->lock);
- goto out;
- }
- if (tdc) {
- /* we have the thing in the cache */
- ObtainWriteLock(&tdc->lock, 661);
- if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Delete(&tdc->f.inode, bufp);
- if (code) {
- ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
- }
- }
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc); /* drop ref count */
- }
- avc->states &= ~CUnique; /* For the dfs xlator */
- ReleaseWriteLock(&avc->lock);
- code = 0;
- out:
- if (sysState.allocked)
- osi_FreeLargeSpace(bufp);
- return code;
-}
-
-DECL_PIOCTL(PVenusLogging)
-{
- return EINVAL; /* OBSOLETE */
-}
-
-DECL_PIOCTL(PGetCellStatus)
-{
- register struct cell *tcell;
- afs_int32 temp;
-
- AFS_STATCNT(PGetCellStatus);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- tcell = afs_GetCellByName(ain, READ_LOCK);
- if (!tcell)
- return ENOENT;
- temp = tcell->states;
- afs_PutCell(tcell, READ_LOCK);
- memcpy(aout, (char *)&temp, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- return 0;
-}
-
-DECL_PIOCTL(PSetCellStatus)
-{
- register struct cell *tcell;
- afs_int32 temp;
-
- if (!afs_osi_suser(*acred))
- return EACCES;
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- tcell = afs_GetCellByName(ain + 2 * sizeof(afs_int32), WRITE_LOCK);
- if (!tcell)
- return ENOENT;
- memcpy((char *)&temp, ain, sizeof(afs_int32));
- if (temp & CNoSUID)
- tcell->states |= CNoSUID;
- else
- tcell->states &= ~CNoSUID;
- afs_PutCell(tcell, WRITE_LOCK);
- return 0;
-}
-
-DECL_PIOCTL(PFlushVolumeData)
-{
- register afs_int32 i;
- register struct dcache *tdc;
- register struct vcache *tvc;
- register struct volume *tv;
- afs_int32 cell, volume;
-
- AFS_STATCNT(PFlushVolumeData);
- if (!avc)
- return EINVAL;
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- volume = avc->fid.Fid.Volume; /* who to zap */
- cell = avc->fid.Cell;
-
- /*
- * Clear stat'd flag from all vnodes from this volume; this will invalidate all
- * the vcaches associated with the volume.
- */
- ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
-#if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
- VN_HOLD(AFSTOV(tvc));
-#else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- osi_vnhold(tvc, 0);
-#else
- VREFCOUNT_INC(tvc);
-#endif
-#endif
- ReleaseReadLock(&afs_xvcache);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
- ObtainWriteLock(&tvc->lock, 232);
-
- ObtainWriteLock(&afs_xcbhash, 458);
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CDirty);
- ReleaseWriteLock(&afs_xcbhash);
- if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- afs_TryToSmush(tvc, *acred, 1);
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- ObtainReadLock(&afs_xvcache);
- /* our tvc ptr is still good until now */
- AFS_FAST_RELE(tvc);
- }
- }
- }
- ReleaseReadLock(&afs_xvcache);
-
-
- MObtainWriteLock(&afs_xdcache, 328); /* needed if you're going to flush any stuff */
- for (i = 0; i < afs_cacheFiles; i++) {
- if (!(afs_indexFlags[i] & IFEverUsed))
- continue; /* never had any data */
- tdc = afs_GetDSlot(i, NULL);
- if (tdc->refCount <= 1) { /* too high, in use by running sys call */
- ReleaseReadLock(&tdc->tlock);
- if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
- if (!(afs_indexFlags[i] & IFDataMod)) {
- /* if the file is modified, but has a ref cnt of only 1, then
- * someone probably has the file open and is writing into it.
- * Better to skip flushing such a file, it will be brought back
- * immediately on the next write anyway.
- *
- * If we *must* flush, then this code has to be rearranged to call
- * afs_storeAllSegments() first */
- afs_FlushDCache(tdc);
- }
- }
- } else {
- ReleaseReadLock(&tdc->tlock);
- }
- afs_PutDCache(tdc); /* bumped by getdslot */
- }
- MReleaseWriteLock(&afs_xdcache);
-
- ObtainReadLock(&afs_xvolume);
- for (i = 0; i < NVOLS; i++) {
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->volume == volume) {
- afs_ResetVolumeInfo(tv);
- break;
- }
- }
- }
- ReleaseReadLock(&afs_xvolume);
-
- /* probably, a user is doing this, probably, because things are screwed up.
- * maybe it's the dnlc's fault? */
- osi_dnlc_purge();
- return 0;
-}
-
-
-
-DECL_PIOCTL(PGetVnodeXStatus)
-{
- register afs_int32 code;
- struct vcxstat stat;
- afs_int32 mode, i;
-
-/* AFS_STATCNT(PGetVnodeXStatus); */
- if (!avc)
- return EINVAL;
- code = afs_VerifyVCache(avc, areq);
- if (code)
- return code;
- if (vType(avc) == VDIR)
- mode = PRSFS_LOOKUP;
- else
- mode = PRSFS_READ;
- if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
- return EACCES;
- stat.fid = avc->fid;
- hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
- stat.lock = avc->lock;
- stat.parentVnode = avc->parentVnode;
- stat.parentUnique = avc->parentUnique;
- hset(stat.flushDV, avc->flushDV);
- hset(stat.mapDV, avc->mapDV);
- stat.truncPos = avc->truncPos;
- { /* just grab the first two - won't break anything... */
- struct axscache *ac;
-
- for (i = 0, ac = avc->Access; ac && i < CPSIZE; i++, ac = ac->next) {
- stat.randomUid[i] = ac->uid;
- stat.randomAccess[i] = ac->axess;
- }
- }
- stat.callback = afs_data_pointer_to_int32(avc->callback);
- stat.cbExpires = avc->cbExpires;
- stat.anyAccess = avc->anyAccess;
- stat.opens = avc->opens;
- stat.execsOrWriters = avc->execsOrWriters;
- stat.flockCount = avc->flockCount;
- stat.mvstat = avc->mvstat;
- stat.states = avc->states;
- memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
- *aoutSize = sizeof(struct vcxstat);
- return 0;
-}
-
-
-/* We require root for local sysname changes, but not for remote */
-/* (since we don't really believe remote uids anyway) */
- /* outname[] shouldn't really be needed- this is left as an excercise */
- /* for the reader. */
-DECL_PIOCTL(PSetSysName)
-{
- char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
- int setsysname, foundname = 0;
- register struct afs_exporter *exporter;
- register struct unixuser *au;
- register afs_int32 pag, error;
- int t, count, num = 0;
- char **sysnamelist[MAXSYSNAME];
-
- AFS_STATCNT(PSetSysName);
- if (!afs_globalVFS) {
- /* Afsd is NOT running; disable it */
-#if defined(KERNEL_HAVE_UERROR)
- return (setuerror(EINVAL), EINVAL);
-#else
- return (EINVAL);
-#endif
- }
- memset(inname, 0, MAXSYSNAME);
- memcpy((char *)&setsysname, ain, sizeof(afs_int32));
- ain += sizeof(afs_int32);
- if (setsysname) {
-
- /* Check my args */
- if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
- return EINVAL;
- cp2 = ain;
- for (cp = ain, count = 0; count < setsysname; count++) {
- /* won't go past end of ain since maxsysname*num < ain length */
- t = strlen(cp);
- if (t >= MAXSYSNAME || t <= 0)
- return EINVAL;
- /* check for names that can shoot us in the foot */
- if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
- return EINVAL;
- cp += t + 1;
- }
- /* args ok */
-
- /* inname gets first entry in case we're being a translator */
- t = strlen(ain);
- memcpy(inname, ain, t + 1); /* include terminating null */
- ain += t + 1;
- num = count;
- }
- if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
- pag = PagInCred(*acred);
- if (pag == NOPAG) {
- return EINVAL; /* Better than panicing */
- }
- if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
- return EINVAL; /* Better than panicing */
- }
- if (!(exporter = au->exporter)) {
- afs_PutUser(au, READ_LOCK);
- return EINVAL; /* Better than panicing */
- }
- error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), sysnamelist,
- &num);
- if (error) {
- if (error == ENODEV)
- foundname = 0; /* sysname not set yet! */
- else {
- afs_PutUser(au, READ_LOCK);
- return error;
- }
- } else {
- foundname = num;
- strcpy(outname, (*sysnamelist)[0]);
- }
- afs_PutUser(au, READ_LOCK);
- } else {
- /* Not xlating, so local case */
- if (!afs_sysname)
- osi_Panic("PSetSysName: !afs_sysname\n");
- if (!setsysname) { /* user just wants the info */
- strcpy(outname, afs_sysname);
- foundname = afs_sysnamecount;
- *sysnamelist = afs_sysnamelist;
- } else { /* Local guy; only root can change sysname */
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- /* clear @sys entries from the dnlc, once afs_lookup can
- * do lookups of @sys entries and thinks it can trust them */
- /* privs ok, store the entry, ... */
- strcpy(afs_sysname, inname);
- if (setsysname > 1) { /* ... or list */
- cp = ain;
- for (count = 1; count < setsysname; ++count) {
- if (!afs_sysnamelist[count])
- osi_Panic
- ("PSetSysName: no afs_sysnamelist entry to write\n");
- t = strlen(cp);
- memcpy(afs_sysnamelist[count], cp, t + 1); /* include null */
- cp += t + 1;
- }
- }
- afs_sysnamecount = setsysname;
- }
- }
- if (!setsysname) {
- cp = aout; /* not changing so report back the count and ... */
- memcpy(cp, (char *)&foundname, sizeof(afs_int32));
- cp += sizeof(afs_int32);
- if (foundname) {
- strcpy(cp, outname); /* ... the entry, ... */
- cp += strlen(outname) + 1;
- for (count = 1; count < foundname; ++count) { /* ... or list. */
- if (!(*sysnamelist)[count])
- osi_Panic
- ("PSetSysName: no afs_sysnamelist entry to read\n");
- t = strlen((*sysnamelist)[count]);
- if (t >= MAXSYSNAME)
- osi_Panic("PSetSysName: sysname entry garbled\n");
- strcpy(cp, (*sysnamelist)[count]);
- cp += t + 1;
- }
- }
- *aoutSize = cp - aout;
- }
- return 0;
-}
-
-/* sequential search through the list of touched cells is not a good
- * long-term solution here. For small n, though, it should be just
- * fine. Should consider special-casing the local cell for large n.
- * Likewise for PSetSPrefs.
- *
- * s - number of ids in array l[] -- NOT index of last id
- * l - array of cell ids which have volumes that need to be sorted
- * vlonly - sort vl servers or file servers?
- */
-static void *
-ReSortCells_cb(struct cell *cell, void *arg)
-{
- afs_int32 *p = (afs_int32 *) arg;
- afs_int32 *l = p + 1;
- int i, s = p[0];
-
- for (i = 0; i < s; i++) {
- if (l[i] == cell->cellNum) {
- ObtainWriteLock(&cell->lock, 690);
- afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
- ReleaseWriteLock(&cell->lock);
- }
- }
-
- return NULL;
-}
-
-static void
-ReSortCells(int s, afs_int32 * l, int vlonly)
-{
- int i;
- struct volume *j;
- register int k;
-
- if (vlonly) {
- afs_int32 *p;
- p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
- p[0] = s;
- memcpy(p + 1, l, s * sizeof(afs_int32));
- afs_TraverseCells(&ReSortCells_cb, p);
- afs_osi_Free(p, sizeof(afs_int32) * (s + 1));
- return;
- }
-
- ObtainReadLock(&afs_xvolume);
- for (i = 0; i < NVOLS; i++) {
- for (j = afs_volumes[i]; j; j = j->next) {
- for (k = 0; k < s; k++)
- if (j->cell == l[k]) {
- ObtainWriteLock(&j->lock, 233);
- afs_SortServers(j->serverHost, MAXHOSTS);
- ReleaseWriteLock(&j->lock);
- break;
- }
- }
- }
- ReleaseReadLock(&afs_xvolume);
-}
-
-
-static int debugsetsp = 0;
-static int
-afs_setsprefs(sp, num, vlonly)
- struct spref *sp;
- unsigned int num;
- unsigned int vlonly;
-{
- struct srvAddr *sa;
- int i, j, k, matches, touchedSize;
- struct server *srvr = NULL;
- afs_int32 touched[34];
- int isfs;
-
- touchedSize = 0;
- for (k = 0; k < num; sp++, k++) {
- if (debugsetsp) {
- printf("sp host=%x, rank=%d\n", sp->host.s_addr, sp->rank);
- }
- matches = 0;
- ObtainReadLock(&afs_xserver);
-
- i = SHash(sp->host.s_addr);
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- if (sa->sa_ip == sp->host.s_addr) {
- srvr = sa->server;
- isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
- || (sa->sa_portal == AFS_FSPORT);
- if ((!vlonly && isfs) || (vlonly && !isfs)) {
- matches++;
- break;
- }
- }
- }
-
- if (sa && matches) { /* found one! */
- if (debugsetsp) {
- printf("sa ip=%x, ip_rank=%d\n", sa->sa_ip, sa->sa_iprank);
- }
- sa->sa_iprank = sp->rank + afs_randomMod15();
- afs_SortOneServer(sa->server);
-
- if (srvr->cell) {
- /* if we don't know yet what cell it's in, this is moot */
- for (j = touchedSize - 1;
- j >= 0 && touched[j] != srvr->cell->cellNum; j--)
- /* is it in our list of touched cells ? */ ;
- if (j < 0) { /* no, it's not */
- touched[touchedSize++] = srvr->cell->cellNum;
- if (touchedSize >= 32) { /* watch for ovrflow */
- ReleaseReadLock(&afs_xserver);
- ReSortCells(touchedSize, touched, vlonly);
- touchedSize = 0;
- ObtainReadLock(&afs_xserver);
- }
- }
- }
- }
-
- ReleaseReadLock(&afs_xserver);
- /* if we didn't find one, start to create one. */
- /* Note that it doesn't have a cell yet... */
- if (!matches) {
- afs_uint32 temp = sp->host.s_addr;
- srvr =
- afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
- WRITE_LOCK, (afsUUID *) 0, 0);
- srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
- afs_PutServer(srvr, WRITE_LOCK);
- }
- } /* for all cited preferences */
-
- ReSortCells(touchedSize, touched, vlonly);
- return 0;
-}
-
- /* Note that this may only be performed by the local root user.
- */
-DECL_PIOCTL(PSetSPrefs)
-{
- struct setspref *ssp;
- AFS_STATCNT(PSetSPrefs);
-
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- if (ainSize < sizeof(struct setspref))
- return EINVAL;
-
- ssp = (struct setspref *)ain;
- if (ainSize < sizeof(struct spref) * ssp->num_servers)
- return EINVAL;
-
- afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
- (ssp->flags & DBservers));
- return 0;
-}
-
-DECL_PIOCTL(PSetSPrefs33)
-{
- struct spref *sp;
- AFS_STATCNT(PSetSPrefs);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- sp = (struct spref *)ain;
- afs_setsprefs(sp, ainSize / (sizeof(struct spref)), 0 /*!vlonly */ );
- return 0;
-}
-
-/* some notes on the following code...
- * in the hash table of server structs, all servers with the same IP address
- * will be on the same overflow chain.
- * This could be sped slightly in some circumstances by having it cache the
- * immediately previous slot in the hash table and some supporting information
- * Only reports file servers now.
- */
-DECL_PIOCTL(PGetSPrefs)
-{
- struct sprefrequest *spin; /* input */
- struct sprefinfo *spout; /* output */
- struct spref *srvout; /* one output component */
- int i, j; /* counters for hash table traversal */
- struct server *srvr; /* one of CM's server structs */
- struct srvAddr *sa;
- int vlonly; /* just return vlservers ? */
- int isfs;
-
- AFS_STATCNT(PGetSPrefs);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
-
- if (ainSize < sizeof(struct sprefrequest_33)) {
- return ENOENT;
- } else {
- spin = ((struct sprefrequest *)ain);
- }
-
- if (ainSize > sizeof(struct sprefrequest_33)) {
- vlonly = (spin->flags & DBservers);
- } else
- vlonly = 0;
-
- /* struct sprefinfo includes 1 server struct... that size gets added
- * in during the loop that follows.
- */
- *aoutSize = sizeof(struct sprefinfo) - sizeof(struct spref);
- spout = (struct sprefinfo *)aout;
- spout->next_offset = spin->offset;
- spout->num_servers = 0;
- srvout = spout->servers;
-
- ObtainReadLock(&afs_xserver);
- for (i = 0, j = 0; j < NSERVERS; j++) { /* sift through hash table */
- for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
- if (spin->offset > (unsigned short)i) {
- continue; /* catch up to where we left off */
- }
- spout->next_offset++;
-
- srvr = sa->server;
- isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
- || (sa->sa_portal == AFS_FSPORT);
-
- if ((vlonly && isfs) || (!vlonly && !isfs)) {
- /* only report ranks for vl servers */
- continue;
- }
-
- srvout->host.s_addr = sa->sa_ip;
- srvout->rank = sa->sa_iprank;
- *aoutSize += sizeof(struct spref);
- spout->num_servers++;
- srvout++;
-
- if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
- ReleaseReadLock(&afs_xserver); /* no more room! */
- return 0;
- }
- }
- }
- ReleaseReadLock(&afs_xserver);
-
- spout->next_offset = 0; /* start over from the beginning next time */
- return 0;
-}
-
-/* Enable/Disable the specified exporter. Must be root to disable an exporter */
-int afs_NFSRootOnly = 1;
-DECL_PIOCTL(PExportAfs)
-{
- afs_int32 export, newint =
- 0, type, changestate, handleValue, convmode, pwsync, smounts;
- register struct afs_exporter *exporter;
-
- AFS_STATCNT(PExportAfs);
- memcpy((char *)&handleValue, ain, sizeof(afs_int32));
- type = handleValue >> 24;
- if (type == 0x71) {
- newint = 1;
- type = 1; /* nfs */
- }
- exporter = exporter_find(type);
- if (newint) {
- export = handleValue & 3;
- changestate = handleValue & 0xff;
- smounts = (handleValue >> 2) & 3;
- pwsync = (handleValue >> 4) & 3;
- convmode = (handleValue >> 6) & 3;
- } else {
- changestate = (handleValue >> 16) & 0x1;
- convmode = (handleValue >> 16) & 0x2;
- pwsync = (handleValue >> 16) & 0x4;
- smounts = (handleValue >> 16) & 0x8;
- export = handleValue & 0xff;
- }
- if (!exporter) {
- /* Failed finding desired exporter; */
- return ENODEV;
- }
- if (!changestate) {
- handleValue = exporter->exp_states;
- memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- } else {
- if (!afs_osi_suser(*acred))
- return EACCES; /* Only superuser can do this */
- if (newint) {
- if (export & 2) {
- if (export & 1)
- exporter->exp_states |= EXP_EXPORTED;
- else
- exporter->exp_states &= ~EXP_EXPORTED;
- }
- if (convmode & 2) {
- if (convmode & 1)
- exporter->exp_states |= EXP_UNIXMODE;
- else
- exporter->exp_states &= ~EXP_UNIXMODE;
- }
- if (pwsync & 2) {
- if (pwsync & 1)
- exporter->exp_states |= EXP_PWSYNC;
- else
- exporter->exp_states &= ~EXP_PWSYNC;
- }
- if (smounts & 2) {
- if (smounts & 1) {
- afs_NFSRootOnly = 0;
- exporter->exp_states |= EXP_SUBMOUNTS;
- } else {
- afs_NFSRootOnly = 1;
- exporter->exp_states &= ~EXP_SUBMOUNTS;
- }
- }
- handleValue = exporter->exp_states;
- memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- } else {
- if (export)
- exporter->exp_states |= EXP_EXPORTED;
- else
- exporter->exp_states &= ~EXP_EXPORTED;
- if (convmode)
- exporter->exp_states |= EXP_UNIXMODE;
- else
- exporter->exp_states &= ~EXP_UNIXMODE;
- if (pwsync)
- exporter->exp_states |= EXP_PWSYNC;
- else
- exporter->exp_states &= ~EXP_PWSYNC;
- if (smounts) {
- afs_NFSRootOnly = 0;
- exporter->exp_states |= EXP_SUBMOUNTS;
- } else {
- afs_NFSRootOnly = 1;
- exporter->exp_states &= ~EXP_SUBMOUNTS;
- }
- }
- }
-
- return 0;
-}
-
-DECL_PIOCTL(PGag)
-{
- struct gaginfo *gagflags;
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- gagflags = (struct gaginfo *)ain;
- afs_showflags = gagflags->showflags;
-
- return 0;
-}
-
-
-DECL_PIOCTL(PTwiddleRx)
-{
- struct rxparams *rxp;
-
- if (!afs_osi_suser(*acred))
- return EACCES;
-
- rxp = (struct rxparams *)ain;
-
- if (rxp->rx_initReceiveWindow)
- rx_initReceiveWindow = rxp->rx_initReceiveWindow;
- if (rxp->rx_maxReceiveWindow)
- rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
- if (rxp->rx_initSendWindow)
- rx_initSendWindow = rxp->rx_initSendWindow;
- if (rxp->rx_maxSendWindow)
- rx_maxSendWindow = rxp->rx_maxSendWindow;
- if (rxp->rxi_nSendFrags)
- rxi_nSendFrags = rxp->rxi_nSendFrags;
- if (rxp->rxi_nRecvFrags)
- rxi_nRecvFrags = rxp->rxi_nRecvFrags;
- if (rxp->rxi_OrphanFragSize)
- rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
- if (rxp->rx_maxReceiveSize) {
- rx_maxReceiveSize = rxp->rx_maxReceiveSize;
- rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
- }
- if (rxp->rx_MyMaxSendSize)
- rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
-
- return 0;
-}
-
-DECL_PIOCTL(PGetInitParams)
-{
- if (sizeof(struct cm_initparams) > PIGGYSIZE)
- return E2BIG;
-
- memcpy(aout, (char *)&cm_initParams, sizeof(struct cm_initparams));
- *aoutSize = sizeof(struct cm_initparams);
- return 0;
-}
-
-#ifdef AFS_SGI65_ENV
-/* They took crget() from us, so fake it. */
-static cred_t *
-crget(void)
-{
- cred_t *cr;
- cr = crdup(get_current_cred());
- memset((char *)cr, 0, sizeof(cred_t));
-#if CELL || CELL_PREPARE
- cr->cr_id = -1;
-#endif
- return cr;
-}
-#endif
-
-DECL_PIOCTL(PGetRxkcrypt)
-{
- memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
- *aoutSize = sizeof(afs_int32);
- return 0;
-}
-
-DECL_PIOCTL(PSetRxkcrypt)
-{
- afs_int32 tmpval;
-
- if (!afs_osi_suser(*acred))
- return EPERM;
- if (ainSize != sizeof(afs_int32) || ain == NULL)
- return EINVAL;
- memcpy((char *)&tmpval, ain, sizeof(afs_int32));
- /* if new mappings added later this will need to be changed */
- if (tmpval != 0 && tmpval != 1)
- return EINVAL;
- cryptall = tmpval;
- return 0;
-}
-
-#ifdef AFS_NEED_CLIENTCONTEXT
-/*
- * Create new credentials to correspond to a remote user with given
- * <hostaddr, uid, g0, g1>. This allows a server running as root to
- * provide pioctl (and other) services to foreign clients (i.e. nfs
- * clients) by using this call to `become' the client.
- */
-#define PSETPAG 110
-#define PIOCTL_HEADER 6
-static int
-HandleClientContext(struct afs_ioctl *ablob, int *com,
- struct AFS_UCRED **acred, struct AFS_UCRED *credp)
-{
- char *ain, *inData;
- afs_uint32 hostaddr;
- afs_int32 uid, g0, g1, i, code, pag, exporter_type;
- struct afs_exporter *exporter, *outexporter;
- struct AFS_UCRED *newcred;
- struct unixuser *au;
-
-#if defined(AFS_SGIMP_ENV)
- osi_Assert(ISAFS_GLOCK());
-#endif
- AFS_STATCNT(HandleClientContext);
- if (ablob->in_size < PIOCTL_HEADER * sizeof(afs_int32)) {
- /* Must at least include the PIOCTL_HEADER header words required by the protocol */
- return EINVAL; /* Too small to be good */
- }
- ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER * sizeof(afs_int32), code);
- if (code) {
- osi_FreeLargeSpace(inData);
- return code;
- }
-
- /* Extract information for remote user */
- hostaddr = *((afs_uint32 *) ain);
- ain += sizeof(hostaddr);
- uid = *((afs_uint32 *) ain);
- ain += sizeof(uid);
- g0 = *((afs_uint32 *) ain);
- ain += sizeof(g0);
- g1 = *((afs_uint32 *) ain);
- ain += sizeof(g1);
- *com = *((afs_uint32 *) ain);
- ain += sizeof(afs_int32);
- exporter_type = *((afs_uint32 *) ain); /* In case we support more than NFS */
-
- /*
- * Of course, one must be root for most of these functions, but
- * we'll allow (for knfs) you to set things if the pag is 0 and
- * you're setting tokens or unlogging.
- */
- i = (*com) & 0xff;
- if (!afs_osi_suser(credp)) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI64_ENV)
- /* Since SGI's suser() returns explicit failure after the call.. */
- u.u_error = 0;
-#endif
- /* check for acceptable opcodes for normal folks, which are, so far,
- * set tokens and unlog.
- */
- if (i != 9 && i != 3 && i != 38 && i != 8) {
- osi_FreeLargeSpace(inData);
- return EACCES;
- }
- }
-
- ablob->in_size -= PIOCTL_HEADER * sizeof(afs_int32);
- ablob->in += PIOCTL_HEADER * sizeof(afs_int32);
- osi_FreeLargeSpace(inData);
- if (uid == 0) {
- /*
- * We map uid 0 to nobody to match the mapping that the nfs
- * server does and to ensure that the suser() calls in the afs
- * code fails for remote client roots.
- */
- uid = afs_nobody; /* NFS_NOBODY == -2 */
- }
- newcred = crget();
-#ifdef AFS_AIX41_ENV
- setuerror(0);
-#endif
- newcred->cr_gid = RMTUSER_REQ;
-#ifdef AFS_AIX51_ENV
- newcred->cr_groupset.gs_union.un_groups[0] = g0;
- newcred->cr_groupset.gs_union.un_groups[1] = g1;
-#else
- newcred->cr_groups[0] = g0;
- newcred->cr_groups[1] = g1;
-#endif
-#ifdef AFS_AIX_ENV
- newcred->cr_ngrps = 2;
-#else
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
- newcred->cr_ngroups = 2;
-#else
- for (i = 2; i < NGROUPS; i++)
- newcred->cr_groups[i] = NOGROUP;
-#endif
-#endif
-#if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
- afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
-#endif
- if (!(exporter = exporter_find(exporter_type))) {
- /* Exporter wasn't initialized or an invalid exporter type */
- crfree(newcred);
- return EINVAL;
- }
- if (exporter->exp_states & EXP_PWSYNC) {
- if (uid != credp->cr_uid) {
- crfree(newcred);
- return ENOEXEC; /* XXX Find a better errno XXX */
- }
- }
- newcred->cr_uid = uid; /* Only temporary */
- code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
- /* The client's pag is the only unique identifier for it */
- newcred->cr_uid = pag;
- *acred = newcred;
- if (!code && *com == PSETPAG) {
- /* Special case for 'setpag' */
- afs_uint32 pagvalue = genpag();
-
- au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
- /*
- * Note that we leave the 'outexporter' struct held so it won't
- * dissappear on us
- */
- au->exporter = outexporter;
- if (ablob->out_size >= 4) {
- AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32),
- code);
- }
- afs_PutUser(au, WRITE_LOCK);
- if (code)
- return code;
- return PSETPAG; /* Special return for setpag */
- } else if (!code) {
- EXP_RELE(outexporter);
- }
- return code;
-}
-#endif /* AFS_NEED_CLIENTCONTEXT */
-
-/* get all interface addresses of this client */
-
-DECL_PIOCTL(PGetCPrefs)
-{
- struct sprefrequest *spin; /* input */
- struct sprefinfo *spout; /* output */
- struct spref *srvout; /* one output component */
- int maxNumber;
- int i, j;
-
- AFS_STATCNT(PGetCPrefs);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- if (ainSize < sizeof(struct sprefrequest))
- return EINVAL;
-
- spin = (struct sprefrequest *)ain;
- spout = (struct sprefinfo *)aout;
-
- maxNumber = spin->num_servers; /* max addrs this time */
- srvout = spout->servers;
-
- ObtainReadLock(&afs_xinterface);
-
- /* copy out the client interface information from the
- ** kernel data structure "interface" to the output buffer
- */
- for (i = spin->offset, j = 0; (i < afs_cb_interface.numberOfInterfaces)
- && (j < maxNumber); i++, j++, srvout++)
- srvout->host.s_addr = afs_cb_interface.addr_in[i];
-
- spout->num_servers = j;
- *aoutSize = sizeof(struct sprefinfo) + (j - 1) * sizeof(struct spref);
-
- if (i >= afs_cb_interface.numberOfInterfaces)
- spout->next_offset = 0; /* start from beginning again */
- else
- spout->next_offset = spin->offset + j;
-
- ReleaseReadLock(&afs_xinterface);
- return 0;
-}
-
-DECL_PIOCTL(PSetCPrefs)
-{
- struct setspref *sin;
- int i;
-
- AFS_STATCNT(PSetCPrefs);
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- sin = (struct setspref *)ain;
-
- if (ainSize < sizeof(struct setspref))
- return EINVAL;
-#if 0 /* num_servers is unsigned */
- if (sin->num_servers < 0)
- return EINVAL;
-#endif
- if (sin->num_servers > AFS_MAX_INTERFACE_ADDR)
- return ENOMEM;
-
- ObtainWriteLock(&afs_xinterface, 412);
- afs_cb_interface.numberOfInterfaces = sin->num_servers;
- for (i = 0; (unsigned short)i < sin->num_servers; i++)
- afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
-
- ReleaseWriteLock(&afs_xinterface);
- return 0;
-}
-
-DECL_PIOCTL(PFlushMount)
-{
- register afs_int32 code;
- register struct vcache *tvc;
- register struct dcache *tdc;
- struct VenusFid tfid;
- char *bufp;
- struct sysname_info sysState;
- afs_size_t offset, len;
-
- AFS_STATCNT(PFlushMount);
- if (!avc)
- return EINVAL;
- code = afs_VerifyVCache(avc, areq);
- if (code)
- return code;
- if (vType(avc) != VDIR) {
- return ENOTDIR;
- }
- tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
- if (!tdc)
- return ENOENT;
- Check_AtSys(avc, ain, &sysState, areq);
- ObtainReadLock(&tdc->lock);
- do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
- } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc); /* we're done with the data */
- bufp = sysState.name;
- if (code) {
- goto out;
- }
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = avc->fid.Fid.Volume;
- if (!tfid.Fid.Unique && (avc->states & CForeign)) {
- tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
- } else {
- tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
- }
- if (!tvc) {
- code = ENOENT;
- goto out;
- }
- if (tvc->mvstat != 1) {
- afs_PutVCache(tvc);
- code = EINVAL;
- goto out;
- }
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
- ObtainWriteLock(&tvc->lock, 649);
- ObtainWriteLock(&afs_xcbhash, 650);
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
- ReleaseWriteLock(&afs_xcbhash);
- /* now find the disk cache entries */
- afs_TryToSmush(tvc, *acred, 1);
- osi_dnlc_purgedp(tvc);
- afs_symhint_inval(tvc);
- if (tvc->linkData && !(tvc->states & CCore)) {
- afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
- tvc->linkData = NULL;
- }
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- afs_PutVCache(tvc);
- out:
- if (sysState.allocked)
- osi_FreeLargeSpace(bufp);
- return code;
-}
-
-DECL_PIOCTL(PRxStatProc)
-{
- int code = 0;
- afs_int32 flags;
-
- if (!afs_osi_suser(*acred)) {
- code = EACCES;
- goto out;
- }
- if (ainSize != sizeof(afs_int32)) {
- code = EINVAL;
- goto out;
- }
- memcpy((char *)&flags, ain, sizeof(afs_int32));
- if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
- code = EINVAL;
- goto out;
- }
- if (flags & AFSCALL_RXSTATS_ENABLE) {
- rx_enableProcessRPCStats();
- }
- if (flags & AFSCALL_RXSTATS_DISABLE) {
- rx_disableProcessRPCStats();
- }
- if (flags & AFSCALL_RXSTATS_CLEAR) {
- rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
- }
- out:
- *aoutSize = 0;
- return code;
-}
-
-
-DECL_PIOCTL(PRxStatPeer)
-{
- int code = 0;
- afs_int32 flags;
-
- if (!afs_osi_suser(*acred)) {
- code = EACCES;
- goto out;
- }
- if (ainSize != sizeof(afs_int32)) {
- code = EINVAL;
- goto out;
- }
- memcpy((char *)&flags, ain, sizeof(afs_int32));
- if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
- code = EINVAL;
- goto out;
- }
- if (flags & AFSCALL_RXSTATS_ENABLE) {
- rx_enablePeerRPCStats();
- }
- if (flags & AFSCALL_RXSTATS_DISABLE) {
- rx_disablePeerRPCStats();
- }
- if (flags & AFSCALL_RXSTATS_CLEAR) {
- rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
- }
- out:
- *aoutSize = 0;
- return code;
-}
-
-DECL_PIOCTL(PPrefetchFromTape)
-{
- register afs_int32 code, code1;
- afs_int32 bytes;
- struct conn *tc;
- struct rx_call *tcall;
- struct AFSVolSync tsync;
- struct AFSFetchStatus OutStatus;
- struct AFSCallBack CallBack;
- struct VenusFid tfid;
- struct AFSFid *Fid;
- struct vcache *tvc;
-
- AFS_STATCNT(PSetAcl);
- if (!avc)
- return EINVAL;
-
- if (ain && (ainSize == 3 * sizeof(afs_int32)))
- Fid = (struct AFSFid *)ain;
- else
- Fid = &avc->fid.Fid;
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = Fid->Volume;
- tfid.Fid.Vnode = Fid->Vnode;
- tfid.Fid.Unique = Fid->Unique;
-
- tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
- if (!tvc) {
- afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &avc->fid);
- return ENOENT;
- }
- afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &tvc->fid);
-
- do {
- tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
- if (tc) {
-
- RX_AFS_GUNLOCK();
- tcall = rx_NewCall(tc->id);
- code =
- StartRXAFS_FetchData(tcall, (struct AFSFid *)&tvc->fid.Fid, 0,
- 0);
- if (!code) {
- bytes = rx_Read(tcall, (char *)aout, sizeof(afs_int32));
- code =
- EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
- }
- code1 = rx_EndCall(tcall, code);
- RX_AFS_GLOCK();
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &tvc->fid, areq, AFS_STATS_FS_RPCIDX_RESIDENCYRPCS,
- SHARED_LOCK, NULL));
- /* This call is done only to have the callback things handled correctly */
- afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
- afs_PutVCache(tvc);
-
- if (!code) {
- *aoutSize = sizeof(afs_int32);
- }
- return code;
-}
-
-DECL_PIOCTL(PResidencyCmd)
-{
- register afs_int32 code;
- struct conn *tc;
- struct vcache *tvc;
- struct ResidencyCmdInputs *Inputs;
- struct ResidencyCmdOutputs *Outputs;
- struct VenusFid tfid;
- struct AFSFid *Fid;
-
- Inputs = (struct ResidencyCmdInputs *)ain;
- Outputs = (struct ResidencyCmdOutputs *)aout;
- if (!avc)
- return EINVAL;
- if (!ain || ainSize != sizeof(struct ResidencyCmdInputs))
- return EINVAL;
-
- Fid = &Inputs->fid;
- if (!Fid->Volume)
- Fid = &avc->fid.Fid;
-
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = Fid->Volume;
- tfid.Fid.Vnode = Fid->Vnode;
- tfid.Fid.Unique = Fid->Unique;
-
- tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
- afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_INT32, Inputs->command, ICL_TYPE_FID, &tfid);
- if (!tvc)
- return ENOENT;
-
- if (Inputs->command) {
- do {
- tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
- if (tc) {
- RX_AFS_GUNLOCK();
- code =
- RXAFS_ResidencyCmd(tc->id, Fid, Inputs,
- (struct ResidencyCmdOutputs *)aout);
- RX_AFS_GLOCK();
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &tvc->fid, areq,
- AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK, NULL));
- /* This call is done to have the callback things handled correctly */
- afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
- } else { /* just a status request, return also link data */
- code = 0;
- Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
- Outputs->chars[0] = 0;
- if (vType(tvc) == VLNK) {
- ObtainWriteLock(&tvc->lock, 555);
- if (afs_HandleLink(tvc, areq) == 0)
- strncpy((char *)&Outputs->chars, tvc->linkData, MAXCMDCHARS);
- ReleaseWriteLock(&tvc->lock);
- }
- }
-
- afs_PutVCache(tvc);
-
- if (!code) {
- *aoutSize = sizeof(struct ResidencyCmdOutputs);
- }
- return code;
-}
+++ /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
- */
-
-#ifndef _AFS_PROTOTYPES_H_
-#define _AFS_PROTOTYPES_H_
-
-/* afs_analyze.c */
-extern void init_et_to_sys_error(void);
-extern void afs_FinalizeReq(struct vrequest *areq);
-extern int afs_Analyze(register struct conn *aconn, afs_int32 acode,
- struct VenusFid *afid, register struct vrequest *areq,
- int op, afs_int32 locktype, struct cell *cellp);
-extern int afs_CheckCode(afs_int32 acode, struct vrequest *areq, int where);
-extern void afs_CopyError(register struct vrequest *afrom,
- register struct vrequest *ato);
-extern void init_sys_error_to_et(void);
-
-/* afs_axscache.c */
-extern afs_rwlock_t afs_xaxs;
-extern struct axscache *afs_SlowFindAxs(struct axscache **cachep,
- afs_int32 id);
-extern struct axscache *axs_Alloc(void);
-extern void afs_RemoveAxs(struct axscache **headp, struct axscache *axsp);
-extern void afs_FreeAllAxs(struct axscache **headp);
-
-/* afs_buffer.c */
-extern void DInit(int abuffers);
-extern void *DRead(register afs_inode_t * fid, register int page);
-extern void DRelease(register struct buffer *bp, int flag);
-extern int DVOffset(register void *ap);
-extern void DZap(afs_inode_t * fid);
-extern void DFlush(void);
-extern void *DNew(register afs_inode_t * fid, register int page);
-extern void shutdown_bufferpackage(void);
-
-/* afs_call.c */
-extern int afs_cold_shutdown;
-extern afs_int32 afs_setTime;
-extern char afs_rootVolumeName[64];
-extern void afs_shutdown(void);
-extern void afs_FlushCBs(void);
-extern struct afs_icl_set *afs_icl_allSets;
-extern int afs_icl_CreateLog(char *name, afs_int32 logSize,
- struct afs_icl_log **outLogpp);
-extern int afs_icl_CreateLogWithFlags(char *name, afs_int32 logSize,
- afs_uint32 flags,
- struct afs_icl_log **outLogpp);
-extern int afs_icl_CopyOut(register struct afs_icl_log *logp,
- afs_int32 * bufferp, afs_int32 * bufSizep,
- afs_uint32 * cookiep, afs_int32 * flagsp);
-extern int afs_icl_GetLogParms(struct afs_icl_log *logp, afs_int32 * maxSizep,
- afs_int32 * curSizep);
-extern int afs_icl_LogHold(register struct afs_icl_log *logp);
-extern int afs_icl_LogHoldNL(register struct afs_icl_log *logp);
-extern int afs_icl_LogUse(register struct afs_icl_log *logp);
-extern int afs_icl_LogFreeUse(register struct afs_icl_log *logp);
-extern int afs_icl_LogSetSize(register struct afs_icl_log *logp,
- afs_int32 logSize);
-extern int afs_icl_ZapLog(register struct afs_icl_log *logp);
-extern int afs_icl_LogRele(register struct afs_icl_log *logp);
-extern int afs_icl_LogReleNL(register struct afs_icl_log *logp);
-extern int afs_icl_ZeroLog(register struct afs_icl_log *logp);
-extern int afs_icl_LogFree(register struct afs_icl_log *logp);
-extern struct afs_icl_log *afs_icl_FindLog(char *name);
-extern int
- afs_icl_EnumerateLogs(int (*aproc)
-
- (char *name, char *arock, struct afs_icl_log * tp),
- char *arock);
-extern int afs_icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
- struct afs_icl_log *fatalLogp,
- struct afs_icl_set **outSetpp);
-extern int afs_icl_CreateSetWithFlags(char *name,
- struct afs_icl_log *baseLogp,
- struct afs_icl_log *fatalLogp,
- afs_uint32 flags,
- struct afs_icl_set **outSetpp);
-extern int afs_icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID,
- int setValue);
-extern int afs_icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID,
- int *getValuep);
-extern int afs_icl_ZeroSet(struct afs_icl_set *setp);
-extern int
- afs_icl_EnumerateSets(int (*aproc)
-
- (char *name, char *arock, struct afs_icl_log * tp),
- char *arock);
-extern int afs_icl_AddLogToSet(struct afs_icl_set *setp,
- struct afs_icl_log *newlogp);
-extern int afs_icl_SetSetStat(struct afs_icl_set *setp, int op);
-extern int afs_icl_SetHold(register struct afs_icl_set *setp);
-extern int afs_icl_ZapSet(register struct afs_icl_set *setp);
-extern int afs_icl_SetRele(register struct afs_icl_set *setp);
-extern int afs_icl_SetFree(register struct afs_icl_set *setp);
-extern struct afs_icl_set *afs_icl_FindSet(char *name);
-
-extern int afs_icl_Event4(register struct afs_icl_set *setp,
- afs_int32 eventID, afs_int32 lAndT, long p1,
- long p2, long p3, long p4);
-extern int afs_icl_Event3(register struct afs_icl_set *setp,
- afs_int32 eventID, afs_int32 lAndT, long p1,
- long p2, long p3);
-extern int afs_icl_Event2(register struct afs_icl_set *setp,
- afs_int32 eventID, afs_int32 lAndT, long p1,
- long p2);
-extern int afs_icl_Event1(register struct afs_icl_set *setp,
- afs_int32 eventID, afs_int32 lAndT, long p1);
-extern int afs_icl_Event0(register struct afs_icl_set *setp,
- afs_int32 eventID, afs_int32 lAndT);
-extern void afs_icl_AppendRecord(register struct afs_icl_log *logp,
- afs_int32 op, afs_int32 types, long p1,
- long p2, long p3, long p4);
-
-extern int afs_CheckInit(void);
-extern void afs_shutdown(void);
-extern void shutdown_afstest(void);
-extern void afs_shutdown_BKG(void);
-
-
-/* afs_callback.c */
-extern afs_int32 afs_allCBs;
-extern afs_int32 afs_oddCBs;
-extern afs_int32 afs_evenCBs;
-extern afs_int32 afs_allZaps;
-extern afs_int32 afs_oddZaps;
-extern afs_int32 afs_evenZaps;
-extern afs_int32 afs_connectBacks;
-extern unsigned long lastCallBack_vnode;
-extern unsigned int lastCallBack_dv;
-extern osi_timeval_t lastCallBack_time;
-extern struct interfaceAddr afs_cb_interface;
-
-extern int afs_RXCallBackServer(void);
-extern int SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBCacheEntry *a_result);
-extern int SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBCacheEntry64 *a_result);
-extern int SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
- struct AFSDBLock *a_result);
-extern int SRXAFSCB_CallBack(struct rx_call *a_call,
- register struct AFSCBFids *a_fids,
- struct AFSCBs *a_callbacks);
-extern int SRXAFSCB_Probe(struct rx_call *a_call);
-extern int SRXAFSCB_InitCallBackState(struct rx_call *a_call);
-extern int SRXAFSCB_XStatsVersion(struct rx_call *a_call,
- afs_int32 * a_versionP);
-extern int SRXAFSCB_GetXStats(struct rx_call *a_call,
- afs_int32 a_clientVersionNum,
- afs_int32 a_collectionNumber,
- afs_int32 * a_srvVersionNumP,
- afs_int32 * a_timeP, AFSCB_CollData * a_dataP);
-extern int afs_RXCallBackServer(void);
-extern int shutdown_CB(void);
-extern int SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
- struct interfaceAddr *addr);
-extern int SRXAFSCB_WhoAreYou(struct rx_call *a_call,
- struct interfaceAddr *addr);
-extern int SRXAFSCB_InitCallBackState3(struct rx_call *a_call,
- afsUUID * a_uuid);
-extern int SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid);
-extern int SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
- afs_int32 * a_srvr_addr,
- afs_int32 * a_srvr_rank);
-extern int SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
- char **a_name, serverList * a_hosts);
-extern int SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name);
-extern int SRXAFSCB_GetCacheConfig(struct rx_call *a_call,
- afs_uint32 callerVersion,
- afs_uint32 * serverVersion,
- afs_uint32 * configCount,
- cacheConfig * config);
-extern int SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid,
- afs_int32 Fd, afs_int64 Position,
- afs_int64 Length, afs_int64 * TotalLength);
-extern int SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid,
- afs_int32 Fd, afs_int64 Position,
- afs_int64 Length, afs_int64 * TotalLength);
-
-
-/* afs_cbqueue.c */
-extern afs_rwlock_t afs_xcbhash;
-extern void afs_QueueCallback(struct vcache *avc, unsigned int atime,
- struct volume *avp);
-extern void afs_CheckCallbacks(unsigned int secs);
-extern void afs_FlushCBs(void);
-extern void afs_FlushServerCBs(struct server *srvp);
-extern int afs_BumpBase(void);
-extern void afs_InitCBQueue(int doLockInit);
-extern void afs_DequeueCallback(struct vcache *avc);
-
-/* afs_cell.c */
-extern afs_rwlock_t afs_xcell;
-extern void afs_CellInit(void);
-extern void shutdown_cell(void);
-extern int afs_cellname_init(ino_t inode, int lookupcode);
-extern int afs_cellname_write(void);
-extern afs_int32 afs_NewCell(char *acellName, afs_int32 * acellHosts,
- int aflags, char *linkedcname, u_short fsport,
- u_short vlport, int timeout);
-extern afs_int32 afs_SetPrimaryCell(char *acellName);
-extern struct cell *afs_GetCell(afs_int32 acell, afs_int32 locktype);
-extern struct cell *afs_GetCellStale(afs_int32 acell, afs_int32 locktype);
-extern struct cell *afs_GetCellByIndex(afs_int32 cellidx, afs_int32 locktype);
-extern struct cell *afs_GetCellByName(char *acellName, afs_int32 locktype);
-extern struct cell *afs_GetPrimaryCell(afs_int32 locktype);
-extern int afs_IsPrimaryCellNum(afs_int32 cellnum);
-extern int afs_IsPrimaryCell(struct cell *cell);
-extern void *afs_TraverseCells(void *(*cb) (struct cell *, void *),
- void *arg);
-extern int afs_CellOrAliasExists(char *aname);
-extern int afs_CellNumValid(afs_int32 cellnum);
-extern afs_int32 afs_NewCellAlias(char *alias, char *cell);
-extern struct cell_alias *afs_GetCellAlias(int index);
-extern void afs_PutCellAlias(struct cell_alias *a);
-extern int afs_AFSDBHandler(char *acellName, int acellNameLen,
- afs_int32 * kernelMsg);
-extern void afs_LookupAFSDB(char *acellName);
-extern void afs_StopAFSDB(void);
-extern void afs_RemoveCellEntry(struct server *srvp);
-
-/* afs_chunk.c */
-extern afs_int32 afs_FirstCSize;
-extern afs_int32 afs_OtherCSize;
-extern afs_int32 afs_LogChunk;
-
-/* afs_cell.c */
-extern struct cell *afs_GetRealCellByIndex(register afs_int32 cellindex,
- afs_int32 locktype,
- afs_int32 refresh);
-
-/* afs_conn.c */
-extern afs_int32 cryptall;
-extern afs_rwlock_t afs_xinterface;
-extern afs_rwlock_t afs_xconn;
-extern struct conn *afs_Conn(register struct VenusFid *afid,
- register struct vrequest *areq,
- afs_int32 locktype);
-extern struct conn *afs_ConnBySA(struct srvAddr *sap, unsigned short aport,
- afs_int32 acell, struct unixuser *tu,
- int force_if_down, afs_int32 create,
- afs_int32 locktype);
-extern struct conn *afs_ConnByMHosts(struct server *ahosts[],
- unsigned short aport, afs_int32 acell,
- register struct vrequest *areq,
- afs_int32 locktype);
-extern struct conn *afs_ConnByHost(struct server *aserver,
- unsigned short aport, afs_int32 acell,
- struct vrequest *areq, int aforce,
- afs_int32 locktype);
-extern void afs_PutConn(register struct conn *ac, afs_int32 locktype);
-extern void ForceNewConnections(struct srvAddr *sap);
-
-
-/* afs_daemons.c */
-extern afs_lock_t afs_xbrs;
-extern short afs_brsWaiters;
-extern short afs_brsDaemons;
-extern struct brequest afs_brs[NBRS];
-extern struct afs_osi_WaitHandle AFS_WaitHandler, AFS_CSWaitHandler;
-extern afs_int32 afs_gcpags;
-extern afs_int32 afs_gcpags_procsize;
-extern afs_int32 afs_CheckServerDaemonStarted;
-extern afs_int32 PROBE_INTERVAL;
-
-extern void afs_Daemon(void);
-extern struct brequest *afs_BQueue(register short aopcode,
- register struct vcache *avc,
- afs_int32 dontwait, afs_int32 ause,
- struct AFS_UCRED *acred,
- afs_size_t asparm0, afs_size_t asparm1,
- void *apparm0);
-extern void afs_CheckServerDaemon(void);
-extern int afs_CheckRootVolume(void);
-extern void afs_BRelease(register struct brequest *ab);
-extern int afs_BBusy(void);
-extern int afs_BioDaemon(afs_int32 nbiods);
-extern void afs_BackgroundDaemon(void);
-extern void shutdown_daemons(void);
-extern int afs_sgidaemon(void);
-
-
-/* afs_dcache.c */
-extern u_int afs_min_cache;
-extern afs_int32 *afs_dvhashTbl;
-extern afs_int32 afs_dhashsize;
-extern afs_rwlock_t afs_xdcache;
-extern afs_size_t afs_vmMappingEnd;
-extern afs_int32 afs_blocksUsed;
-extern afs_int32 afs_blocksDiscarded;
-extern int afs_WaitForCacheDrain;
-extern int cacheDiskType;
-extern unsigned char *afs_indexFlags;
-extern struct afs_cacheOps *afs_cacheType;
-extern ino_t cacheInode;
-extern struct osi_file *afs_cacheInodep;
-extern void afs_dcacheInit(int afiles, int ablocks, int aDentries, int achunk,
- int aflags);
-extern int afs_PutDCache(register struct dcache *adc);
-extern void afs_FlushDCache(register struct dcache *adc);
-extern void shutdown_dcache(void);
-extern void afs_CacheTruncateDaemon(void);
-extern afs_int32 afs_fsfragsize;
-extern struct dcache *afs_MemGetDSlot(register afs_int32 aslot,
- register struct dcache *tmpdc);
-extern struct dcache *afs_GetDCache(register struct vcache *avc,
- afs_size_t abyte,
- register struct vrequest *areq,
- afs_size_t * aoffset, afs_size_t * alen,
- int aflags);
-extern struct dcache *afs_FindDCache(register struct vcache *avc,
- afs_size_t abyte);
-extern void afs_StoreWarn(register afs_int32 acode, afs_int32 avolume,
- register afs_int32 aflags);
-extern void afs_MaybeWakeupTruncateDaemon(void);
-extern void afs_CacheTruncateDaemon(void);
-extern void afs_AdjustSize(register struct dcache *adc,
- register afs_int32 newSize);
-extern int afs_HashOutDCache(struct dcache *adc);
-extern int afs_MaybeFreeDiscardedDCache(void);
-extern int afs_RefDCache(struct dcache *adc);
-extern void afs_TryToSmush(register struct vcache *avc,
- struct AFS_UCRED *acred, int sync);
-extern void updateV2DC(int lockVc, struct vcache *v, struct dcache *d,
- int src);
-extern void afs_WriteThroughDSlots(void);
-extern struct dcache *afs_UFSGetDSlot(register afs_int32 aslot,
- register struct dcache *tmpdc);
-extern int afs_WriteDCache(register struct dcache *adc, int atime);
-extern int afs_wakeup(register struct vcache *avc);
-extern int afs_InitCacheFile(char *afile, ino_t ainode);
-
-
-/* afs_dynroot.c */
-extern int afs_IsDynrootFid(struct VenusFid *fid);
-extern void afs_GetDynrootFid(struct VenusFid *fid);
-extern int afs_IsDynroot(struct vcache *avc);
-extern void afs_DynrootInvalidate(void);
-extern void afs_GetDynroot(char **dynrootDir, int *dynrootLen,
- struct AFSFetchStatus *status);
-extern void afs_PutDynroot(void);
-extern int afs_DynrootNewVnode(struct vcache *avc,
- struct AFSFetchStatus *status);
-extern int afs_SetDynrootEnable(int enable);
-extern int afs_GetDynrootEnable(void);
-extern int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname);
-extern int afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname, char *atargetName);
-
-/* afs_exporter.c */
-extern struct afs_exporter *root_exported;
-extern struct afs_exporter *exporter_find(int type);
-
-/* afs_init.c */
-extern struct cm_initparams cm_initParams;
-extern int afs_resourceinit_flag;
-extern afs_rwlock_t afs_puttofileLock;
-extern char *afs_sysname;
-extern char *afs_sysnamelist[MAXNUMSYSNAMES];
-extern int afs_sysnamecount;
-extern afs_int32 cacheInfoModTime;
-extern int afs_CacheInit(afs_int32 astatSize, afs_int32 afiles,
- afs_int32 ablocks, afs_int32 aDentries,
- afs_int32 aVolumes, afs_int32 achunk,
- afs_int32 aflags, afs_int32 ninodes,
- afs_int32 nusers);
-extern void afs_ComputeCacheParms(void);
-extern int afs_InitCacheInfo(register char *afile);
-extern int afs_InitVolumeInfo(char *afile);
-extern int afs_InitCellInfo(char *afile);
-extern int afs_ResourceInit(int preallocs);
-extern void shutdown_cache(void);
-extern void shutdown_vnodeops(void);
-extern void shutdown_AFS(void);
-
-/* afs_lock.c */
-extern void Lock_Init(register struct afs_lock *lock);
-extern void ObtainLock(register struct afs_lock *lock, int how,
- unsigned int src_indicator);
-extern void ReleaseLock(register struct afs_lock *lock, int how);
-extern int Afs_Lock_Trace(int op, struct afs_lock *alock, int type,
- char *file, int line);
-extern void Afs_Lock_Obtain(register struct afs_lock *lock, int how);
-extern void Afs_Lock_ReleaseR(register struct afs_lock *lock);
-extern void Afs_Lock_ReleaseW(register struct afs_lock *lock);
-extern void afs_osi_SleepR(register char *addr,
- register struct afs_lock *alock);
-extern void afs_osi_SleepW(register char *addr,
- register struct afs_lock *alock);
-extern void afs_osi_SleepS(register char *addr,
- register struct afs_lock *alock);
-#ifndef AFS_NOBOZO_LOCK
-extern void afs_BozonLock(struct afs_bozoLock *alock, struct vcache *avc);
-extern void afs_BozonUnlock(struct afs_bozoLock *alock, struct vcache *avc);
-extern void afs_BozonInit(struct afs_bozoLock *alock, struct vcache *avc);
-extern int afs_CheckBozonLock(struct afs_bozoLock *alock);
-extern int afs_CheckBozonLockBlocking(struct afs_bozoLock *alock);
-#endif
-
-
-
-
-/* afs_mariner.c */
-extern afs_int32 afs_mariner;
-extern afs_int32 afs_marinerHost;
-extern struct rx_service *afs_server;
-extern int afs_AddMarinerName(register char *aname,
- register struct vcache *avc);
-extern char *afs_GetMariner(register struct vcache *avc);
-extern void afs_MarinerLogFetch(register struct vcache *avc,
- register afs_int32 off,
- register afs_int32 bytes,
- register afs_int32 idx);
-extern void afs_MarinerLog(register char *astring,
- register struct vcache *avc);
-extern void shutdown_mariner(void);
-
-
-/* afs_memcache.c */
-extern int afs_InitMemCache(int blkCount, int blkSize, int flags);
-extern int afs_MemCacheClose(char *file);
-extern void *afs_MemCacheOpen(ino_t blkno);
-extern int afs_MemReadBlk(register struct memCacheEntry *mceP, int offset,
- char *dest, int size);
-extern int afs_MemReadvBlk(register struct memCacheEntry *mceP, int offset,
- struct iovec *iov, int nio, int size);
-extern int afs_MemReadUIO(ino_t blkno, struct uio *uioP);
-extern int afs_MemWriteBlk(register struct memCacheEntry *mceP, int offset,
- char *src, int size);
-extern int afs_MemWritevBlk(register struct memCacheEntry *mceP, int offset,
- struct iovec *iov, int nio, int size);
-extern int afs_MemWriteUIO(ino_t blkno, struct uio *uioP);
-extern int afs_MemCacheTruncate(register struct memCacheEntry *mceP,
- int size);
-extern int afs_MemCacheStoreProc(register struct rx_call *acall,
- register struct memCacheEntry *mceP,
- register afs_int32 alen, struct vcache *avc,
- int *shouldWake, afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP,
- afs_int32 length);
-extern int afs_MemCacheFetchProc(register struct rx_call *acall,
- register struct memCacheEntry *mceP,
- afs_size_t abase, struct dcache *adc,
- struct vcache *avc,
- afs_size_t * abytesToXferP,
- afs_size_t * abytesXferredP,
- afs_int32 lengthFound);
-extern void shutdown_memcache(void);
-
-
-/* afs_nfsclnt.c */
-extern struct afs_exporter *afs_nfsexported;
-extern struct afs_exporter *afs_nfsexporter;
-
-/* afs_osi.c */
-extern afs_lock_t afs_ftf;
-extern void afs_osi_Invisible(void);
-extern void afs_osi_RxkRegister(void);
-extern void afs_osi_MaskSignals(void);
-extern void afs_osi_UnmaskRxkSignals(void);
-extern void *afs_osi_Alloc_debug(size_t x, char *func, int line);
-#ifndef afs_osi_Alloc_NoSleep
-extern void *afs_osi_Alloc_NoSleep(size_t x);
-#endif
-#ifndef afs_osi_Free
-extern void afs_osi_Free(void *x, size_t asize);
-#endif
-extern void afs_osi_FreeStr(char *x);
-extern void osi_Init(void);
-extern int osi_Active(register struct vcache *avc);
-extern void osi_FlushPages(register struct vcache *avc,
- struct AFS_UCRED *credp);
-extern void osi_FlushText_really(register struct vcache *vp);
-extern void afs_osi_MaskSignals(void);
-extern void afs_osi_UnmaskRxkSignals(void);
-extern void afs_osi_RxkRegister(void);
-extern void afs_osi_Invisible(void);
-extern int osi_VMDirty_p(struct vcache *avc);
-#ifndef UKERNEL
-extern void osi_ReleaseVM(struct vcache *avc, struct AFS_UCRED *acred);
-#endif
-extern void shutdown_osi(void);
-extern int afs_osi_suser(void *credp);
-extern void afs_osi_TraverseProcTable(void);
-#if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_PROC)
-extern const struct AFS_UCRED *afs_osi_proc2cred(AFS_PROC * pr);
-#endif
-
-/* afs_osi_pag.c */
-extern int afs_setpag();
-extern afs_uint32 genpag(void);
-extern afs_uint32 getpag(void);
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-extern int AddPag(struct proc *p, afs_int32 aval, struct AFS_UCRED **credpp);
-#else
-extern int AddPag(afs_int32 aval, struct AFS_UCRED **credpp);
-#endif
-extern int afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred);
-extern afs_uint32 afs_get_pag_from_groups(gid_t g0a, gid_t g1a);
-extern void afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p);
-extern afs_int32 PagInCred(const struct AFS_UCRED *cred);
-
-/* afs_osi_alloc.c */
-#ifndef AFS_FBSD_ENV
-extern afs_int32 afs_preallocs;
-extern afs_lock_t osi_fsplock;
-extern afs_lock_t osi_flplock;
-#endif
-extern void osi_FreeLargeSpace(void *adata);
-extern void osi_FreeMediumSpace(void *adata);
-extern void osi_FreeSmallSpace(void *adata);
-extern void *osi_AllocLargeSpace(size_t size);
-extern void *osi_AllocMediumSpace(size_t size);
-extern void *osi_AllocSmallSpace(size_t size);
-#ifndef osi_AllocSmall
-extern char *osi_AllocSmall(register afs_int32 size,
- register afs_int32 morespace);
-#endif
-
-/* afs_osi_uio.c */
-extern int afsio_copy(struct uio *ainuio, struct uio *aoutuio,
- struct iovec *aoutvec);
-extern int afsio_trim(struct uio *auio, afs_int32 asize);
-extern int afsio_skip(struct uio *auio, afs_int32 asize);
-
-
-
-/* ARCH/osi_misc.c */
-extern void osi_iput(struct inode *ip);
-extern void afs_osi_SetTime(osi_timeval_t * atv);
-
-/* LINUX/osi_misc.c */
-#ifdef AFS_LINUX20_ENV
-#ifdef AFS_LINUX24_ENV
-extern int osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- vnode_t ** dirvpp, struct dentry **dpp);
-extern int osi_InitCacheInfo(char *aname);
-extern int osi_rdwr(int rw, struct osi_file *file, caddr_t addrp,
- size_t asize, size_t * resid);
-extern int osi_file_uio_rdwr(struct osi_file *osifile, uio_t * uiop, int rw);
-extern void setup_uio(uio_t * uiop, struct iovec *iovecp, char *buf,
- afs_offs_t pos, int count, uio_flag_t flag,
- uio_seg_t seg);
-extern int uiomove(char *dp, int length, uio_flag_t rw, uio_t * uiop);
-extern void osi_linux_free_inode_pages(void);
-extern void osi_clear_inode(struct inode *ip);
-extern void check_bad_parent(struct dentry *dp);
-#endif
-extern void osi_linux_mask(void);
-extern void osi_linux_unmask(void);
-extern void osi_linux_rxkreg(void);
-extern int setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
- int change_parent);
-#endif
-
-
-/* ARCH/osi_sleep.c */
-extern void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle);
-extern void afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle);
-extern int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle,
- int aintok);
-#ifndef afs_osi_Wakeup
-extern int afs_osi_Wakeup(void *event);
-#endif
-#ifndef afs_osi_Sleep
-extern void afs_osi_Sleep(void *event);
-#endif
-#ifndef afs_osi_SleepSig
-extern int afs_osi_SleepSig(void *event);
-#endif
-
-
-/* ARCH/osi_inode.c */
-extern int afs_syscall_icreate();
-extern int afs_syscall_iopen();
-extern int afs_syscall_iincdec();
-
-
-/* ARCH/osi_file.c */
-extern int afs_osicred_initialized;
-#if defined(AFS_SUN57_64BIT_ENV) || defined(AFS_SGI62_ENV)
-extern void *osi_UFSOpen(ino_t ainode);
-#else
-extern void *osi_UFSOpen(afs_int32 ainode);
-#endif
-extern int afs_osi_Stat(register struct osi_file *afile,
- register struct osi_stat *astat);
-extern int osi_UFSClose(register struct osi_file *afile);
-extern int osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize);
-extern void osi_DisableAtimes(struct vnode *avp);
-extern int afs_osi_Read(register struct osi_file *afile, int offset,
- void *aptr, afs_int32 asize);
-extern int afs_osi_Write(register struct osi_file *afile, afs_int32 offset,
- void *aptr, afs_int32 asize);
-extern int afs_osi_MapStrategy(int (*aproc) (struct buf * bp),
- register struct buf *bp);
-extern void shutdown_osifile(void);
-
-
-/* ARCH/osi_groups.c */
-#ifdef AFS_XBSD_ENV
-extern int setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
- afs_uint32 * newpag, int change_parent);
-#endif
-
-
-/* ARCH/osi_vm.c */
-extern int osi_VM_FlushVCache(struct vcache *avc, int *slept);
-extern void osi_VM_StoreAllSegments(struct vcache *avc);
-extern void osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred,
- int sync);
-extern void osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp);
-extern void osi_VM_Truncate(struct vcache *avc, int alen,
- struct AFS_UCRED *acred);
-extern void osi_VM_TryReclaim(struct vcache *avc, int *slept);
-extern void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size);
-extern int osi_VM_Setup(struct vcache *avc, int force);
-
-#ifdef AFS_SUN5_ENV
-extern int osi_VM_GetDownD(struct vcache *avc, struct dcache *adc);
-extern void osi_VM_PreTruncate(struct vcache *avc, int alen,
- struct AFS_UCRED *acred);
-#endif
-
-
-/* ARCH/osi_vnodeops.c */
-extern struct vnodeops Afs_vnodeops;
-#if defined(AFS_OSF_ENV)
-#if defined(AFS_OSF30_ENV)
-extern int max_vnodes; /* number of total system vnodes */
-#else
-extern int nvnode; /* number of total system vnodes */
-extern int numvnodes; /* number vnodes in use now */
-#endif
-#ifdef AFS_DUX40_ENV
-extern struct vfs_ubcops afs_ubcops;
-#endif
-#endif
-
-/* afs_osifile.c */
-
-/* afs_osi_pag.c */
-extern afs_uint32 pag_epoch;
-extern afs_uint32 pagCounter;
-
-/* OS/osi_vfsops.c */
-#if defined(AFS_OSF_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV)
-extern struct mount *afs_globalVFS;
-#else
-extern struct vfs *afs_globalVFS;
-#endif
-extern struct vcache *afs_globalVp;
-#ifdef AFS_LINUX20_ENV
-extern void vcache2inode(struct vcache *avc);
-#endif
-
-/* afs_pioctl.c */
-extern struct VenusFid afs_rootFid;
-extern afs_int32 afs_waitForever;
-extern short afs_waitForeverCount;
-extern afs_int32 afs_showflags;
-extern int afs_defaultAsynchrony;
-extern int afs_syscall_pioctl();
-
-/* afs_segments.c */
-extern int afs_StoreMini(register struct vcache *avc, struct vrequest *areq);
-extern int afs_StoreAllSegments(register struct vcache *avc,
- struct vrequest *areq, int sync);
-extern int afs_InvalidateAllSegments(struct vcache *avc);
-extern int afs_TruncateAllSegments(register struct vcache *avc,
- afs_size_t alen, struct vrequest *areq,
- struct AFS_UCRED *acred);
-
-/* afs_server.c */
-extern afs_rwlock_t afs_xsrvAddr;
-extern afs_rwlock_t afs_xserver;
-extern afs_rwlock_t afs_icl_lock;
-extern struct srvAddr *afs_srvAddrs[NSERVERS];
-extern struct server *afs_servers[NSERVERS];
-extern int afs_totalServers;
-extern struct server *afs_setTimeHost;
-extern struct server *afs_FindServer(afs_int32 aserver, ushort aport,
- afsUUID * uuidp, afs_int32 locktype);
-extern struct server *afs_GetServer(afs_uint32 * aserver, afs_int32 nservers,
- afs_int32 acell, u_short aport,
- afs_int32 locktype, afsUUID * uuidp,
- afs_int32 addr_uniquifier);
-extern void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown);
-extern void afs_ServerDown(struct srvAddr *sa);
-extern void afs_CountServers(void);
-extern void afs_CheckServers(int adown, struct cell *acellp);
-extern unsigned int afs_random(void);
-extern int afs_randomMod15(void);
-extern int afs_randomMod127(void);
-extern void afs_SortOneServer(struct server *asp);
-extern void afs_SortServers(struct server *aservers[], int count);
-extern void afs_FlushServer(struct server *srvp);
-extern void afs_RemoveSrvAddr(struct srvAddr *sap);
-extern void afs_ActivateServer(struct srvAddr *sap);
-#ifdef AFS_USERSPACE_IP_ADDR
-extern int afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
- afs_uint32 subnetmask);
-#else
-#if (!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)
-void afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa);
-#endif
-#endif
-
-
-
-/* afs_osidnlc.c */
-extern int osi_dnlc_enter(struct vcache *adp, char *aname, struct vcache *avc,
- afs_hyper_t * avno);
-extern struct vcache *osi_dnlc_lookup(struct vcache *adp, char *aname,
- int locktype);
-extern int osi_dnlc_remove(struct vcache *adp, char *aname,
- struct vcache *avc);
-extern int osi_dnlc_purgedp(struct vcache *adp);
-extern int osi_dnlc_purgevp(struct vcache *avc);
-extern int osi_dnlc_purge(void);
-extern int osi_dnlc_purgevol(struct VenusFid *fidp);
-extern int osi_dnlc_init(void);
-extern int osi_dnlc_shutdown(void);
-
-
-/* afs_stat.c */
-extern struct afs_CMStats afs_cmstats;
-extern struct afs_stats_CMPerf afs_stats_cmperf;
-extern struct afs_stats_CMFullPerf afs_stats_cmfullperf;
-extern afs_int32 afs_stats_XferSumBytes[AFS_STATS_NUM_FS_XFER_OPS];
-extern void afs_InitStats(void);
-extern void afs_GetCMStat(char **ptr, unsigned *size);
-#ifndef AFS_NOSTATS
-extern void afs_AddToMean(struct afs_MeanStats *oldMean, afs_int32 newValue);
-#endif
-
-
-/* UKERNEL/afs_usrops.c */
-#ifdef UKERNEL
-extern void uafs_Shutdown(void);
-extern void osi_ReleaseVM(struct vcache *avc, int len,
- struct usr_ucred *credp);
-extern int osi_GetTime(struct timeval *tv);
-#endif
-
-
-
-
-/* afs_user.c */
-extern afs_rwlock_t afs_xuser;
-extern struct unixuser *afs_users[NUSERS];
-extern struct unixuser *afs_FindUser(afs_int32 auid, afs_int32 acell,
- afs_int32 locktype);
-extern struct unixuser *afs_GetUser(register afs_int32 auid, afs_int32 acell,
- afs_int32 locktype);
-#if AFS_GCPAGS
-extern afs_int32 afs_GCPAGs(afs_int32 * ReleasedCount);
-extern void afs_GCPAGs_perproc_func(AFS_PROC * pproc);
-#endif /* AFS_GCPAGS */
-extern void afs_ComputePAGStats(void);
-extern void afs_PutUser(register struct unixuser *au, afs_int32 locktype);
-extern void afs_GCUserData(int aforce);
-extern void afs_CheckTokenCache(void);
-extern void afs_ResetAccessCache(afs_int32 uid, int alock);
-extern void afs_ResetUserConns(register struct unixuser *auser);
-extern void afs_SetPrimary(register struct unixuser *au, register int aflag);
-
-
-/* afs_util.c */
-#ifndef afs_cv2string
-extern char *afs_cv2string(char *ttp, afs_uint32 aval);
-#endif
-#ifndef afs_strcasecmp
-extern int afs_strcasecmp(char *s1, char *s2);
-#endif
-#ifndef afs_strcat
-extern char *afs_strcat(char *s1, char *s2);
-#endif
-#ifdef AFS_OBSD34_ENV
-extern char *afs_strcpy(char *s1, char *s2);
-#endif
-#ifndef afs_strchr
-extern char *afs_strchr(char *s, int c);
-#endif
-extern char *afs_strdup(char *s);
-extern void print_internet_address(char *preamble, struct srvAddr *sa,
- char *postamble, int flag);
-extern afs_int32 afs_data_pointer_to_int32(const void *p);
-
-#if 0 /* problems - need to change to varargs, right now is incorrect usage
- * throughout code */
-extern void afs_warn(char *a, long b, long c, long d, long e, long f, long g,
- long h, long i, long j);
-extern void afs_warnuser(char *a, long b, long c, long d, long e, long f,
- long g, long h, long i, long j);
-#else
-extern void afs_warn();
-extern void afs_warnuser();
-#endif
-extern void afs_CheckLocks(void);
-extern int afs_badop(void);
-extern int afs_noop(void);
-extern afs_int32 afs_data_pointer_to_int32(const void *p);
-
-
-
-/* afs_vcache.c */
-extern afs_int32 afs_maxvcount;
-extern afs_int32 afs_vcount;
-extern int afsvnumbers;
-extern afs_rwlock_t afs_xvcache;
-extern afs_lock_t afs_xvcb;
-extern struct vcache *freeVCList;
-extern struct vcache *Initial_freeVCList;
-extern struct afs_q VLRU;
-extern afs_int32 vcachegen;
-extern unsigned int afs_paniconwarn;
-extern struct vcache *afs_vhashT[VCSIZE];
-extern afs_int32 afs_bulkStatsLost;
-extern int afs_norefpanic;
-
-void afs_vcacheInit(int astatSize);
-extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 * retry,
- afs_int32 flag);
-extern afs_int32 afs_FetchStatus(struct vcache *avc, struct VenusFid *afid,
- struct vrequest *areq,
- struct AFSFetchStatus *Outsp);
-
-extern afs_int32 afs_FlushVCBs(afs_int32 lockit);
-extern void afs_InactiveVCache(struct vcache *avc, struct AFS_UCRED *acred);
-extern struct vcache *afs_LookupVCache(struct VenusFid *afid,
- struct vrequest *areq,
- afs_int32 * cached, struct vcache *adp,
- char *aname);
-extern int afs_FlushVCache(struct vcache *avc, int *slept);
-extern struct vcache *afs_GetRootVCache(struct VenusFid *afid,
- struct vrequest *areq,
- afs_int32 * cached,
- struct volume *tvolp);
-extern struct vcache *afs_NewVCache(struct VenusFid *afid,
- struct server *serverp);
-extern int afs_VerifyVCache2(struct vcache *avc, struct vrequest *areq);
-extern struct vcache *afs_GetVCache(register struct VenusFid *afid,
- struct vrequest *areq, afs_int32 * cached,
- struct vcache *avc);
-extern void afs_PutVCache(register struct vcache *avc);
-extern void afs_ProcessFS(register struct vcache *avc,
- register struct AFSFetchStatus *astat,
- struct vrequest *areq);
-extern struct afs_cbr *afs_AllocCBR(void);
-extern int afs_FreeCBR(register struct afs_cbr *asp);
-extern void afs_RemoveVCB(register struct VenusFid *afid);
-extern void afs_FlushActiveVcaches(register afs_int32 doflocks);
-extern int afs_WriteVCache(register struct vcache *avc,
- register struct AFSStoreStatus *astatus,
- struct vrequest *areq);
-extern int afs_RemoteLookup(register struct VenusFid *afid,
- struct vrequest *areq, char *name,
- struct VenusFid *nfid,
- struct AFSFetchStatus *OutStatusp,
- struct AFSCallBack *CallBackp,
- struct server **serverp,
- struct AFSVolSync *tsyncp);
-extern afs_int32 afs_NFSFindVCache(struct vcache **avcp,
- struct VenusFid *afid);
-extern void afs_vcacheInit(int astatSize);
-extern void shutdown_vcache(void);
-
-
-/* VNOPS/afs_vnop_access.c */
-extern afs_int32 afs_GetAccessBits(register struct vcache *avc,
- register afs_int32 arights,
- register struct vrequest *areq);
-extern int afs_AccessOK(struct vcache *avc, afs_int32 arights,
- struct vrequest *areq, afs_int32 check_mode_bits);
-#if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
-extern int afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
- struct AFS_UCRED *acred);
-#else
-extern int afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
- struct AFS_UCRED *acred);
-#endif
-extern int afs_getRights(OSI_VC_DECL(avc), register afs_int32 arights,
- struct AFS_UCRED *acred);
-
-/* VNOPS/afs_vnop_attrs.c */
-extern int afs_CopyOutAttrs(register struct vcache *avc,
- register struct vattr *attrs);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-extern int afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, int flags,
- struct AFS_UCRED *acred);
-#else
-extern int afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs,
- struct AFS_UCRED *acred);
-#endif
-extern int afs_VAttrToAS(register struct vcache *avc,
- register struct vattr *av,
- register struct AFSStoreStatus *as);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-extern int afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
- int flags, struct AFS_UCRED *acred);
-#else
-extern int afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
- struct AFS_UCRED *acred);
-#endif
-
-/* VNOPS/afs_vnop_create.c */
-#ifdef AFS_OSF_ENV
-extern int afs_create(struct nameidata *ndp, struct vattr *attrs);
-#else /* AFS_OSF_ENV */
-#ifdef AFS_SGI64_ENV
-extern int afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
- int flags, int amode, struct vcache **avcp,
- struct AFS_UCRED *acred);
-#else /* AFS_SGI64_ENV */
-extern int afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
- enum vcexcl aexcl, int amode, struct vcache **avcp,
- struct AFS_UCRED *acred);
-#endif /* AFS_SGI64_ENV */
-#endif /* AFS_OSF_ENV */
-extern int afs_LocalHero(register struct vcache *avc,
- register struct dcache *adc,
- register AFSFetchStatus * astat, register int aincr);
-
-
-/* VNOPS/afs_vnop_flock.c */
-extern void lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp,
- int clid);
-extern int HandleFlock(register struct vcache *avc, int acom,
- struct vrequest *areq, pid_t clid, int onlymine);
-
-
-
-/* VNOPS/afs_vnop_lookup.c */
-extern int EvalMountPoint(register struct vcache *avc, struct vcache *advc,
- struct volume **avolpp,
- register struct vrequest *areq);
-extern void afs_InitFakeStat(struct afs_fakestat_state *state);
-extern int afs_EvalFakeStat(struct vcache **avcp,
- struct afs_fakestat_state *state,
- struct vrequest *areq);
-extern int afs_TryEvalFakeStat(struct vcache **avcp,
- struct afs_fakestat_state *state,
- struct vrequest *areq);
-extern void afs_PutFakeStat(struct afs_fakestat_state *state);
-extern int afs_ENameOK(register char *aname);
-extern void Check_AtSys(register struct vcache *avc, char *aname,
- struct sysname_info *state, struct vrequest *areq);
-extern int Next_AtSys(register struct vcache *avc, struct vrequest *areq,
- struct sysname_info *state);
-extern int afs_DoBulkStat(struct vcache *adp, long dirCookie,
- struct vrequest *areqp);
-extern int afs_lookup();
-
-
-/* VNOPS/afs_vnop_open.c */
-#ifdef AFS_SGI64_ENV
-extern int afs_open(bhv_desc_t * bhv, struct vcache **avcp, afs_int32 aflags,
- struct AFS_UCRED *acred);
-#else
-extern int afs_open(struct vcache **avcp, afs_int32 aflags,
- struct AFS_UCRED *acred);
-#endif
-
-
-/* VNOPS/afs_vnop_read.c */
-extern afs_int32 maxIHint;
-extern afs_int32 nihints;
-extern afs_int32 usedihint;
-extern int afs_MemRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn,
- struct buf **abpp, int noLock);
-extern int afs_UFSRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn,
- struct buf **abpp, int noLock);
-
-
-/* VNOPS/afs_vnop_readdir.c */
-extern int afs_rd_stash_i;
-
-
-/* VNOPS/afs_vnop_remove.c */
-extern int afsremove(register struct vcache *adp, register struct dcache *tdc,
- register struct vcache *tvc, char *aname,
- struct AFS_UCRED *acred, struct vrequest *treqp);
-extern int afs_remunlink(register struct vcache *avc, register int doit);
-
-
-/* VNOPS/afs_vnop_rename.c */
-extern int afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
- char *aname2, struct AFS_UCRED *acred,
- struct vrequest *areq);
-
-
-/* VNOPS/afs_vnop_symlink.c */
-extern int afs_MemHandleLink(register struct vcache *avc,
- struct vrequest *areq);
-extern int afs_UFSHandleLink(register struct vcache *avc,
- struct vrequest *areq);
-
-/* VNOPS/afs_vnop_flock.c */
-extern afs_int32 lastWarnTime;
-
-/* VNOPS/afs_vnop_write.c */
-extern int afs_MemWrite(register struct vcache *avc, struct uio *auio,
- int aio, struct AFS_UCRED *acred, int noLock);
-extern int afs_StoreOnLastReference(register struct vcache *avc,
- register struct vrequest *treq);
-extern int afs_UFSWrite(register struct vcache *avc, struct uio *auio,
- int aio, struct AFS_UCRED *acred, int noLock);
-extern int afs_DoPartialWrite(register struct vcache *avc,
- struct vrequest *areq);
-extern int afs_closex(register struct file *afd);
-
-/* other VNOPS (please fix these) */
-extern int afs_close();
-extern int HandleIoctl();
-extern int afs_fsync();
-extern int afs_remove();
-extern int afs_link();
-extern int afs_rename();
-extern int afs_mkdir();
-extern int afs_rmdir();
-extern int afs_symlink();
-extern int afs_readdir();
-extern int afs_readlink();
-extern int afs_ustrategy();
-extern int afs_lockctl();
-
-
-/* afs_volume.c */
-extern afs_int32 afs_FVIndex;
-extern afs_int32 afs_volCounter;
-extern afs_rwlock_t afs_xvolume;
-extern struct volume *afs_volumes[NVOLS];
-extern ino_t volumeInode;
-extern struct volume *afs_FindVolume(struct VenusFid *afid,
- afs_int32 locktype);
-extern struct volume *afs_freeVolList;
-extern afs_int32 fvTable[NFENTRIES];
-extern void InstallVolumeEntry(struct volume *av, struct vldbentry *ve,
- int acell);
-extern void InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve,
- int acell);
-extern void InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve,
- int acell, struct cell *tcell,
- struct vrequest *areq);
-extern void afs_ResetVolumeInfo(struct volume *tv);
-extern struct volume *afs_MemGetVolSlot(void);
-extern void afs_ResetVolumes(struct server *srvp);
-extern struct volume *afs_GetVolume(struct VenusFid *afid,
- struct vrequest *areq,
- afs_int32 locktype);
-extern struct volume *afs_GetVolumeByName(register char *aname,
- afs_int32 acell, int agood,
- struct vrequest *areq,
- afs_int32 locktype);
-extern struct volume *afs_UFSGetVolSlot(void);
-extern void afs_CheckVolumeNames(int flags);
-
-
-/* Prototypes for generated files that aren't really in src/afs/ */
-
-/* afs_uuid.c */
-extern afs_int32 afs_uuid_equal(afsUUID * u1, afsUUID * u2);
-extern afs_int32 afs_uuid_is_nil(afsUUID * u1);
-extern void afs_htonuuid(afsUUID * uuidp);
-extern void afs_ntohuuid(afsUUID * uuidp);
-extern afs_int32 afs_uuid_create(afsUUID * uuid);
-extern u_short afs_uuid_hash(afsUUID * uuid);
-
-
-/* MISC PROTOTYPES - THESE SHOULD NOT BE HERE */
-/* MOVE THEM TO APPROPRIATE LOCATIONS */
-extern afs_int32 RXAFSCB_ExecuteRequest(struct rx_call *acall);
-extern afs_int32 RXSTATS_ExecuteRequest(struct rx_call *acall);
-
-
-
-#if defined(AFS_SUN5_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_AIX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_SGI62_ENV)
-#include "osi_prototypes.h"
-#endif
-
-#endif /* _AFS_PROTOTYPES_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
- */
-
-/*
- * --------------------- Required definitions ---------------------
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_segments.c,v 1.16 2003/07/15 23:14:13 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/afs_cbqueue.h"
-#include "afs/afs_osidnlc.h"
-
-afs_uint32 afs_stampValue = 0;
-
-/*
- * afs_StoreMini
- *
- * Description:
- * Send a truncation request to a FileServer.
- *
- * Parameters:
- * xxx : description
- *
- * Environment:
- * We're write-locked upon entry.
- */
-
-int
-afs_StoreMini(register struct vcache *avc, struct vrequest *areq)
-{
- register struct conn *tc;
- struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutStatus;
- struct AFSVolSync tsync;
- register afs_int32 code;
- register struct rx_call *tcall;
- afs_size_t tlen, xlen = 0;
- XSTATS_DECLS AFS_STATCNT(afs_StoreMini);
- afs_Trace2(afs_iclSetp, CM_TRACE_STOREMINI, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, avc->m.Length);
- tlen = avc->m.Length;
- if (avc->truncPos < tlen)
- tlen = avc->truncPos;
- avc->truncPos = AFS_NOTRUNC;
- avc->states &= ~CExtendedFile;
-
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- RX_AFS_GUNLOCK();
- retry:
- tcall = rx_NewCall(tc->id);
- RX_AFS_GLOCK();
- /* Set the client mod time since we always want the file
- * to have the client's mod time and not the server's one
- * (to avoid problems with make, etc.) It almost always
- * works fine with standard afs because them server/client
- * times are in sync and more importantly this storemini
- * it's a special call that would typically be followed by
- * the proper store-data or store-status calls.
- */
- InStatus.Mask = AFS_SETMODTIME;
- InStatus.ClientModTime = avc->m.Date;
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREDATA);
- afs_Trace4(afs_iclSetp, CM_TRACE_STOREDATA64, ICL_TYPE_FID,
- &avc->fid.Fid, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(xlen), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(tlen));
- RX_AFS_GUNLOCK();
-#ifdef AFS_64BIT_CLIENT
- if (!afs_serverHasNo64Bit(tc)) {
- code =
- StartRXAFS_StoreData64(tcall,
- (struct AFSFid *)&avc->fid.Fid,
- &InStatus, avc->m.Length,
- (afs_size_t) 0, tlen);
- } else {
- afs_int32 l1, l2;
- l1 = avc->m.Length;
- l2 = tlen;
- code =
- StartRXAFS_StoreData(tcall,
- (struct AFSFid *)&avc->fid.Fid,
- &InStatus, l1, 0, l2);
- }
-#else /* AFS_64BIT_CLIENT */
- code =
- StartRXAFS_StoreData(tcall, (struct AFSFid *)&avc->fid.Fid,
- &InStatus, avc->m.Length, 0, tlen);
-#endif /* AFS_64BIT_CLIENT */
- if (code == 0) {
- code = EndRXAFS_StoreData(tcall, &OutStatus, &tsync);
-#ifdef AFS_64BIT_CLIENT
- if (code == RXGEN_OPCODE) {
- afs_serverSetNo64Bit(tc);
- code = rx_EndCall(tcall, code);
- goto retry;
- }
-#endif /* AFS_64BIT_CLIENT */
- }
- code = rx_EndCall(tcall, code);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREDATA,
- SHARED_LOCK, NULL));
-
- if (code == 0) {
- afs_ProcessFS(avc, &OutStatus, areq);
- } else {
- /* blew it away */
- afs_InvalidateAllSegments(avc);
- }
- return code;
-
-} /*afs_StoreMini */
-
-unsigned int storeallmissing = 0;
-#define lmin(a,b) (((a) < (b)) ? (a) : (b))
-/*
- * afs_StoreAllSegments
- *
- * Description:
- * Stores all modified segments back to server
- *
- * Parameters:
- * avc : Pointer to vcache entry.
- * areq : Pointer to request structure.
- *
- * Environment:
- * Called with avc write-locked.
- */
-#if defined (AFS_HPUX_ENV) || defined(AFS_ULTRIX_ENV)
-int NCHUNKSATONCE = 3;
-#else
-int NCHUNKSATONCE = 64;
-#endif
-int afs_dvhack = 0;
-
-
-int
-afs_StoreAllSegments(register struct vcache *avc, struct vrequest *areq,
- int sync)
-{
- register struct dcache *tdc;
- register afs_int32 code = 0;
- register afs_int32 index;
- register afs_int32 origCBs, foreign = 0;
- int hash, stored;
- afs_hyper_t newDV, oldDV; /* DV when we start, and finish, respectively */
- struct dcache **dcList, **dclist;
- unsigned int i, j, minj, moredata, high, off;
- afs_size_t tlen;
- afs_size_t maxStoredLength; /* highest offset we've written to server. */
- int safety;
-#ifndef AFS_NOSTATS
- struct afs_stats_xferData *xferP; /* Ptr to this op's xfer struct */
- osi_timeval_t xferStartTime, /*FS xfer start time */
- xferStopTime; /*FS xfer stop time */
- afs_size_t bytesToXfer; /* # bytes to xfer */
- afs_size_t bytesXferred; /* # bytes actually xferred */
-#endif /* AFS_NOSTATS */
-
-
- AFS_STATCNT(afs_StoreAllSegments);
-
- hset(oldDV, avc->m.DataVersion);
- hset(newDV, avc->m.DataVersion);
- hash = DVHash(&avc->fid);
- foreign = (avc->states & CForeign);
- dcList = (struct dcache **)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- afs_Trace2(afs_iclSetp, CM_TRACE_STOREALL, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
-#if !defined(AFS_AIX32_ENV) && !defined(AFS_SGI65_ENV)
- /* In the aix vm implementation we need to do the vm_writep even
- * on the memcache case since that's we adjust the file's size
- * and finish flushing partial vm pages.
- */
- if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
-#endif /* !AFS_AIX32_ENV && !AFS_SGI65_ENV */
- {
- /* If we're not diskless, reading a file may stress the VM
- * system enough to cause a pageout, and this vnode would be
- * locked when the pageout occurs. We can prevent this problem
- * by making sure all dirty pages are already flushed. We don't
- * do this when diskless because reading a diskless (i.e.
- * memory-resident) chunk doesn't require using new VM, and we
- * also don't want to dump more dirty data into a diskless cache,
- * since they're smaller, and we might exceed its available
- * space.
- */
-#if defined(AFS_SUN5_ENV)
- if (sync & AFS_VMSYNC_INVAL) /* invalidate VM pages */
- osi_VM_TryToSmush(avc, CRED(), 1);
- else
-#endif
- osi_VM_StoreAllSegments(avc);
- }
-
- ConvertWToSLock(&avc->lock);
-
- /*
- * Subsequent code expects a sorted list, and it expects all the
- * chunks in the list to be contiguous, so we need a sort and a
- * while loop in here, too - but this will work for a first pass...
- * 92.10.05 - OK, there's a sort in here now. It's kind of a modified
- * bin sort, I guess. Chunk numbers start with 0
- *
- * - Have to get a write lock on xdcache because GetDSlot might need it (if
- * the chunk doesn't have a dcache struct).
- * This seems like overkill in most cases.
- * - I'm not sure that it's safe to do "index = .hvNextp", then unlock
- * xdcache, then relock xdcache and try to use index. It is done
- * a lot elsewhere in the CM, but I'm not buying that argument.
- * - should be able to check IFDataMod without doing the GetDSlot (just
- * hold afs_xdcache). That way, it's easy to do this without the
- * writelock on afs_xdcache, and we save unneccessary disk
- * operations. I don't think that works, 'cuz the next pointers
- * are still on disk.
- */
- origCBs = afs_allCBs;
-
- retry:
- maxStoredLength = 0;
- tlen = avc->m.Length;
- minj = 0;
-
- do {
- memset((char *)dcList, 0, NCHUNKSATONCE * sizeof(struct dcache *));
- high = 0;
- moredata = FALSE;
-
- /* lock and start over from beginning of hash chain
- * in order to avoid a race condition. */
- MObtainWriteLock(&afs_xdcache, 284);
- index = afs_dvhashTbl[hash];
-
- for (j = 0; index != NULLIDX;) {
- if ((afs_indexFlags[index] & IFDataMod)
- && (afs_indexUnique[index] == avc->fid.Fid.Unique)) {
- tdc = afs_GetDSlot(index, 0); /* refcount+1. */
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid) && tdc->f.chunk >= minj) {
- off = tdc->f.chunk - minj;
- if (off < NCHUNKSATONCE) {
- if (dcList[off])
- osi_Panic("dclist slot already in use!");
- dcList[off] = tdc;
- if (off > high)
- high = off;
- j++;
- /* DCLOCKXXX: chunkBytes is protected by tdc->lock which we
- * can't grab here, due to lock ordering with afs_xdcache.
- * So, disable this shortcut for now. -- kolya 2001-10-13
- */
- /* shortcut: big win for little files */
- /* tlen -= tdc->f.chunkBytes;
- * if (tlen <= 0)
- * break;
- */
- } else {
- moredata = TRUE;
- afs_PutDCache(tdc);
- if (j == NCHUNKSATONCE)
- break;
- }
- } else {
- afs_PutDCache(tdc);
- }
- }
- index = afs_dvnextTbl[index];
- }
- MReleaseWriteLock(&afs_xdcache);
-
- /* this guy writes chunks, puts back dcache structs, and bumps newDV */
- /* "moredata" just says "there are more dirty chunks yet to come".
- */
- if (j) {
-#ifdef AFS_NOSTATS
- static afs_uint32 lp1 = 10000, lp2 = 10000;
-#endif
- struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutStatus;
- int doProcessFS = 0;
- afs_size_t base, bytes;
- afs_uint32 nchunks;
- int nomore;
- unsigned int first;
- int *shouldwake;
- struct conn *tc;
- struct osi_file *tfile;
- struct rx_call *tcall;
- XSTATS_DECLS for (bytes = 0, j = 0; !code && j <= high; j++) {
- if (dcList[j]) {
- ObtainSharedLock(&(dcList[j]->lock), 629);
- if (!bytes)
- first = j;
- bytes += dcList[j]->f.chunkBytes;
- if ((dcList[j]->f.chunkBytes < afs_OtherCSize)
- && (dcList[j]->f.chunk - minj < high)
- && dcList[j + 1]) {
- int sbytes = afs_OtherCSize - dcList[j]->f.chunkBytes;
- bytes += sbytes;
- }
- }
- if (bytes && (j == high || !dcList[j + 1])) {
- /* base = AFS_CHUNKTOBASE(dcList[first]->f.chunk); */
- base = AFS_CHUNKTOBASE(first + minj);
- /*
- *
- * take a list of dcache structs and send them all off to the server
- * the list must be in order, and the chunks contiguous.
- * Note - there is no locking done by this code currently. For
- * safety's sake, xdcache could be locked over the entire call.
- * However, that pretty well ties up all the threads. Meantime, all
- * the chunks _MUST_ have their refcounts bumped.
- * The writes done before a store back will clear setuid-ness
- * in cache file.
- * We can permit CacheStoreProc to wake up the user process IFF we
- * are doing the last RPC for this close, ie, storing back the last
- * set of contiguous chunks of a file.
- */
-
- dclist = &dcList[first];
- nchunks = 1 + j - first;
- nomore = !(moredata || (j != high));
- InStatus.ClientModTime = avc->m.Date;
- InStatus.Mask = AFS_SETMODTIME;
- if (sync & AFS_SYNC) {
- InStatus.Mask |= AFS_FSYNC;
- }
- tlen = lmin(avc->m.Length, avc->truncPos);
- afs_Trace4(afs_iclSetp, CM_TRACE_STOREDATA64,
- ICL_TYPE_FID, &avc->fid.Fid, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(base), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(bytes), ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(tlen));
-
- do {
- stored = 0;
- tc = afs_Conn(&avc->fid, areq, 0);
- if (tc) {
- restart:
- RX_AFS_GUNLOCK();
- tcall = rx_NewCall(tc->id);
-#ifdef AFS_64BIT_CLIENT
- if (!afs_serverHasNo64Bit(tc)) {
- code =
- StartRXAFS_StoreData64(tcall,
- (struct AFSFid *)
- &avc->fid.Fid,
- &InStatus, base,
- bytes, tlen);
- } else {
- if (tlen > 0xFFFFFFFF) {
- code = EFBIG;
- } else {
- afs_int32 t1, t2, t3;
- t1 = base;
- t2 = bytes;
- t3 = tlen;
- code =
- StartRXAFS_StoreData(tcall,
- (struct AFSFid *)
- &avc->fid.Fid,
- &InStatus, t1,
- t2, t3);
- }
- }
-#else /* AFS_64BIT_CLIENT */
- code =
- StartRXAFS_StoreData(tcall,
- (struct AFSFid *)&avc->
- fid.Fid, &InStatus, base,
- bytes, tlen);
-#endif /* AFS_64BIT_CLIENT */
- RX_AFS_GLOCK();
- } else {
- code = -1;
- tcall = NULL;
- }
- if (!code) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREDATA);
- avc->truncPos = AFS_NOTRUNC;
- }
- for (i = 0; i < nchunks && !code; i++) {
- tdc = dclist[i];
- if (!tdc) {
- afs_warn("afs: missing dcache!\n");
- storeallmissing++;
- continue; /* panic? */
- }
- afs_Trace4(afs_iclSetp, CM_TRACE_STOREALL2,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32,
- tdc->f.chunk, ICL_TYPE_INT32,
- tdc->index, ICL_TYPE_INT32,
- tdc->f.inode);
- shouldwake = 0;
- if (nomore) {
- if (avc->asynchrony == -1) {
- if (afs_defaultAsynchrony >
- (bytes - stored)) {
- shouldwake = &nomore;
- }
- } else if ((afs_uint32) avc->asynchrony >=
- (bytes - stored)) {
- shouldwake = &nomore;
- }
- }
- tfile = afs_CFileOpen(tdc->f.inode);
-#ifndef AFS_NOSTATS
- xferP =
- &(afs_stats_cmfullperf.rpc.
- fsXferTimes
- [AFS_STATS_FS_XFERIDX_STOREDATA]);
- osi_GetuTime(&xferStartTime);
-
- code =
- afs_CacheStoreProc(tcall, tfile,
- tdc->f.chunkBytes, avc,
- shouldwake, &bytesToXfer,
- &bytesXferred);
-
- osi_GetuTime(&xferStopTime);
- (xferP->numXfers)++;
- if (!code) {
- (xferP->numSuccesses)++;
- afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_STOREDATA] +=
- bytesXferred;
- (xferP->sumBytes) +=
- (afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_STOREDATA] >> 10);
- afs_stats_XferSumBytes
- [AFS_STATS_FS_XFERIDX_STOREDATA] &= 0x3FF;
- if (bytesXferred < xferP->minBytes)
- xferP->minBytes = bytesXferred;
- if (bytesXferred > xferP->maxBytes)
- xferP->maxBytes = bytesXferred;
-
- /*
- * Tally the size of the object. Note: we tally the actual size,
- * NOT the number of bytes that made it out over the wire.
- */
- if (bytesToXfer <= AFS_STATS_MAXBYTES_BUCKET0)
- (xferP->count[0])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET1)
- (xferP->count[1])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET2)
- (xferP->count[2])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET3)
- (xferP->count[3])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET4)
- (xferP->count[4])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET5)
- (xferP->count[5])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET6)
- (xferP->count[6])++;
- else if (bytesToXfer <=
- AFS_STATS_MAXBYTES_BUCKET7)
- (xferP->count[7])++;
- else
- (xferP->count[8])++;
-
- afs_stats_GetDiff(elapsedTime, xferStartTime,
- xferStopTime);
- afs_stats_AddTo((xferP->sumTime),
- elapsedTime);
- afs_stats_SquareAddTo((xferP->sqrTime),
- elapsedTime);
- if (afs_stats_TimeLessThan
- (elapsedTime, (xferP->minTime))) {
- afs_stats_TimeAssign((xferP->minTime),
- elapsedTime);
- }
- if (afs_stats_TimeGreaterThan
- (elapsedTime, (xferP->maxTime))) {
- afs_stats_TimeAssign((xferP->maxTime),
- elapsedTime);
- }
- }
-#else
- code =
- afs_CacheStoreProc(tcall, tfile,
- tdc->f.chunkBytes, avc,
- shouldwake, &lp1, &lp2);
-#endif /* AFS_NOSTATS */
- afs_CFileClose(tfile);
-#ifdef AFS_64BIT_CLIENT
- if (code == RXGEN_OPCODE) {
- afs_serverSetNo64Bit(tc);
- goto restart;
- }
-#endif /* AFS_64BIT_CLIENT */
- if ((tdc->f.chunkBytes < afs_OtherCSize)
- && (i < (nchunks - 1))) {
- int bsent, tlen, sbytes =
- afs_OtherCSize - tdc->f.chunkBytes;
- char *tbuffer =
- osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-
- while (sbytes > 0) {
- tlen =
- (sbytes >
- AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ :
- sbytes);
- memset(tbuffer, 0, tlen);
- RX_AFS_GUNLOCK();
- bsent = rx_Write(tcall, tbuffer, tlen);
- RX_AFS_GLOCK();
-
- if (bsent != tlen) {
- code = -33; /* XXX */
- break;
- }
- sbytes -= tlen;
- }
- osi_FreeLargeSpace(tbuffer);
- }
- stored += tdc->f.chunkBytes;
-
- /* ideally, I'd like to unlock the dcache and turn
- * off the writing bit here, but that would
- * require being able to retry StoreAllSegments in
- * the event of a failure. It only really matters
- * if user can't read from a 'locked' dcache or
- * one which has the writing bit turned on. */
- }
- if (!code) {
- struct AFSVolSync tsync;
- RX_AFS_GUNLOCK();
- code =
- EndRXAFS_StoreData(tcall, &OutStatus, &tsync);
- RX_AFS_GLOCK();
- hadd32(newDV, 1);
- XSTATS_END_TIME;
- if (!code)
- doProcessFS = 1; /* Flag to run afs_ProcessFS() later on */
- }
- if (tcall) {
- afs_int32 code2;
- RX_AFS_GUNLOCK();
- code2 = rx_EndCall(tcall, code);
- RX_AFS_GLOCK();
- if (code2)
- code = code2;
- }
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_STOREDATA, SHARED_LOCK,
- NULL));
-
- /* put back all remaining locked dcache entries */
- for (i = 0; i < nchunks; i++) {
- tdc = dclist[i];
- if (!code) {
- if (afs_indexFlags[tdc->index] & IFDataMod) {
- /*
- * LOCKXXX -- should hold afs_xdcache(W) when
- * modifying afs_indexFlags.
- */
- afs_indexFlags[tdc->index] &= ~IFDataMod;
- afs_stats_cmperf.cacheCurrDirtyChunks--;
- afs_indexFlags[tdc->index] &= ~IFDirtyPages;
- if (sync & AFS_VMSYNC_INVAL) {
- /* since we have invalidated all the pages of this
- ** vnode by calling osi_VM_TryToSmush, we can
- ** safely mark this dcache entry as not having
- ** any pages. This vnode now becomes eligible for
- ** reclamation by getDownD.
- */
- afs_indexFlags[tdc->index] &= ~IFAnyPages;
- }
- }
- }
- UpgradeSToWLock(&tdc->lock, 628);
- tdc->f.states &= ~DWriting; /* correct? */
- tdc->dflags |= DFEntryMod;
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- /* Mark the entry as released */
- dclist[i] = NULL;
- }
-
- if (doProcessFS) {
- /* Now copy out return params */
- UpgradeSToWLock(&avc->lock, 28); /* keep out others for a while */
- afs_ProcessFS(avc, &OutStatus, areq);
- /* Keep last (max) size of file on server to see if
- * we need to call afs_StoreMini to extend the file.
- */
- if (!moredata)
- maxStoredLength = OutStatus.Length;
- ConvertWToSLock(&avc->lock);
- doProcessFS = 0;
- }
-
- if (code) {
- for (j++; j <= high; j++) {
- if (dcList[j]) {
- ReleaseSharedLock(&(dcList[j]->lock));
- afs_PutDCache(dcList[j]);
- /* Releasing entry */
- dcList[j] = NULL;
- }
- }
- }
-
- afs_Trace2(afs_iclSetp, CM_TRACE_STOREALLDCDONE,
- ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code);
- bytes = 0;
- }
- }
-
- /* Release any zero-length dcache entries in our interval
- * that we locked but didn't store back above.
- */
- for (j = 0; j <= high; j++) {
- tdc = dcList[j];
- if (tdc) {
- osi_Assert(tdc->f.chunkBytes == 0);
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- }
- }
- /* if (j) */
- minj += NCHUNKSATONCE;
- } while (!code && moredata);
-
- UpgradeSToWLock(&avc->lock, 29);
-
- /* send a trivial truncation store if did nothing else */
- if (code == 0) {
- /*
- * Call StoreMini if we haven't written enough data to extend the
- * file at the fileserver to the client's notion of the file length.
- */
- if ((avc->truncPos != AFS_NOTRUNC) || ((avc->states & CExtendedFile)
- && (maxStoredLength <
- avc->m.Length))) {
- code = afs_StoreMini(avc, areq);
- if (code == 0)
- hadd32(newDV, 1); /* just bumped here, too */
- }
- avc->states &= ~CExtendedFile;
- }
-
- /*
- * Finally, turn off DWriting, turn on DFEntryMod,
- * update f.versionNo.
- * A lot of this could be integrated into the loop above
- */
- if (!code) {
- afs_hyper_t h_unset;
- hones(h_unset);
-
- minj = 0;
-
- do {
- moredata = FALSE;
- memset((char *)dcList, 0,
- NCHUNKSATONCE * sizeof(struct dcache *));
-
- /* overkill, but it gets the lock in case GetDSlot needs it */
- MObtainWriteLock(&afs_xdcache, 285);
-
- for (j = 0, safety = 0, index = afs_dvhashTbl[hash];
- index != NULLIDX && safety < afs_cacheFiles + 2;) {
-
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, 0);
- ReleaseReadLock(&tdc->tlock);
-
- if (!FidCmp(&tdc->f.fid, &avc->fid)
- && tdc->f.chunk >= minj) {
- off = tdc->f.chunk - minj;
- if (off < NCHUNKSATONCE) {
- /* this is the file, and the correct chunk range */
- if (j >= NCHUNKSATONCE)
- osi_Panic
- ("Too many dcache entries in range\n");
- dcList[j++] = tdc;
- } else {
- moredata = TRUE;
- afs_PutDCache(tdc);
- if (j == NCHUNKSATONCE)
- break;
- }
- } else {
- afs_PutDCache(tdc);
- }
- }
-
- index = afs_dvnextTbl[index];
- }
- MReleaseWriteLock(&afs_xdcache);
-
- for (i = 0; i < j; i++) {
- /* Iterate over the dcache entries we collected above */
- tdc = dcList[i];
- ObtainSharedLock(&tdc->lock, 677);
-
- /* was code here to clear IFDataMod, but it should only be done
- * in storedcache and storealldcache.
- */
- /* Only increase DV if we had up-to-date data to start with.
- * Otherwise, we could be falsely upgrading an old chunk
- * (that we never read) into one labelled with the current
- * DV #. Also note that we check that no intervening stores
- * occurred, otherwise we might mislabel cache information
- * for a chunk that we didn't store this time
- */
- /* Don't update the version number if it's not yet set. */
- if (!hsame(tdc->f.versionNo, h_unset)
- && hcmp(tdc->f.versionNo, oldDV) >= 0) {
-
- if ((!(afs_dvhack || foreign)
- && hsame(avc->m.DataVersion, newDV))
- || ((afs_dvhack || foreign)
- && (origCBs == afs_allCBs))) {
- /* no error, this is the DV */
-
- UpgradeSToWLock(&tdc->lock, 678);
- hset(tdc->f.versionNo, avc->m.DataVersion);
- tdc->dflags |= DFEntryMod;
- ConvertWToSLock(&tdc->lock);
- }
- }
-
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
-
- minj += NCHUNKSATONCE;
-
- } while (moredata);
- }
-
- if (code) {
- /*
- * Invalidate chunks after an error for ccores files since
- * afs_inactive won't be called for these and they won't be
- * invalidated. Also discard data if it's a permanent error from the
- * fileserver.
- */
- if (areq->permWriteError || (avc->states & (CCore1 | CCore))) {
- afs_InvalidateAllSegments(avc);
- }
- }
- afs_Trace3(afs_iclSetp, CM_TRACE_STOREALLDONE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, avc->m.Length, ICL_TYPE_INT32, code);
- /* would like a Trace5, but it doesn't exist... */
- afs_Trace3(afs_iclSetp, CM_TRACE_AVCLOCKER, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, avc->lock.wait_states, ICL_TYPE_INT32,
- avc->lock.excl_locked);
- afs_Trace4(afs_iclSetp, CM_TRACE_AVCLOCKEE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, avc->lock.wait_states, ICL_TYPE_INT32,
- avc->lock.readers_reading, ICL_TYPE_INT32,
- avc->lock.num_waiting);
-
- /*
- * Finally, if updated DataVersion matches newDV, we did all of the
- * stores. If mapDV indicates that the page cache was flushed up
- * to when we started the store, then we can relabel them as flushed
- * as recently as newDV.
- * Turn off CDirty bit because the stored data is now in sync with server.
- */
- if (code == 0 && hcmp(avc->mapDV, oldDV) >= 0) {
- if ((!(afs_dvhack || foreign) && hsame(avc->m.DataVersion, newDV))
- || ((afs_dvhack || foreign) && (origCBs == afs_allCBs))) {
- hset(avc->mapDV, newDV);
- avc->states &= ~CDirty;
- }
- }
- osi_FreeLargeSpace(dcList);
-
- /* If not the final write a temporary error is ok. */
- if (code && !areq->permWriteError && !(sync & AFS_LASTSTORE))
- code = 0;
-
- return code;
-
-} /*afs_StoreAllSegments (new 03/02/94) */
-
-
-/*
- * afs_InvalidateAllSegments
- *
- * Description:
- * Invalidates all chunks for a given file
- *
- * Parameters:
- * avc : Pointer to vcache entry.
- *
- * Environment:
- * For example, called after an error has been detected. Called
- * with avc write-locked, and afs_xdcache unheld.
- */
-
-int
-afs_InvalidateAllSegments(struct vcache *avc)
-{
- struct dcache *tdc;
- afs_int32 hash;
- afs_int32 index;
- struct dcache **dcList;
- int i, dcListMax, dcListCount;
-
- AFS_STATCNT(afs_InvalidateAllSegments);
- afs_Trace2(afs_iclSetp, CM_TRACE_INVALL, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
- hash = DVHash(&avc->fid);
- avc->truncPos = AFS_NOTRUNC; /* don't truncate later */
- avc->states &= ~CExtendedFile; /* not any more */
- ObtainWriteLock(&afs_xcbhash, 459);
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CDirty); /* mark status information as bad, too */
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- /* Blow away pages; for now, only for Solaris */
-#if (defined(AFS_SUN5_ENV))
- if (WriteLocked(&avc->lock))
- osi_ReleaseVM(avc, (struct AFS_UCRED *)0);
-#endif
- /*
- * Block out others from screwing with this table; is a read lock
- * sufficient?
- */
- MObtainWriteLock(&afs_xdcache, 286);
- dcListMax = 0;
-
- for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, 0);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid))
- dcListMax++;
- afs_PutDCache(tdc);
- }
- index = afs_dvnextTbl[index];
- }
-
- dcList = osi_Alloc(dcListMax * sizeof(struct dcache *));
- dcListCount = 0;
-
- for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, 0);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid)) {
- /* same file? we'll zap it */
- if (afs_indexFlags[index] & IFDataMod) {
- afs_stats_cmperf.cacheCurrDirtyChunks--;
- /* don't write it back */
- afs_indexFlags[index] &= ~IFDataMod;
- }
- afs_indexFlags[index] &= ~IFAnyPages;
- if (dcListCount < dcListMax)
- dcList[dcListCount++] = tdc;
- else
- afs_PutDCache(tdc);
- } else {
- afs_PutDCache(tdc);
- }
- }
- index = afs_dvnextTbl[index];
- }
- MReleaseWriteLock(&afs_xdcache);
-
- for (i = 0; i < dcListCount; i++) {
- tdc = dcList[i];
-
- ObtainWriteLock(&tdc->lock, 679);
- ZapDCE(tdc);
- if (vType(avc) == VDIR)
- DZap(&tdc->f.inode);
- ReleaseWriteLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
-
- osi_Free(dcList, dcListMax * sizeof(struct dcache *));
-
- return 0;
-}
-
-
-/*
- * afs_TruncateAllSegments
- *
- * Description:
- * Truncate a cache file.
- *
- * Parameters:
- * avc : Ptr to vcache entry to truncate.
- * alen : Number of bytes to make the file.
- * areq : Ptr to request structure.
- *
- * Environment:
- * Called with avc write-locked; in VFS40 systems, pvnLock is also
- * held.
- */
-int
-afs_TruncateAllSegments(register struct vcache *avc, afs_size_t alen,
- struct vrequest *areq, struct AFS_UCRED *acred)
-{
- register struct dcache *tdc;
- register afs_int32 code;
- register afs_int32 index;
- afs_int32 newSize;
-
- int dcCount, dcPos;
- struct dcache **tdcArray;
-
- AFS_STATCNT(afs_TruncateAllSegments);
- avc->m.Date = osi_Time();
- afs_Trace3(afs_iclSetp, CM_TRACE_TRUNCALL, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(alen));
- if (alen >= avc->m.Length) {
- /*
- * Special speedup since Sun's vm extends the file this way;
- * we've never written to the file thus we can just set the new
- * length and avoid the needless calls below.
- * Also used for ftruncate calls which can extend the file.
- * To completely minimize the possible extra StoreMini RPC, we really
- * should keep the ExtendedPos as well and clear this flag if we
- * truncate below that value before we store the file back.
- */
- avc->states |= CExtendedFile;
- avc->m.Length = alen;
- return 0;
- }
-#if (defined(AFS_SUN5_ENV))
-
- /* Zero unused portion of last page */
- osi_VM_PreTruncate(avc, alen, acred);
-
-#endif
-
-#if (defined(AFS_SUN5_ENV))
- ObtainWriteLock(&avc->vlock, 546);
- avc->activeV++; /* Block new getpages */
- ReleaseWriteLock(&avc->vlock);
-#endif
-
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
-
- /* Flush pages beyond end-of-file. */
- osi_VM_Truncate(avc, alen, acred);
-
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 79);
-
- avc->m.Length = alen;
-
- if (alen < avc->truncPos)
- avc->truncPos = alen;
- code = DVHash(&avc->fid);
-
- /* block out others from screwing with this table */
- MObtainWriteLock(&afs_xdcache, 287);
-
- dcCount = 0;
- for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, 0);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid))
- dcCount++;
- afs_PutDCache(tdc);
- }
- index = afs_dvnextTbl[index];
- }
-
- /* Now allocate space where we can save those dcache entries, and
- * do a second pass over them.. Since we're holding xdcache, it
- * shouldn't be changing.
- */
- tdcArray = osi_Alloc(dcCount * sizeof(struct dcache *));
- dcPos = 0;
-
- for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
- if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
- tdc = afs_GetDSlot(index, 0);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, &avc->fid)) {
- /* same file, and modified, we'll store it back */
- if (dcPos < dcCount) {
- tdcArray[dcPos++] = tdc;
- } else {
- afs_PutDCache(tdc);
- }
- } else {
- afs_PutDCache(tdc);
- }
- }
- index = afs_dvnextTbl[index];
- }
-
- MReleaseWriteLock(&afs_xdcache);
-
- /* Now we loop over the array of dcache entries and truncate them */
- for (index = 0; index < dcPos; index++) {
- struct osi_file *tfile;
-
- tdc = tdcArray[index];
-
- newSize = alen - AFS_CHUNKTOBASE(tdc->f.chunk);
- if (newSize < 0)
- newSize = 0;
- ObtainSharedLock(&tdc->lock, 672);
- if (newSize < tdc->f.chunkBytes) {
- UpgradeSToWLock(&tdc->lock, 673);
- tfile = afs_CFileOpen(tdc->f.inode);
- afs_CFileTruncate(tfile, newSize);
- afs_CFileClose(tfile);
- afs_AdjustSize(tdc, newSize);
- ConvertWToSLock(&tdc->lock);
- }
- ReleaseSharedLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
-
- osi_Free(tdcArray, dcCount * sizeof(struct dcache *));
-
-#if (defined(AFS_SUN5_ENV))
- ObtainWriteLock(&avc->vlock, 547);
- if (--avc->activeV == 0 && (avc->vstates & VRevokeWait)) {
- avc->vstates &= ~VRevokeWait;
- afs_osi_Wakeup((char *)&avc->vstates);
- }
- ReleaseWriteLock(&avc->vlock);
-#endif
- 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
- */
-
-/*
- * Implements:
- * afs_MarkServerUpOrDown
- * afs_ServerDown
- * afs_CountServers
- * afs_CheckServers
- * afs_FindServer
- * afs_random
- * afs_randomMod127
- * afs_SortServers
- * afsi_SetServerIPRank
- * afs_GetServer
- * afs_ActivateServer
- *
- *
- * Local:
- * HaveCallBacksFrom
- * CheckVLServer
- * afs_SortOneServer
- * afs_SetServerPrefs
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_server.c,v 1.29 2004/05/08 04:23:56 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* AFS_HPUX110_ENV */
-#ifdef AFS_DARWIN60_ENV
-#include <net/if_var.h>
-#endif
-#endif /* !defined(UKERNEL) */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-#include "rx/rx_multi.h"
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-# include <netinet/ip6.h>
-# define ipif_local_addr ipif_lcl_addr
-# ifndef V4_PART_OF_V6
-# define V4_PART_OF_V6(v6) v6.s6_addr32[3]
-# endif
-# endif
-#include <inet/ip.h>
-#endif
-
-/* Exported variables */
-afs_rwlock_t afs_xserver; /* allocation lock for servers */
-struct server *afs_setTimeHost = 0; /* last host we used for time */
-struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
-afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
-struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
-
-
-/* debugging aids - number of alloc'd server and srvAddr structs. */
-int afs_reuseServers = 0;
-int afs_reuseSrvAddrs = 0;
-int afs_totalServers = 0;
-int afs_totalSrvAddrs = 0;
-
-
-
-static struct afs_stats_SrvUpDownInfo *
-GetUpDownStats(struct server *srv)
-{
- struct afs_stats_SrvUpDownInfo *upDownP;
- u_short fsport = AFS_FSPORT;
-
- if (srv->cell)
- fsport = srv->cell->fsport;
-
- if (srv->addr->sa_portal == fsport)
- upDownP = afs_stats_cmperf.fs_UpDown;
- else
- upDownP = afs_stats_cmperf.vl_UpDown;
-
- if (srv->cell && afs_IsPrimaryCell(srv->cell))
- return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
- else
- return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
-}
-
-
-/*------------------------------------------------------------------------
- * afs_MarkServerUpOrDown
- *
- * Description:
- * Mark the given server up or down, and track its uptime stats.
- *
- * Arguments:
- * a_serverP : Ptr to server record to fiddle with.
- * a_isDown : Is the server is to be marked down?
- *
- * Returns:
- * Nothing.
- *
- * Environment:
- * The CM server structures must be write-locked.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-void
-afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
-{
- register struct server *a_serverP = sa->server;
- register struct srvAddr *sap;
- osi_timeval_t currTime, *currTimeP; /*Current time */
- afs_int32 downTime; /*Computed downtime, in seconds */
- struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
-
- /*
- * If the server record is marked the same as the new status we've
- * been fed, then there isn't much to be done.
- */
- if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
- || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
- return;
-
- if (a_isDown) {
- sa->sa_flags |= SRVADDR_ISDOWN;
- for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
- if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
- /* Not all ips are up so don't bother with the
- * server's up/down stats */
- return;
- }
- }
- /*
- * All ips are down we treat the whole server down
- */
- a_serverP->flags |= SRVR_ISDOWN;
- /*
- * If this was our time server, search for another time server
- */
- if (a_serverP == afs_setTimeHost)
- afs_setTimeHost = 0;
- } else {
- sa->sa_flags &= ~SRVADDR_ISDOWN;
- /* If any ips are up, the server is also marked up */
- a_serverP->flags &= ~SRVR_ISDOWN;
- for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
- if (sap->sa_flags & SRVADDR_ISDOWN) {
- /* Not all ips are up so don't bother with the
- * server's up/down stats */
- return;
- }
- }
- }
-#ifndef AFS_NOSTATS
- /*
- * Compute the current time and which overall stats record is to be
- * updated; we'll need them one way or another.
- */
- currTimeP = &currTime;
- osi_GetuTime(currTimeP);
-
- upDownP = GetUpDownStats(a_serverP);
-
- if (a_isDown) {
- /*
- * Server going up -> down; remember the beginning of this
- * downtime incident.
- */
- a_serverP->lastDowntimeStart = currTime.tv_sec;
-
- (upDownP->numDownRecords)++;
- (upDownP->numUpRecords)--;
- } /*Server being marked down */
- else {
- /*
- * Server going down -> up; remember everything about this
- * newly-completed downtime incident.
- */
- downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
- (a_serverP->numDowntimeIncidents)++;
- a_serverP->sumOfDowntimes += downTime;
-
- (upDownP->numUpRecords)++;
- (upDownP->numDownRecords)--;
- (upDownP->numDowntimeIncidents)++;
- if (a_serverP->numDowntimeIncidents == 1)
- (upDownP->numRecordsNeverDown)--;
- upDownP->sumOfDowntimes += downTime;
- if ((upDownP->shortestDowntime == 0)
- || (downTime < upDownP->shortestDowntime))
- upDownP->shortestDowntime = downTime;
- if ((upDownP->longestDowntime == 0)
- || (downTime > upDownP->longestDowntime))
- upDownP->longestDowntime = downTime;
-
-
- if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
- (upDownP->downDurations[0])++;
- else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
- (upDownP->downDurations[1])++;
- else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
- (upDownP->downDurations[2])++;
- else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
- (upDownP->downDurations[3])++;
- else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
- (upDownP->downDurations[4])++;
- else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
- (upDownP->downDurations[5])++;
- else
- (upDownP->downDurations[6])++;
-
- } /*Server being marked up */
-#endif
-} /*MarkServerUpOrDown */
-
-
-void
-afs_ServerDown(struct srvAddr *sa)
-{
- register struct server *aserver = sa->server;
-
- AFS_STATCNT(ServerDown);
- if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
- return;
- afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
- if (sa->sa_portal == aserver->cell->vlport)
- print_internet_address
- ("afs: Lost contact with volume location server ", sa, "", 1);
- else
- print_internet_address("afs: Lost contact with file server ", sa, "",
- 1);
-
-} /*ServerDown */
-
-
-/* return true if we have any callback promises from this server */
-static int
-HaveCallBacksFrom(struct server *aserver)
-{
- register afs_int32 now;
- register int i;
- register struct vcache *tvc;
-
- AFS_STATCNT(HaveCallBacksFrom);
- now = osi_Time(); /* for checking for expired callbacks */
- for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- /*
- * Check to see if this entry has an unexpired callback promise
- * from the required host
- */
- if (aserver == tvc->callback && tvc->cbExpires >= now
- && ((tvc->states & CRO) == 0))
- return 1;
- }
- }
- return 0;
-
-} /*HaveCallBacksFrom */
-
-
-static void
-CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
-{
- register struct server *aserver = sa->server;
- register struct conn *tc;
- register afs_int32 code;
-
- AFS_STATCNT(CheckVLServer);
- /* Ping dead servers to see if they're back */
- if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
- || (aserver->flags & SRVR_ISGONE))
- return;
- if (!aserver->cell)
- return; /* can't do much */
-
- tc = afs_ConnByHost(aserver, aserver->cell->vlport,
- aserver->cell->cellNum, areq, 1, SHARED_LOCK);
- if (!tc)
- return;
- rx_SetConnDeadTime(tc->id, 3);
-
- RX_AFS_GUNLOCK();
- code = VL_ProbeServer(tc->id);
- RX_AFS_GLOCK();
- rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
- afs_PutConn(tc, SHARED_LOCK);
- /*
- * If probe worked, or probe call not yet defined (for compatibility
- * with old vlsevers), then we treat this server as running again
- */
- if (code == 0 || (code <= -450 && code >= -470)) {
- if (tc->srvr == sa) {
- afs_MarkServerUpOrDown(sa, 0);
- print_internet_address("afs: volume location server ", sa,
- " is back up", 2);
- }
- }
-
-} /*CheckVLServer */
-
-
-#ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
-#define AFS_MINCHANGE 2 /* min change we'll bother with */
-#endif
-#ifndef AFS_MAXCHANGEBACK
-#define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
-#endif
-
-
-/*------------------------------------------------------------------------
- * EXPORTED afs_CountServers
- *
- * Description:
- * Originally meant to count the number of servers and determining
- * up/down info, this routine will now simply sum up all of the
- * server record ages. All other up/down information is kept on the
- * fly.
- *
- * Arguments:
- * None.
- *
- * Returns:
- * Nothing.
- *
- * Environment:
- * This routine locks afs_xserver for write for the duration.
- *
- * Side Effects:
- * Set CM perf stats field sumOfRecordAges for all server record
- * entries.
- *------------------------------------------------------------------------*/
-
-void
-afs_CountServers(void)
-{
- int currIdx; /*Curr idx into srv table */
- struct server *currSrvP; /*Ptr to curr server record */
- afs_int32 currChainLen; /*Length of curr hash chain */
- osi_timeval_t currTime; /*Current time */
- osi_timeval_t *currTimeP; /*Ptr to above */
- afs_int32 srvRecordAge; /*Age of server record, in secs */
- struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
- * info being manipulated */
-
- /*
- * Write-lock the server table so we don't get any interference.
- */
- ObtainReadLock(&afs_xserver);
-
- /*
- * Iterate over each hash index in the server table, walking down each
- * chain and tallying what we haven't computed from the records there on
- * the fly. First, though, initialize the tallies that will change.
- */
- afs_stats_cmperf.srvMaxChainLength = 0;
-
- afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
- afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
- afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
- AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
-
- afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
- afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
- afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
- AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
-
- afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
- afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
- afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
- AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
-
- afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
- afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
- afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
- AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
-
- /*
- * Compute the current time, used to figure out server record ages.
- */
- currTimeP = &currTime;
- osi_GetuTime(currTimeP);
-
- /*
- * Sweep the server hash table, tallying all we need to know.
- */
- for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
- currChainLen = 0;
- for (currSrvP = afs_servers[currIdx]; currSrvP;
- currSrvP = currSrvP->next) {
- /*
- * Bump the current chain length.
- */
- currChainLen++;
-
- /*
- * Any further tallying for this record will only be done if it has
- * been activated.
- */
- if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
- && currSrvP->addr && currSrvP->cell) {
-
- /*
- * Compute the current server record's age, then remember it
- * in the appropriate places.
- */
- srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
- upDownP = GetUpDownStats(currSrvP);
- upDownP->sumOfRecordAges += srvRecordAge;
- if ((upDownP->ageOfYoungestRecord == 0)
- || (srvRecordAge < upDownP->ageOfYoungestRecord))
- upDownP->ageOfYoungestRecord = srvRecordAge;
- if ((upDownP->ageOfOldestRecord == 0)
- || (srvRecordAge > upDownP->ageOfOldestRecord))
- upDownP->ageOfOldestRecord = srvRecordAge;
-
- if (currSrvP->numDowntimeIncidents <=
- AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
- (upDownP->downIncidents[0])++;
- else if (currSrvP->numDowntimeIncidents <=
- AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
- (upDownP->downIncidents[1])++;
- else if (currSrvP->numDowntimeIncidents <=
- AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
- (upDownP->downIncidents[2])++;
- else if (currSrvP->numDowntimeIncidents <=
- AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
- (upDownP->downIncidents[3])++;
- else if (currSrvP->numDowntimeIncidents <=
- AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
- (upDownP->downIncidents[4])++;
- else
- (upDownP->downIncidents[5])++;
-
-
- } /*Current server has been active */
- } /*Walk this chain */
-
- /*
- * Before advancing to the next chain, remember facts about this one.
- */
- if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
- /*
- * We beat out the former champion (which was initially set to 0
- * here). Mark down the new winner, and also remember if it's an
- * all-time winner.
- */
- afs_stats_cmperf.srvMaxChainLength = currChainLen;
- if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
- afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
- } /*Update chain length maximum */
- } /*For each hash chain */
-
- /*
- * We're done. Unlock the server table before returning to our caller.
- */
- ReleaseReadLock(&afs_xserver);
-
-} /*afs_CountServers */
-
-
-/* check down servers (if adown), or running servers (if !adown) */
-void
-afs_CheckServers(int adown, struct cell *acellp)
-{
- struct vrequest treq;
- struct server *ts;
- struct srvAddr *sa;
- struct conn *tc;
- afs_int32 i, j;
- afs_int32 code;
- afs_int32 start, end, delta;
- osi_timeval_t tv;
- int setTimer;
- struct unixuser *tu;
- char tbuffer[CVBS];
- int srvAddrCount;
- struct srvAddr **addrs;
- struct conn **conns;
- int nconns;
- struct rx_connection **rxconns;
- int nrxconns;
- afs_int32 *conntimer, *deltas;
- XSTATS_DECLS;
-
- AFS_STATCNT(afs_CheckServers);
-
- conns = (struct conn **)0;
- rxconns = (struct rx_connection **) 0;
- conntimer = 0;
- nconns = 0;
-
- if ((code = afs_InitReq(&treq, afs_osi_credp)))
- return;
- ObtainReadLock(&afs_xserver); /* Necessary? */
- ObtainReadLock(&afs_xsrvAddr);
-
- srvAddrCount = 0;
- for (i = 0; i < NSERVERS; i++) {
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- srvAddrCount++;
- }
- }
-
- addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
- j = 0;
- for (i = 0; i < NSERVERS; i++) {
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- if (j >= srvAddrCount)
- break;
- addrs[j++] = sa;
- }
- }
-
- ReleaseReadLock(&afs_xsrvAddr);
- ReleaseReadLock(&afs_xserver);
-
- conns = (struct conn **)afs_osi_Alloc(j * sizeof(struct conn *));
- rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
- conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
- deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
-
- for (i = 0; i < j; i++) {
- deltas[i] = 0;
- sa = addrs[i];
- ts = sa->server;
- if (!ts)
- continue;
-
- /* See if a cell to check was specified. If it is spec'd and not
- * this server's cell, just skip the server.
- */
- if (acellp && acellp != ts->cell)
- continue;
-
- if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
- || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
- continue;
-
- /* check vlserver with special code */
- if (sa->sa_portal == AFS_VLPORT) {
- CheckVLServer(sa, &treq);
- continue;
- }
-
- if (!ts->cell) /* not really an active server, anyway, it must */
- continue; /* have just been added by setsprefs */
-
- /* get a connection, even if host is down; bumps conn ref count */
- tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
- tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
- 1 /*force */ , 1 /*create */ , SHARED_LOCK);
- afs_PutUser(tu, SHARED_LOCK);
- if (!tc)
- continue;
-
- if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(sa->server)
- || (tc->srvr->server == afs_setTimeHost)) {
- conns[nconns]=tc;
- rxconns[nconns]=tc->id;
- if (sa->sa_flags & SRVADDR_ISDOWN) {
- rx_SetConnDeadTime(tc->id, 3);
- conntimer[nconns]=1;
- } else {
- conntimer[nconns]=0;
- }
- nconns++;
- }
- } /* Outer loop over addrs */
-
- start = osi_Time(); /* time the gettimeofday call */
- AFS_GUNLOCK();
- multi_Rx(rxconns,nconns)
- {
- tv.tv_sec = tv.tv_usec = 0;
- multi_RXAFS_GetTime(&tv.tv_sec, &tv.tv_usec);
- tc = conns[multi_i];
- sa = tc->srvr;
- if (conntimer[multi_i] == 0)
- rx_SetConnDeadTime(tc->id, AFS_RXDEADTIME);
- end = osi_Time();
- if ((start == end) && !multi_error)
- deltas[multi_i] = end - tv.tv_sec;
- if (( multi_error >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
- /* server back up */
- print_internet_address("afs: file server ", sa, " is back up", 2);
-
- ObtainWriteLock(&afs_xserver, 244);
- ObtainWriteLock(&afs_xsrvAddr, 245);
- afs_MarkServerUpOrDown(sa, 0);
- ReleaseWriteLock(&afs_xsrvAddr);
- ReleaseWriteLock(&afs_xserver);
-
- if (afs_waitForeverCount) {
- afs_osi_Wakeup(&afs_waitForever);
- }
- } else {
- if (multi_error < 0) {
- /* server crashed */
- afs_ServerDown(sa);
- ForceNewConnections(sa); /* multi homed clients */
- }
- }
-
- } multi_End;
- AFS_GLOCK();
-
- /*
- * If we're supposed to set the time, and the call worked
- * quickly (same second response) and this is the host we
- * use for the time and the time is really different, then
- * really set the time
- */
- if (afs_setTime != 0) {
- for (i=0; i<nconns; i++) {
- delta = deltas[i];
- tc = conns[i];
- sa = tc->srvr;
-
- if ((tc->srvr->server == afs_setTimeHost ||
- /* Sync only to a server in the local cell */
- (afs_setTimeHost == (struct server *)0 &&
- afs_IsPrimaryCell(sa->server->cell)))) {
- /* set the time */
- char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
- delta = end - tv.tv_sec; /* how many secs fast we are */
-
- afs_setTimeHost = tc->srvr->server;
- /* see if clock has changed enough to make it worthwhile */
- if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
- end = osi_Time();
- if (delta > AFS_MAXCHANGEBACK) {
- /* setting clock too far back, just do it a little */
- tv.tv_sec = end - AFS_MAXCHANGEBACK;
- } else {
- tv.tv_sec = end - delta;
- }
- afs_osi_SetTime(&tv);
- if (delta > 0) {
- strcpy(msgbuf, "afs: setting clock back ");
- if (delta > AFS_MAXCHANGEBACK) {
- afs_strcat(msgbuf,
- afs_cv2string(&tbuffer[CVBS],
- AFS_MAXCHANGEBACK));
- afs_strcat(msgbuf, " seconds (of ");
- afs_strcat(msgbuf,
- afs_cv2string(&tbuffer[CVBS],
- delta -
- AFS_MAXCHANGEBACK));
- afs_strcat(msgbuf, ", via ");
- print_internet_address(msgbuf, sa,
- "); clock is still fast.",
- 0);
- } else {
- afs_strcat(msgbuf,
- afs_cv2string(&tbuffer[CVBS], delta));
- afs_strcat(msgbuf, " seconds (via ");
- print_internet_address(msgbuf, sa, ").", 0);
- }
- } else {
- strcpy(msgbuf, "afs: setting clock ahead ");
- afs_strcat(msgbuf,
- afs_cv2string(&tbuffer[CVBS], -delta));
- afs_strcat(msgbuf, " seconds (via ");
- print_internet_address(msgbuf, sa, ").", 0);
- }
- /* We're only going to set it once; why bother looping? */
- break;
- }
- }
- }
- }
- for (i = 0; i < nconns; i++) {
- afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
- }
-
- afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
- afs_osi_Free(conns, j * sizeof(struct conn *));
- afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
- afs_osi_Free(conntimer, j * sizeof(afs_int32));
- afs_osi_Free(deltas, j * sizeof(afs_int32));
-
-} /*afs_CheckServers*/
-
-
-/* find a server structure given the host address */
-struct server *
-afs_FindServer(afs_int32 aserver, ushort aport, afsUUID * uuidp,
- afs_int32 locktype)
-{
- struct server *ts;
- struct srvAddr *sa;
- int i;
-
- AFS_STATCNT(afs_FindServer);
- if (uuidp) {
- i = afs_uuid_hash(uuidp) % NSERVERS;
- for (ts = afs_servers[i]; ts; ts = ts->next) {
- if ((ts->flags & SRVR_MULTIHOMED)
- &&
- (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
- == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
- return ts;
- }
- } else {
- i = SHash(aserver);
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
- return sa->server;
- }
- }
- }
- return NULL;
-
-} /*afs_FindServer */
-
-
-/* some code for creating new server structs and setting preferences follows
- * in the next few lines...
- */
-
-#define MAXDEFRANK 60000
-#define DEFRANK 40000
-
-/* Random number generator and constants from KnuthV2 2d ed, p170 */
-
-/* Rules:
- X = (aX + c) % m
- m is a power of two
- a % 8 is 5
- a is 0.73m should be 0.01m .. 0.99m
- c is more or less immaterial. 1 or a is suggested.
-
-NB: LOW ORDER BITS are not very random. To get small random numbers,
- treat result as <1, with implied binary point, and multiply by
- desired modulus.
-NB: Has to be unsigned, since shifts on signed quantities may preserve
- the sign bit.
-*/
-/* added rxi_getaddr() to try to get as much initial randomness as
- possible, since at least one customer reboots ALL their clients
- simultaneously -- so osi_Time is bound to be the same on some of the
- clients. This is probably OK, but I don't want to see too much of it.
-*/
-
-#define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
-
-unsigned int
-afs_random(void)
-{
- static afs_int32 state = 0;
- register int i;
-
- AFS_STATCNT(afs_random);
- if (!state) {
- osi_timeval_t t;
- osi_GetTime(&t);
- /*
- * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
- * bits are in a tv_usec
- */
- state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
- state += (t.tv_sec & 0xff);
- for (i = 0; i < 30; i++) {
- ranstage(state);
- }
- }
-
- ranstage(state);
- return (state);
-
-} /*afs_random */
-
-/* returns int 0..14 using the high bits of a pseudo-random number instead of
- the low bits, as the low bits are "less random" than the high ones...
- slight roundoff error exists, an excercise for the reader.
- need to multiply by something with lots of ones in it, so multiply by
- 8 or 16 is right out.
- */
-int
-afs_randomMod15(void)
-{
- afs_uint32 temp;
-
- temp = afs_random() >> 4;
- temp = (temp * 15) >> 28;
-
- return temp;
-}
-
-int
-afs_randomMod127(void)
-{
- afs_uint32 temp;
-
- temp = afs_random() >> 7;
- temp = (temp * 127) >> 25;
-
- return temp;
-}
-
-/* afs_SortOneServer()
- * Sort all of the srvAddrs, of a server struct, by rank from low to high.
- */
-void
-afs_SortOneServer(struct server *asp)
-{
- struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
- int lowrank, rank;
-
- for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
- lowprev = NULL;
- lowsa = *rootsa; /* lowest sa is the first one */
- lowrank = lowsa->sa_iprank;
-
- for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
- rank = tsa->next_sa->sa_iprank;
- if (rank < lowrank) {
- lowprev = tsa;
- lowsa = tsa->next_sa;
- lowrank = lowsa->sa_iprank;
- }
- }
- if (lowprev) { /* found one lower, so rearrange them */
- lowprev->next_sa = lowsa->next_sa;
- lowsa->next_sa = *rootsa;
- *rootsa = lowsa;
- }
- }
-}
-
-/* afs_SortServer()
- * Sort the pointer to servers by the server's rank (its lowest rank).
- * It is assumed that the server already has its IP addrs sorted (the
- * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
- */
-void
-afs_SortServers(struct server *aservers[], int count)
-{
- struct server *ts;
- int i, j, low;
-
- AFS_STATCNT(afs_SortServers);
-
- for (i = 0; i < count; i++) {
- if (!aservers[i])
- break;
- for (low = i, j = i + 1; j <= count; j++) {
- if ((!aservers[j]) || (!aservers[j]->addr))
- break;
- if ((!aservers[low]) || (!aservers[low]->addr))
- break;
- if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
- low = j;
- }
- }
- if (low != i) {
- ts = aservers[i];
- aservers[i] = aservers[low];
- aservers[low] = ts;
- }
- }
-} /*afs_SortServers */
-
-/* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
- data structures to determine what the local IP addresses and subnet masks
- are in order to choose which server(s) are on the local subnet.
-
- As I see it, there are several cases:
- 1. The server address is one of this host's local addresses. In this case
- this server is to be preferred over all others.
- 2. The server is on the same subnet as one of the this host's local
- addresses. (ie, an odd-sized subnet, not class A,B,orC)
- 3. The server is on the same net as this host (class A,B or C)
- 4. The server is on a different logical subnet or net than this host, but
- this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
- one physical medium.
- 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
- server.
- 6. This host and the server are disjoint.
-
- That is a rough order of preference. If a point-to-point link has a high
- metric, I'm assuming that it is a very slow link, and putting it at the
- bottom of the list (at least until RX works better over slow links). If
- its metric is 1, I'm assuming that it's relatively fast (T1) and putting
- it ahead of #6.
- It's not easy to check for case #4, so I'm ignoring it for the time being.
-
- BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
- That could be used to prefer certain servers fairly easily. Maybe some
- other time...
-
- NOTE: this code is very system-dependent, and very dependent on the TCP/IP
- protocols (well, addresses that are stored in uint32s, at any rate).
- */
-
-#define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
-#define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
-
-/* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
-#define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
-#define TOPR 5000
-#define HI 20000
-#define MED 30000
-#define LO DEFRANK
-#define PPWEIGHT 4096
-
-#define USEIFADDR
-
-
-#if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
-#include <inet/common.h>
-/* IP interface structure, one per local address */
-typedef struct ipif_s {
- /**/ struct ipif_s *ipif_next;
- struct ill_s *ipif_ill; /* Back pointer to our ill */
- long ipif_id; /* Logical unit number */
- u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
- afs_int32 ipif_local_addr; /* Local IP address for this if. */
- afs_int32 ipif_net_mask; /* Net mask for this interface. */
- afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
- afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
- u_int ipif_flags; /* Interface flags. */
- u_int ipif_metric; /* BSD if metric, for compatibility. */
- u_int ipif_ire_type; /* LOCAL or LOOPBACK */
- mblk_t *ipif_arp_down_mp; /* Allocated at time arp comes up to
- * prevent awkward out of mem condition
- * later
- */
- mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
- * RESOLVER on this interface so that
- * they can survive ifconfig down.
- */
- /*
- * The packet counts in the ipif contain the sum of the
- * packet counts in dead IREs that were affiliated with
- * this ipif.
- */
- u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
- u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
- u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
- unsigned int
- ipif_multicast_up:1, /* We have joined the allhosts group */
- : 0;
-} ipif_t;
-
-typedef struct ipfb_s {
- /**/ struct ipf_s *ipfb_ipf; /* List of ... */
- kmutex_t ipfb_lock; /* Protect all ipf in list */
-} ipfb_t;
-
-typedef struct ilm_s {
- /**/ afs_int32 ilm_addr;
- int ilm_refcnt;
- u_int ilm_timer; /* IGMP */
- struct ipif_s *ilm_ipif; /* Back pointer to ipif */
- struct ilm_s *ilm_next; /* Linked list for each ill */
-} ilm_t;
-
-typedef struct ill_s {
- /**/ struct ill_s *ill_next; /* Chained in at ill_g_head. */
- struct ill_s **ill_ptpn; /* Pointer to previous next. */
- queue_t *ill_rq; /* Read queue. */
- queue_t *ill_wq; /* Write queue. */
-
- int ill_error; /* Error value sent up by device. */
-
- ipif_t *ill_ipif; /* Interface chain for this ILL. */
- u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
- u_int ill_max_frag; /* Max IDU. */
- char *ill_name; /* Our name. */
- u_int ill_name_length; /* Name length, incl. terminator. */
- u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
- u_int ill_ppa; /* Physical Point of Attachment num. */
- u_long ill_sap;
- int ill_sap_length; /* Including sign (for position) */
- u_int ill_phys_addr_length; /* Excluding the sap. */
- mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
- ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
-
- queue_t *ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
- ipif_t *ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
-
- /* ill_hdr_length and ill_hdr_mp will be non zero if
- * the underlying device supports the M_DATA fastpath
- */
- int ill_hdr_length;
-
- ilm_t *ill_ilm; /* Multicast mebership for lower ill */
-
- /* All non-nil cells between 'ill_first_mp_to_free' and
- * 'ill_last_mp_to_free' are freed in ill_delete.
- */
-#define ill_first_mp_to_free ill_hdr_mp
- mblk_t *ill_hdr_mp; /* Contains fastpath template */
- mblk_t *ill_bcast_mp; /* DLPI header for broadcasts. */
- mblk_t *ill_bind_pending; /* T_BIND_REQ awaiting completion. */
- mblk_t *ill_resolver_mp; /* Resolver template. */
- mblk_t *ill_attach_mp;
- mblk_t *ill_bind_mp;
- mblk_t *ill_unbind_mp;
- mblk_t *ill_detach_mp;
-#define ill_last_mp_to_free ill_detach_mp
-
- u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
- ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
- MI_HRT_DCL(ill_rtime)
- MI_HRT_DCL(ill_rtmp)
-} ill_t;
-#endif
-
-#ifdef AFS_USERSPACE_IP_ADDR
-#ifndef afs_min
-#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
-#endif
-/*
- * The IP addresses and ranks are determined by afsd (in user space) and
- * passed into the kernel at startup time through the AFSOP_ADVISEADDR
- * system call. These are stored in the data structure
- * called 'afs_cb_interface'.
- *
- * struct srvAddr *sa; remote server
- * afs_int32 addr; one of my local addr in net order
- * afs_uint32 subnetmask; subnet mask of local addr in net order
- *
- */
-int
-afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
- afs_uint32 subnetmask)
-{
- afs_uint32 myAddr, myNet, mySubnet, netMask;
- afs_uint32 serverAddr;
-
- myAddr = ntohl(addr); /* one of my IP addr in host order */
- serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
- subnetmask = ntohl(subnetmask); /* subnet mask in host order */
-
- if (IN_CLASSA(myAddr))
- netMask = IN_CLASSA_NET;
- else if (IN_CLASSB(myAddr))
- netMask = IN_CLASSB_NET;
- else if (IN_CLASSC(myAddr))
- netMask = IN_CLASSC_NET;
- else
- netMask = 0;
-
- myNet = myAddr & netMask;
- mySubnet = myAddr & subnetmask;
-
- if ((serverAddr & netMask) == myNet) {
- if ((serverAddr & subnetmask) == mySubnet) {
- if (serverAddr == myAddr) { /* same machine */
- sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
- } else { /* same subnet */
- sa->sa_iprank = afs_min(sa->sa_iprank, HI);
- }
- } else { /* same net */
- sa->sa_iprank = afs_min(sa->sa_iprank, MED);
- }
- }
-}
-#else /* AFS_USERSPACE_IP_ADDR */
-#if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
-void
-afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
-{
- struct sockaddr_in *sin;
- int t;
-
- if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
- if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
- sin = IA_SIN(ifa);
- if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
- sa->sa_iprank = TOPR;
- } else {
- t = HI + ifa->ia_ifp->if_metric; /* case #2 */
- if (sa->sa_iprank > t)
- sa->sa_iprank = t;
- }
- } else {
- t = MED + ifa->ia_ifp->if_metric; /* case #3 */
- if (sa->sa_iprank > t)
- sa->sa_iprank = t;
- }
- }
-#ifdef IFF_POINTTOPOINT
- /* check for case #4 -- point-to-point link */
- if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
- && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
- if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
- t = MAXDEFRANK;
- else
- t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
- if (sa->sa_iprank > t)
- sa->sa_iprank = t;
- }
-#endif /* IFF_POINTTOPOINT */
-}
-#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
-#ifndef afs_min
-#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
-#endif
-void
-afsi_SetServerIPRank(sa, ifa)
- struct srvAddr *sa;
- struct ifaddr *ifa;
-{
- struct sockaddr_in *sin;
- int t;
-
- afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
- afs_uint32 serverAddr;
-
- if (ifa->ifa_addr->sa_family != AF_INET)
- return;
- sin = (struct sockaddr_in *)ifa->ifa_addr;
- myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
- serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
- sin = (struct sockaddr_in *)ifa->ifa_netmask;
- subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
- sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
- if (sin)
- myDstaddr = sin->sin_addr.s_addr;
-
- if (IN_CLASSA(myAddr))
- netMask = IN_CLASSA_NET;
- else if (IN_CLASSB(myAddr))
- netMask = IN_CLASSB_NET;
- else if (IN_CLASSC(myAddr))
- netMask = IN_CLASSC_NET;
- else
- netMask = 0;
-
- myNet = myAddr & netMask;
- mySubnet = myAddr & subnetmask;
-
- if ((serverAddr & netMask) == myNet) {
- if ((serverAddr & subnetmask) == mySubnet) {
- if (serverAddr == myAddr) { /* same machine */
- sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
- } else { /* same subnet */
- sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifa->ifa_metric);
- }
- } else { /* same net */
- sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifa->ifa_metric);
- }
- }
-#ifdef IFF_POINTTOPOINT
- /* check for case #4 -- point-to-point link */
- if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
- && (myDstaddr == serverAddr))
- ) {
- if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
- t = MAXDEFRANK;
- else
- t = MED + (PPWEIGHT << ifa->->ifa_metric);
- if (sa->sa_iprank > t)
- sa->sa_iprank = t;
- }
-#endif /* IFF_POINTTOPOINT */
-}
-#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#endif /* else AFS_USERSPACE_IP_ADDR */
-
-#ifdef AFS_SGI62_ENV
-static int
-
- afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
- caddr_t arg2) {
- afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
- return 0; /* Never match, so we enumerate everyone */
-}
-#endif /* AFS_SGI62_ENV */
-static int afs_SetServerPrefs(struct srvAddr *sa) {
-#if defined(AFS_USERSPACE_IP_ADDR)
- int i;
-
- sa->sa_iprank = LO;
- for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
- afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
- afs_cb_interface.subnetmask[i]);
- }
-#else /* AFS_USERSPACE_IP_ADDR */
-#if defined(AFS_SUN5_ENV)
- extern struct ill_s *ill_g_headp;
- ill_t *ill;
- ipif_t *ipif;
- int subnet, subnetmask, net, netmask;
- long *addr = (long *)ill_g_headp;
-
- if (sa)
- sa->sa_iprank = 0;
- for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
- ill = ill->ill_next) {
-#ifdef AFS_SUN58_ENV
- /* Make sure this is an IPv4 ILL */
- if (ill->ill_isv6)
- continue;
-#endif
- for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
- subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
- subnetmask = ipif->ipif_net_mask;
- /*
- * Generate the local net using the local address and
- * whate we know about Class A, B and C networks.
- */
- if (IN_CLASSA(ipif->ipif_local_addr)) {
- netmask = IN_CLASSA_NET;
- } else if (IN_CLASSB(ipif->ipif_local_addr)) {
- netmask = IN_CLASSB_NET;
- } else if (IN_CLASSC(ipif->ipif_local_addr)) {
- netmask = IN_CLASSC_NET;
- } else {
- netmask = 0;
- }
- net = ipif->ipif_local_addr & netmask;
-#ifdef notdef
- if (!s) {
- if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
- *cnt += 1;
- if (*cnt > 16)
- return;
- *addrp++ = ipif->ipif_local_addr;
- }
- } else
-#endif /* notdef */
- {
- /* XXXXXX Do the individual ip ranking below XXXXX */
- if ((sa->sa_ip & netmask) == net) {
- if ((sa->sa_ip & subnetmask) == subnet) {
- if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
- sa->sa_iprank = TOPR;
- } else {
- sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
- }
- } else {
- sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
- }
- } else {
- sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
- }
- /* check for case #5 -- point-to-point link */
- if ((ipif->ipif_flags & IFF_POINTOPOINT)
- && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
-
- if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
- sa->sa_iprank = MAXDEFRANK;
- else
- sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
- }
- }
- }
- }
-#else
-#ifndef USEIFADDR
- struct ifnet *ifn = NULL;
- struct in_ifaddr *ifad = (struct in_ifaddr *)0;
- struct sockaddr_in *sin;
-
- if (!sa) {
-#ifdef notdef /* clean up, remove this */
- for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
- for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
- if ((IFADDR2SA(ifad)->sa_family == AF_INET)
- && !(ifn->if_flags & IFF_LOOPBACK)) {
- *cnt += 1;
- if (*cnt > 16)
- return;
- *addrp++ =
- ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
- s_addr;
- }
- }}
-#endif /* notdef */
- return;
- }
- sa->sa_iprank = 0;
-#ifdef ADAPT_MTU
- ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
-#endif
- if (ifn) { /* local, more or less */
-#ifdef IFF_LOOPBACK
- if (ifn->if_flags & IFF_LOOPBACK) {
- sa->sa_iprank = TOPR;
- goto end;
- }
-#endif /* IFF_LOOPBACK */
- sin = (struct sockaddr_in *)IA_SIN(ifad);
- if (SA2ULONG(sin) == sa->sa_ip) {
- sa->sa_iprank = TOPR;
- goto end;
- }
-#ifdef IFF_BROADCAST
- if (ifn->if_flags & IFF_BROADCAST) {
- if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
- sa->sa_iprank = HI;
- goto end;
- }
- }
-#endif /* IFF_BROADCAST */
-#ifdef IFF_POINTOPOINT
- if (ifn->if_flags & IFF_POINTOPOINT) {
- if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
- if (ifn->if_metric > 4) {
- sa->sa_iprank = LO;
- goto end;
- } else
- sa->sa_iprank = ifn->if_metric;
- }
- }
-#endif /* IFF_POINTOPOINT */
- sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
- }
-#else /* USEIFADDR */
-
- if (sa)
- sa->sa_iprank = LO;
-#ifdef AFS_SGI62_ENV
- (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
- (caddr_t) sa, NULL);
-#elif defined(AFS_DARWIN60_ENV)
- {
- struct ifnet *ifn;
- struct ifaddr *ifa;
- TAILQ_FOREACH(ifn, &ifnet, if_link) {
- TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
- afsi_SetServerIPRank(sa, ifa);
- }}}
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- {
- struct in_ifaddr *ifa;
- TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
- afsi_SetServerIPRank(sa, ifa);
- }}
-#elif defined(AFS_OBSD_ENV)
- {
- extern struct in_ifaddrhead in_ifaddr;
- struct in_ifaddr *ifa;
- for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
- afsi_SetServerIPRank(sa, ifa);
- }
-#else
- {
- struct in_ifaddr *ifa;
- for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
- afsi_SetServerIPRank(sa, ifa);
- }}
-#endif
- end:
-#endif /* USEIFADDR */
-#endif /* AFS_SUN5_ENV */
-#endif /* else AFS_USERSPACE_IP_ADDR */
- if (sa)
- sa->sa_iprank += afs_randomMod15();
-
- return 0;
-} /* afs_SetServerPrefs */
-
-#undef TOPR
-#undef HI
-#undef MED
-#undef LO
-#undef PPWEIGHT
-
-/* afs_FlushServer()
- * The addresses on this server struct has changed in some way and will
- * clean up all other structures that may reference it.
- * The afs_xserver and afs_xsrvAddr locks are assumed taken.
- */
-void afs_FlushServer(struct server *srvp) {
- afs_int32 i;
- struct server *ts, **pts;
-
- /* Find any volumes residing on this server and flush their state */
- afs_ResetVolumes(srvp);
-
- /* Flush all callbacks in the all vcaches for this specific server */
- afs_FlushServerCBs(srvp);
-
- /* Remove all the callbacks structs */
- if (srvp->cbrs) {
- struct afs_cbr *cb, *cbnext;
-
- MObtainWriteLock(&afs_xvcb, 300);
- for (cb = srvp->cbrs; cb; cb = cbnext) {
- cbnext = cb->next;
- afs_FreeCBR(cb);
- } srvp->cbrs = (struct afs_cbr *)0;
- ReleaseWriteLock(&afs_xvcb);
- }
-
- /* If no more srvAddr structs hanging off of this server struct,
- * then clean it up.
- */
- if (!srvp->addr) {
- /* Remove the server structure from the cell list - if there */
- afs_RemoveCellEntry(srvp);
-
- /* Remove from the afs_servers hash chain */
- for (i = 0; i < NSERVERS; i++) {
- for (pts = &(afs_servers[i]), ts = *pts; ts;
- pts = &(ts->next), ts = *pts) {
- if (ts == srvp)
- break;
- }
- if (ts)
- break;
- }
- if (ts) {
- *pts = ts->next; /* Found it. Remove it */
- afs_osi_Free(ts, sizeof(struct server)); /* Free it */
- afs_totalServers--;
- }
- }
-}
-
-/* afs_RemoveSrvAddr()
- * This removes a SrvAddr structure from its server structure.
- * The srvAddr struct is not free'd because it connections may still
- * be open to it. It is up to the calling process to make sure it
- * remains connected to a server struct.
- * The afs_xserver and afs_xsrvAddr locks are assumed taken.
- * It is not removed from the afs_srvAddrs hash chain.
- */
-void afs_RemoveSrvAddr(struct srvAddr *sap) {
- struct srvAddr **psa, *sa;
- struct server *srv;
-
- if (!sap)
- return;
- srv = sap->server;
-
- /* Find the srvAddr in the server's list and remove it */
- for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
- if (sa == sap)
- break;
- } if (sa) {
- *psa = sa->next_sa;
- sa->next_sa = 0;
- sa->server = 0;
-
- /* Flush the server struct since it's IP address has changed */
- afs_FlushServer(srv);
- }
-}
-
-/* afs_GetServer()
- * Return an updated and properly initialized server structure
- * corresponding to the server ID, cell, and port specified.
- * If one does not exist, then one will be created.
- * aserver and aport must be in NET byte order.
- */
-struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
- afs_int32 acell, u_short aport,
- afs_int32 locktype, afsUUID * uuidp,
- afs_int32 addr_uniquifier) {
- struct server *oldts = 0, *ts, *newts, *orphts = 0;
- struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
- u_short fsport;
- afs_int32 iphash, k, srvcount = 0;
- unsigned int srvhash;
-
- AFS_STATCNT(afs_GetServer);
-
- ObtainSharedLock(&afs_xserver, 13);
-
- /* Check if the server struct exists and is up to date */
- if (!uuidp) {
- if (nservers != 1)
- panic("afs_GetServer: incorect count of servers");
- ObtainReadLock(&afs_xsrvAddr);
- ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
- ReleaseReadLock(&afs_xsrvAddr);
- if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
- /* Found a server struct that is not multihomed and has the
- * IP address associated with it. A correct match.
- */
- ReleaseSharedLock(&afs_xserver);
- return (ts);
- }
- } else {
- if (nservers <= 0)
- panic("afs_GetServer: incorrect count of servers");
- ts = afs_FindServer(0, aport, uuidp, locktype);
- if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
- /* Found a server struct that is multihomed and same
- * uniqufier (same IP addrs). The above if statement is the
- * same as in InstallUVolumeEntry().
- */
- ReleaseSharedLock(&afs_xserver);
- return ts;
- }
- if (ts)
- oldts = ts; /* Will reuse if same uuid */
- }
-
- UpgradeSToWLock(&afs_xserver, 36);
- ObtainWriteLock(&afs_xsrvAddr, 116);
-
- srvcount = afs_totalServers;
-
- /* Reuse/allocate a new server structure */
- if (oldts) {
- newts = oldts;
- } else {
- newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
- if (!newts)
- panic("malloc of server struct");
- afs_totalServers++;
- memset((char *)newts, 0, sizeof(struct server));
-
- /* Add the server struct to the afs_servers[] hash chain */
- srvhash =
- (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
- newts->next = afs_servers[srvhash];
- afs_servers[srvhash] = newts;
- }
-
- /* Initialize the server structure */
- if (uuidp) { /* Multihomed */
- newts->sr_uuid = *uuidp;
- newts->sr_addr_uniquifier = addr_uniquifier;
- newts->flags |= SRVR_MULTIHOMED;
- }
- if (acell)
- newts->cell = afs_GetCell(acell, 0);
-
- fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
-
- /* For each IP address we are registering */
- for (k = 0; k < nservers; k++) {
- iphash = SHash(aserverp[k]);
-
- /* Check if the srvAddr structure already exists. If so, remove
- * it from its server structure and add it to the new one.
- */
- for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
- if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
- break;
- }
- if (oldsa && (oldsa->server != newts)) {
- afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
- oldsa->next_sa = newts->addr; /* Add to the new server struct */
- newts->addr = oldsa;
- }
-
- /* Reuse/allocate a new srvAddr structure */
- if (oldsa) {
- newsa = oldsa;
- } else {
- newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
- if (!newsa)
- panic("malloc of srvAddr struct");
- afs_totalSrvAddrs++;
- memset((char *)newsa, 0, sizeof(struct srvAddr));
-
- /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
- newsa->next_bkt = afs_srvAddrs[iphash];
- afs_srvAddrs[iphash] = newsa;
-
- /* Hang off of the server structure */
- newsa->next_sa = newts->addr;
- newts->addr = newsa;
-
- /* Initialize the srvAddr Structure */
- newsa->sa_ip = aserverp[k];
- newsa->sa_portal = aport;
- }
-
- /* Update the srvAddr Structure */
- newsa->server = newts;
- if (newts->flags & SRVR_ISDOWN)
- newsa->sa_flags |= SRVADDR_ISDOWN;
- if (uuidp)
- newsa->sa_flags |= SRVADDR_MH;
- else
- newsa->sa_flags &= ~SRVADDR_MH;
-
- /* Compute preference values and resort */
- if (!newsa->sa_iprank) {
- if (aport == fsport) {
- afs_SetServerPrefs(newsa); /* new fileserver rank */
- } else {
- newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
- }
- }
- }
- afs_SortOneServer(newts); /* Sort by rank */
-
- /* If we reused the server struct, remove any of its srvAddr
- * structs that will no longer be associated with this server.
- */
- if (oldts) { /* reused the server struct */
- for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
- nextsa = orphsa->next_sa;
- for (k = 0; k < nservers; k++) {
- if (orphsa->sa_ip == aserverp[k])
- break; /* belongs */
- }
- if (k < nservers)
- continue; /* belongs */
-
- /* Have a srvAddr struct. Now get a server struct (if not already) */
- if (!orphts) {
- orphts =
- (struct server *)afs_osi_Alloc(sizeof(struct server));
- if (!orphts)
- panic("malloc of lo server struct");
- memset((char *)orphts, 0, sizeof(struct server));
- afs_totalServers++;
-
- /* Add the orphaned server to the afs_servers[] hash chain.
- * Its iphash does not matter since we never look up the server
- * in the afs_servers table by its ip address (only by uuid -
- * which this has none).
- */
- iphash = SHash(aserverp[k]);
- orphts->next = afs_servers[iphash];
- afs_servers[iphash] = orphts;
-
- if (acell)
- orphts->cell = afs_GetCell(acell, 0);
- }
-
- /* Hang the srvAddr struct off of the server structure. The server
- * may have multiple srvAddrs, but it won't be marked multihomed.
- */
- afs_RemoveSrvAddr(orphsa); /* remove */
- orphsa->next_sa = orphts->addr; /* hang off server struct */
- orphts->addr = orphsa;
- orphsa->server = orphts;
- orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
- orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
- }
- }
-
- srvcount = afs_totalServers - srvcount; /* # servers added and removed */
- if (srvcount) {
- struct afs_stats_SrvUpDownInfo *upDownP;
- /* With the introduction of this new record, we need to adjust the
- * proper individual & global server up/down info.
- */
- upDownP = GetUpDownStats(newts);
- upDownP->numTtlRecords += srvcount;
- afs_stats_cmperf.srvRecords += srvcount;
- if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
- afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
- }
-
- ReleaseWriteLock(&afs_xsrvAddr);
- ReleaseWriteLock(&afs_xserver);
- return (newts);
-} /* afs_GetServer */
-
-void afs_ActivateServer(struct srvAddr *sap) {
- osi_timeval_t currTime; /*Filled with current time */
- osi_timeval_t *currTimeP; /*Ptr to above */
- struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
- struct server *aserver = sap->server;
-
- if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
- /*
- * This server record has not yet been activated. Go for it,
- * recording its ``birth''.
- */
- aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
- currTimeP = &currTime;
- osi_GetuTime(currTimeP);
- aserver->activationTime = currTime.tv_sec;
- upDownP = GetUpDownStats(aserver);
- if (aserver->flags & SRVR_ISDOWN) {
- upDownP->numDownRecords++;
- } else {
- upDownP->numUpRecords++;
- upDownP->numRecordsNeverDown++;
- }
- }
-}
-
-
-void shutdown_server()
-{
- int i;
-
- for (i = 0; i < NSERVERS; i++) {
- struct server *ts, *next;
-
- ts = afs_servers[i];
- while(ts) {
- next = ts->next;
- afs_osi_Free(ts, sizeof(struct server));
- ts = next;
- }
- }
-
- for (i = 0; i < NSERVERS; i++) {
- struct srvAddr *sa, *next;
-
- sa = afs_srvAddrs[i];
- while(sa) {
- next = sa->next_bkt;
- afs_osi_Free(sa, sizeof(struct srvAddr));
- sa = next;
- }
- }
-}
+++ /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
- */
-
-/* statistics-gathering package */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_stat.c,v 1.9 2003/07/15 23:14:13 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs_stats.h"
-
-struct afs_CMStats afs_cmstats;
-struct afs_stats_CMPerf afs_stats_cmperf;
-struct afs_stats_CMFullPerf afs_stats_cmfullperf;
-afs_int32 afs_stats_XferSumBytes[AFS_STATS_NUM_FS_XFER_OPS];
-
-
-
-/*
- * afs_InitStats
- *
- * Description:
- * Initialize all of the CM statistics structures.
- *
- * Parameters:
- * None.
- *
- * Environment:
- * This routine should only be called once, at initialization time.
- */
-void
-afs_InitStats(void)
-{
- struct afs_stats_opTimingData *opTimeP; /*Ptr to curr timing struct */
- struct afs_stats_xferData *xferP; /*Ptr to curr xfer struct */
- int currIdx; /*Current index */
-
- /*
- * First step is to zero everything out.
- */
- memset((char *)(&afs_cmstats), 0, sizeof(struct afs_CMStats));
- memset((char *)(&afs_stats_cmperf), 0, sizeof(struct afs_stats_CMPerf));
- memset((char *)(&afs_stats_cmfullperf), 0,
- sizeof(struct afs_stats_CMFullPerf));
-
- /*
- * Some fields really should be non-zero at the start, so set 'em up.
- */
- afs_stats_cmperf.srvNumBuckets = NSERVERS;
-
- opTimeP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[0]);
- for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_RPC_OPS;
- currIdx++, opTimeP++)
- opTimeP->minTime.tv_sec = 999999;
-
- opTimeP = &(afs_stats_cmfullperf.rpc.cmRPCTimes[0]);
- for (currIdx = 0; currIdx < AFS_STATS_NUM_CM_RPC_OPS;
- currIdx++, opTimeP++)
- opTimeP->minTime.tv_sec = 999999;
-
- xferP = &(afs_stats_cmfullperf.rpc.fsXferTimes[0]);
- for (currIdx = 0; currIdx < AFS_STATS_NUM_FS_XFER_OPS; currIdx++, xferP++) {
- xferP->minTime.tv_sec = 999999;
- xferP->minBytes = 999999999;
- }
-}
-
-void
-afs_GetCMStat(char **ptr, unsigned *size)
-{
-#ifndef AFS_NOSTATS
- AFS_STATCNT(afs_GetCMStat);
- *ptr = (char *)&afs_cmstats;
- *size = sizeof(afs_cmstats);
-#endif /* AFS_NOSTATS */
-}
-
-void
-afs_AddToMean(struct afs_MeanStats *oldMean, afs_int32 newValue)
-{
- AFS_STATCNT(afs_AddToMean);
-}
+++ /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
- */
-
-/*
- * Statistics gathering stuff for the AFS cache manager.
- */
-/*
- * The remainder of this file contains the statistics gathering stuff.
- */
-
-#ifndef __OPENAFS_AFS_STATS_H__
-#define __OPENAFS_AFS_STATS_H__
-
-#include "afs/param.h"
-
-/* the following is to work around a VAX compiler limitation */
-#if defined(vax)
-#undef AFS_NOSTATS
-#define AFS_NOSTATS
-#endif /* VAX environment */
-
-#ifdef AFS_NOSTATS
-
-/*
- * The data collection routines are simply no-ops
- */
-#define AFS_STATCNT(arg)
-#define AFS_MEANCNT(arg, value)
-#define AFS_STATS(arg)
-#define XSTATS_DECLS
-#define XSTATS_START_TIME(arg)
-#define XSTATS_END_TIME
-
-#else /* AFS_NOSTATS */
-
-#define AFS_STATS(arg) arg
-#ifndef KERNEL
-/* NOTE: Ensure this is the same size in user and kernel mode. */
-typedef struct timeval osi_timeval_t;
-#endif /* !KERNEL */
-
-#define XSTATS_DECLS struct afs_stats_opTimingData *opP; \
- osi_timeval_t opStartTime, opStopTime, elapsedTime;
-
-#define XSTATS_START_TIME(arg) \
- opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[arg]); \
- osi_GetuTime(&opStartTime);
-
-#define XSTATS_START_CMTIME(arg) \
- opP = &(afs_stats_cmfullperf.rpc.cmRPCTimes[arg]); \
- osi_GetuTime(&opStartTime);
-
-#define XSTATS_END_TIME osi_GetuTime(&opStopTime); \
- (opP->numOps)++; \
- if (!code) { (opP->numSuccesses)++; \
- afs_stats_GetDiff(elapsedTime, opStartTime, opStopTime); \
- afs_stats_AddTo((opP->sumTime), elapsedTime); \
- afs_stats_SquareAddTo((opP->sqrTime), elapsedTime); \
- if (afs_stats_TimeLessThan(elapsedTime, (opP->minTime))) { \
- afs_stats_TimeAssign((opP->minTime), elapsedTime); \
- } if (afs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) { \
- afs_stats_TimeAssign((opP->maxTime), elapsedTime); } }
-
-#endif /* AFS_NOSTATS */
-
-
-
-struct afs_MeanStats {
- afs_int32 average;
- afs_int32 elements;
-};
-
-/*
- * struct afs_CMCallStats
- * This is the place where we keep records on each and every
- * function call.
- */
-struct afs_CMCallStats {
- afs_int32 C_afs_init; /* afs_aix_subr.c */
- afs_int32 C_gop_rdwr; /* afs_aix_subr.c */
- afs_int32 C_aix_gnode_rele; /* afs_aix_subr.c */
- afs_int32 C_gettimeofday; /* afs_aix_subr.c */
- afs_int32 C_m_cpytoc; /* afs_aix_subr.c */
- afs_int32 C_aix_vattr_null; /* afs_aix_subr.c */
- afs_int32 C_afs_gn_ftrunc; /* afs_aixops.c */
- afs_int32 C_afs_gn_rdwr; /* afs_aixops.c */
- afs_int32 C_afs_gn_ioctl; /* afs_aixops.c */
- afs_int32 C_afs_gn_lockctl; /* afs_aixops.c */
- afs_int32 C_afs_gn_readlink; /* afs_aixops.c */
- afs_int32 C_afs_gn_readdir; /* afs_aixops.c */
- afs_int32 C_afs_gn_select; /* afs_aixops.c */
- afs_int32 C_afs_gn_strategy; /* afs_aixops.c */
- afs_int32 C_afs_gn_symlink; /* afs_aixops.c */
- afs_int32 C_afs_gn_revoke; /* afs_aixops.c */
- afs_int32 C_afs_gn_link; /* afs_aixops.c */
- afs_int32 C_afs_gn_mkdir; /* afs_aixops.c */
- afs_int32 C_afs_gn_mknod; /* afs_aixops.c */
- afs_int32 C_afs_gn_remove; /* afs_aixops.c */
- afs_int32 C_afs_gn_rename; /* afs_aixops.c */
- afs_int32 C_afs_gn_rmdir; /* afs_aixops.c */
- afs_int32 C_afs_gn_fid; /* afs_aixops.c */
- afs_int32 C_afs_gn_lookup; /* afs_aixops.c */
- afs_int32 C_afs_gn_open; /* afs_aixops.c */
- afs_int32 C_afs_gn_create; /* afs_aixops.c */
- afs_int32 C_afs_gn_hold; /* afs_aixops.c */
- afs_int32 C_afs_gn_close; /* afs_aixops.c */
- afs_int32 C_afs_gn_map; /* afs_aixops.c */
- afs_int32 C_afs_gn_rele; /* afs_aixops.c */
- afs_int32 C_afs_gn_unmap; /* afs_aixops.c */
- afs_int32 C_afs_gn_access; /* afs_aixops.c */
- afs_int32 C_afs_gn_getattr; /* afs_aixops.c */
- afs_int32 C_afs_gn_setattr; /* afs_aixops.c */
- afs_int32 C_afs_gn_fclear; /* afs_aixops.c */
- afs_int32 C_afs_gn_fsync; /* afs_aixops.c */
- afs_int32 C_pHash; /* afs_buffer.c */
- afs_int32 C_DInit; /* afs_buffer.c */
- afs_int32 C_DRead; /* afs_buffer.c */
- afs_int32 C_FixupBucket; /* afs_buffer.c */
- afs_int32 C_afs_newslot; /* afs_buffer.c */
- afs_int32 C_DRelease; /* afs_buffer.c */
- afs_int32 C_DFlush; /* afs_buffer.c */
- afs_int32 C_DFlushEntry; /* afs_buffer.c */
- afs_int32 C_DVOffset; /* afs_buffer.c */
- afs_int32 C_DZap; /* afs_buffer.c */
- afs_int32 C_DNew; /* afs_buffer.c */
- afs_int32 C_shutdown_bufferpackage; /* afs_buffer.c */
- afs_int32 C_afs_CheckKnownBad; /* afs_cache.c */
- afs_int32 C_afs_RemoveVCB; /* afs_cache.c */
- afs_int32 C_afs_NewVCache; /* afs_cache.c */
- afs_int32 C_afs_FlushActiveVcaches; /* afs_cache.c */
- afs_int32 C_afs_VerifyVCache; /* afs_cache.c */
- afs_int32 C_afs_WriteVCache; /* afs_cache.c */
- afs_int32 C_afs_GetVCache; /* afs_cache.c */
- afs_int32 C_afs_StuffVcache; /* afs_cache.c */
- afs_int32 C_afs_FindVCache; /* afs_cache.c */
- afs_int32 C_afs_PutDCache; /* afs_cache.c */
- afs_int32 C_afs_PutVCache; /* afs_cache.c */
- afs_int32 C_CacheStoreProc; /* afs_cache.c */
- afs_int32 C_afs_FindDCache; /* afs_cache.c */
- afs_int32 C_afs_TryToSmush; /* afs_cache.c */
- afs_int32 C_afs_AdjustSize; /* afs_cache.c */
- afs_int32 C_afs_CheckSize; /* afs_cache.c */
- afs_int32 C_afs_StoreWarn; /* afs_cache.c */
- afs_int32 C_CacheFetchProc; /* afs_cache.c */
- afs_int32 C_UFS_CacheStoreProc; /* afs_cache.c */
- afs_int32 C_UFS_CacheFetchProc; /* afs_cache.c */
- afs_int32 C_afs_GetDCache; /* afs_cache.c */
- afs_int32 C_afs_SimpleVStat; /* afs_cache.c */
- afs_int32 C_afs_ProcessFS; /* afs_cache.c */
- afs_int32 C_afs_InitCacheInfo; /* afs_cache.c */
- afs_int32 C_afs_InitVolumeInfo; /* afs_cache.c */
- afs_int32 C_afs_InitCacheFile; /* afs_cache.c */
- afs_int32 C_afs_CacheInit; /* afs_cache.c */
- afs_int32 C_afs_GetDSlot; /* afs_cache.c */
- afs_int32 C_afs_WriteThroughDSlots; /* afs_cache.c */
- afs_int32 C_afs_MemGetDSlot; /* afs_cache.c */
- afs_int32 C_afs_UFSGetDSlot; /* afs_cache.c */
- afs_int32 C_afs_StoreDCache; /* afs_cache.c */
- afs_int32 C_afs_StoreMini; /* afs_cache.c */
- afs_int32 C_shutdown_cache; /* afs_cache.c */
- afs_int32 C_afs_StoreAllSegments; /* afs_cache.c */
- afs_int32 C_afs_InvalidateAllSegments; /* afs_cache.c */
- afs_int32 C_afs_TruncateAllSegments; /* afs_cache.c */
- afs_int32 C_afs_CheckVolSync; /* afs_cache.c */
- afs_int32 C_afs_wakeup; /* afs_cache.c */
- afs_int32 C_afs_CFileOpen; /* afs_cache.c */
- afs_int32 C_afs_CFileTruncate; /* afs_cache.c */
- afs_int32 C_afs_GetDownD; /* afs_cache.c */
- afs_int32 C_afs_WriteDCache; /* afs_cache.c */
- afs_int32 C_afs_FlushDCache; /* afs_cache.c */
- afs_int32 C_afs_GetDownDSlot; /* afs_cache.c */
- afs_int32 C_afs_FlushVCache; /* afs_cache.c */
- afs_int32 C_afs_GetDownV; /* afs_cache.c */
- afs_int32 C_afs_QueueVCB; /* afs_cache.c */
- afs_int32 C_afs_call; /* afs_call.c */
- afs_int32 C_afs_syscall_call; /* afs_call.c */
- afs_int32 C_syscall; /* afs_call.c */
- afs_int32 C_lpioctl; /* afs_call.c */
- afs_int32 C_lsetpag; /* afs_call.c */
- afs_int32 C_afs_syscall; /* afs_call.c */
- afs_int32 C_afs_CheckInit; /* afs_call.c */
- afs_int32 C_afs_shutdown; /* afs_call.c */
- afs_int32 C_shutdown_BKG; /* afs_call.c */
- afs_int32 C_shutdown_afstest; /* afs_call.c */
- afs_int32 C_SRXAFSCB_GetCE; /* afs_callback.c */
- afs_int32 C_ClearCallBack; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetLock; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_CallBack; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_InitCallBackState; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_Probe; /* afs_callback.c */
- afs_int32 C_afs_RXCallBackServer; /* afs_callback.c */
- afs_int32 C_shutdown_CB; /* afs_callback.c */
- afs_int32 C_afs_Chunk; /* afs_chunk.c */
- afs_int32 C_afs_ChunkBase; /* afs_chunk.c */
- afs_int32 C_afs_ChunkOffset; /* afs_chunk.c */
- afs_int32 C_afs_ChunkSize; /* afs_chunk.c */
- afs_int32 C_afs_ChunkToBase; /* afs_chunk.c */
- afs_int32 C_afs_ChunkToSize; /* afs_chunk.c */
- afs_int32 C_afs_SetChunkSize; /* afs_chunk.c */
-
- afs_int32 C_afs_config; /* afs_config.c */
- afs_int32 C_mem_freebytes; /* afs_config.c */
- afs_int32 C_mem_getbytes; /* afs_config.c */
- afs_int32 C_fpalloc; /* afs_config.c */
- afs_int32 C_kluge_init; /* afs_config.c */
- afs_int32 C_ufdalloc; /* afs_config.c */
- afs_int32 C_ufdfree; /* afs_config.c */
- afs_int32 C_commit; /* afs_config.c */
- afs_int32 C_dev_ialloc; /* afs_config.c */
- afs_int32 C_ffree; /* afs_config.c */
- afs_int32 C_iget; /* afs_config.c */
- afs_int32 C_iptovp; /* afs_config.c */
- afs_int32 C_ilock; /* afs_config.c */
- afs_int32 C_irele; /* afs_config.c */
- afs_int32 C_iput; /* afs_config.c */
-
- afs_int32 C_afs_Daemon; /* afs_daemons.c */
- afs_int32 C_afs_CheckRootVolume; /* afs_daemons.c */
- afs_int32 C_BPath; /* afs_daemons.c */
- afs_int32 C_BPrefetch; /* afs_daemons.c */
- afs_int32 C_BStore; /* afs_daemons.c */
- afs_int32 C_afs_BBusy; /* afs_daemons.c */
- afs_int32 C_afs_BQueue; /* afs_daemons.c */
- afs_int32 C_afs_BRelease; /* afs_daemons.c */
- afs_int32 C_afs_BackgroundDaemon; /* afs_daemons.c */
- afs_int32 C_shutdown_daemons; /* afs_daemons.c */
- afs_int32 C_exporter_add; /* afs_exporter.c */
- afs_int32 C_exporter_find; /* afs_exporter.c */
- afs_int32 C_afs_gfs_kalloc; /* afs_gfs_subr.c */
- afs_int32 C_IsAfsVnode; /* afs_gfs_subr.c */
- afs_int32 C_SetAfsVnode; /* afs_gfs_subr.c */
- afs_int32 C_afs_gfs_kfree; /* afs_gfs_subr.c */
- afs_int32 C_gop_lookupname; /* afs_gfs_subr.c */
- afs_int32 C_gfsvop_getattr; /* afs_gfs_subr.c */
- afs_int32 C_gfsvop_rdwr; /* afs_gfs_subr.c */
- afs_int32 C_afs_uniqtime; /* afs_gfs_subr.c */
- afs_int32 C_gfs_vattr_null; /* afs_gfs_subr.c */
- afs_int32 C_afs_lock; /* afs_gfsops.c */
- afs_int32 C_afs_unlock; /* afs_gfsops.c */
- afs_int32 C_afs_update; /* afs_gfsops.c */
- afs_int32 C_afs_gclose; /* afs_gfsops.c */
- afs_int32 C_afs_gopen; /* afs_gfsops.c */
- afs_int32 C_afs_greadlink; /* afs_gfsops.c */
- afs_int32 C_afs_select; /* afs_gfsops.c */
- afs_int32 C_afs_gbmap; /* afs_gfsops.c */
- afs_int32 C_afs_getfsdata; /* afs_gfsops.c */
- afs_int32 C_afs_gsymlink; /* afs_gfsops.c */
- afs_int32 C_afs_namei; /* afs_gfsops.c */
- afs_int32 C_printgnode; /* afs_gfsops.c */
- afs_int32 C_HaveGFSLock; /* afs_gfsops.c */
- afs_int32 C_afs_gmount; /* afs_gfsops.c */
- afs_int32 C_AddGFSLock; /* afs_gfsops.c */
- afs_int32 C_RemoveGFSLock; /* afs_gfsops.c */
- afs_int32 C_afs_grlock; /* afs_gfsops.c */
- afs_int32 C_afs_gumount; /* afs_gfsops.c */
- afs_int32 C_afs_gget; /* afs_gfsops.c */
- afs_int32 C_afs_glink; /* afs_gfsops.c */
- afs_int32 C_afs_gmkdir; /* afs_gfsops.c */
- afs_int32 C_afs_sbupdate; /* afs_gfsops.c */
- afs_int32 C_afs_unlink; /* afs_gfsops.c */
- afs_int32 C_afs_grmdir; /* afs_gfsops.c */
- afs_int32 C_afs_makenode; /* afs_gfsops.c */
- afs_int32 C_afs_grename; /* afs_gfsops.c */
- afs_int32 C_afs_rele; /* afs_gfsops.c */
- afs_int32 C_afs_syncgp; /* afs_gfsops.c */
- afs_int32 C_afs_getval; /* afs_gfsops.c */
- afs_int32 C_afs_gfshack; /* afs_gfsops.c */
- afs_int32 C_afs_trunc; /* afs_gfsops.c */
- afs_int32 C_afs_rwgp; /* afs_gfsops.c */
- afs_int32 C_afs_stat; /* afs_gfsops.c */
- afs_int32 C_afsc_link; /* afs_hp_subr.c */
- afs_int32 C_hpsobind; /* afs_hp_subr.c */
- afs_int32 C_hpsoclose; /* afs_hp_subr.c */
- afs_int32 C_hpsocreate; /* afs_hp_subr.c */
- afs_int32 C_hpsoreserve; /* afs_hp_subr.c */
- afs_int32 C_afs_vfs_mount; /* afs_hp_subr.c */
- afs_int32 C_devtovfs; /* afs_istuff.c */
- afs_int32 C_igetinode; /* afs_istuff.c */
- afs_int32 C_afs_syscall_iopen; /* afs_istuff.c */
- afs_int32 C_iopen; /* afs_istuff.c */
- afs_int32 C_afs_syscall_iincdec; /* afs_istuff.c */
- afs_int32 C_afs_syscall_ireadwrite; /* afs_istuff.c */
- afs_int32 C_iincdec; /* afs_istuff.c */
- afs_int32 C_ireadwrite; /* afs_istuff.c */
- afs_int32 C_oiread; /* afs_istuff.c */
- afs_int32 C_AHash; /* afs_istuff.c */
- afs_int32 C_QTOA; /* afs_istuff.c */
- afs_int32 C_afs_FindPartByDev; /* afs_istuff.c */
- afs_int32 C_aux_init; /* afs_istuff.c */
- afs_int32 C_afs_GetNewPart; /* afs_istuff.c */
- afs_int32 C_afs_InitAuxVolFile; /* afs_istuff.c */
- afs_int32 C_afs_CreateAuxEntry; /* afs_istuff.c */
- afs_int32 C_afs_GetAuxSlot; /* afs_istuff.c */
- afs_int32 C_afs_GetDownAux; /* afs_istuff.c */
- afs_int32 C_afs_FlushAuxCache; /* afs_istuff.c */
- afs_int32 C_afs_GetAuxInode; /* afs_istuff.c */
- afs_int32 C_afs_PutAuxInode; /* afs_istuff.c */
- afs_int32 C_afs_ReadAuxInode; /* afs_istuff.c */
- afs_int32 C_afs_WriteAuxInode; /* afs_istuff.c */
- afs_int32 C_afs_auxcall; /* afs_istuff.c */
- afs_int32 C_tmpdbg_auxtbl; /* afs_istuff.c */
- afs_int32 C_tmpdbg_parttbl; /* afs_istuff.c */
- afs_int32 C_idec; /* afs_istuff.c */
- afs_int32 C_iinc; /* afs_istuff.c */
- afs_int32 C_iread; /* afs_istuff.c */
- afs_int32 C_iwrite; /* afs_istuff.c */
- afs_int32 C_getinode; /* afs_istuff.c */
- afs_int32 C_trygetfs; /* afs_istuff.c */
- afs_int32 C_iforget; /* afs_istuff.c */
- afs_int32 C_afs_syscall_icreate; /* afs_istuff.c */
- afs_int32 C_icreate; /* afs_istuff.c */
- afs_int32 C_Lock_Init; /* afs_lock.c */
- afs_int32 C_Lock_Obtain; /* afs_lock.c */
- afs_int32 C_Lock_ReleaseR; /* afs_lock.c */
- afs_int32 C_Lock_ReleaseW; /* afs_lock.c */
- afs_int32 C_afs_BozonLock; /* afs_lock.c */
- afs_int32 C_afs_BozonUnlock; /* afs_lock.c */
- afs_int32 C_osi_SleepR; /* afs_lock.c */
- afs_int32 C_osi_SleepS; /* afs_lock.c */
- afs_int32 C_osi_SleepW; /* afs_lock.c */
- afs_int32 C_osi_Sleep; /* afs_lock */
- afs_int32 C_afs_BozonInit; /* afs_lock.c */
- afs_int32 C_afs_CheckBozonLock; /* afs_lock.c */
- afs_int32 C_afs_CheckBozonLockBlocking; /* afs_lock.c */
- afs_int32 C_xxxinit; /* afs_main.c */
- afs_int32 C_KernelEntry; /* afs_main.c */
- afs_int32 C_afs_InitMemCache; /* afs_memcache.c */
- afs_int32 C_afs_LookupMCE; /* afs_memcache.c */
- afs_int32 C_afs_MemReadBlk; /* afs_memcache.c */
- afs_int32 C_afs_MemReadUIO; /* afs_memcache.c */
- afs_int32 C_afs_MemWriteBlk; /* afs_memcache.c */
- afs_int32 C_afs_MemCacheStoreProc; /* afs_memcache.c */
- afs_int32 C_afs_MemCacheTruncate; /* afs_memcache.c */
- afs_int32 C_afs_MemWriteUIO; /* afs_memcache.c */
- afs_int32 C_afs_MemCacheFetchProc; /* afs_memcache.c */
- afs_int32 C_afs_vnode_pager_create; /* afs_next_aux.c */
- afs_int32 C_next_KernelEntry; /* afs_next_subr.c */
- afs_int32 C_afs_GetNfsClientPag; /* afs_nfsclnt.c */
- afs_int32 C_afs_FindNfsClientPag; /* afs_nfsclnt.c */
- afs_int32 C_afs_PutNfsClientPag; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_reqhandler; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_GC; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_hold; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_stats; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_sysname; /* afs_nfsclnt.c */
- afs_int32 C_afs_nfsclient_shutdown; /* afs_nfsclnt.c */
- afs_int32 C_afs_rfs_readdir_fixup; /* afs_nfssrv.c */
- afs_int32 C_afs_rfs_dispatch; /* afs_nfssrv.c */
- afs_int32 C_afs_xnfs_svc; /* afs_nfssrv.c */
- afs_int32 C_afs_xdr_putrddirres; /* afs_nfssrv.c */
- afs_int32 C_afs_rfs_readdir; /* afs_nfssrv.c */
- afs_int32 C_afs_rfs_rddirfree; /* afs_nfssrv.c */
- afs_int32 C_rfs_dupcreate; /* afs_nfssrv.c */
- afs_int32 C_rfs_dupsetattr; /* afs_nfssrv.c */
- afs_int32 C_Nfs2AfsCall; /* afs_nfssrv.c */
- afs_int32 C_afs_sun_xuntext; /* afs_osi.c */
- afs_int32 C_osi_Active; /* afs_osi.c */
- afs_int32 C_osi_FlushPages; /* afs_osi.c */
- afs_int32 C_osi_FlushText; /* afs_osi.c */
- afs_int32 C_osi_CallProc; /* afs_osi.c */
- afs_int32 C_osi_CancelProc; /* afs_osi.c */
- afs_int32 C_osi_Invisible; /* afs_osi.c */
- afs_int32 C_osi_Time; /* afs_osi.c */
- afs_int32 C_osi_Alloc; /* afs_osi.c */
- afs_int32 C_osi_SetTime; /* afs_osi.c */
- afs_int32 C_osi_Dump; /* afs_osi.c */
- afs_int32 C_osi_Free; /* afs_osi.c */
- afs_int32 C_shutdown_osi; /* afs_osi.c */
- afs_int32 C_osi_UFSOpen; /* afs_osifile.c */
- afs_int32 C_osi_Close; /* afs_osifile.c */
- afs_int32 C_osi_Stat; /* afs_osifile.c */
- afs_int32 C_osi_Truncate; /* afs_osifile.c */
- afs_int32 C_osi_Read; /* afs_osifile.c */
- afs_int32 C_osi_Write; /* afs_osifile.c */
- afs_int32 C_osi_MapStrategy; /* afs_osifile.c */
- afs_int32 C_shutdown_osifile; /* afs_osifile.c */
- afs_int32 C_osi_FreeLargeSpace; /* afs_osinet.c */
- afs_int32 C_osi_FreeSmallSpace; /* afs_osinet.c */
- afs_int32 C_pkt_iodone; /* afs_osinet.c */
- afs_int32 C_shutdown_osinet; /* afs_osinet.c */
- afs_int32 C_afs_cs; /* afs_osinet.c */
- afs_int32 C_osi_AllocLargeSpace; /* afs_osinet.c */
- afs_int32 C_osi_AllocSmallSpace; /* afs_osinet.c */
- afs_int32 C_osi_CloseToTheEdge; /* afs_osinet.c */
- afs_int32 C_osi_xgreedy; /* afs_osinet.c */
- afs_int32 C_osi_FreeSocket; /* afs_osinet.c */
- afs_int32 C_osi_NewSocket; /* afs_osinet.c */
- afs_int32 C_trysblock; /* afs_osinet.c */
- afs_int32 C_osi_NetSend; /* afs_osinet.c */
- afs_int32 C_WaitHack; /* afs_osinet.c */
- afs_int32 C_osi_CancelWait; /* afs_osinet.c */
- afs_int32 C_osi_InitWaitHandle; /* afs_osinet.c */
- afs_int32 C_osi_Wakeup; /* afs_osinet.c */
- afs_int32 C_osi_Wait; /* afs_osinet.c */
- afs_int32 C_dirp_Read; /* afs_physio.c */
- afs_int32 C_dirp_SetCacheDev; /* afs_physio.c */
- afs_int32 C_Die; /* afs_physio.c */
- afs_int32 C_dirp_Cpy; /* afs_physio.c */
- afs_int32 C_dirp_Eq; /* afs_physio.c */
- afs_int32 C_dirp_Write; /* afs_physio.c */
- afs_int32 C_dirp_Zap; /* afs_physio.c */
- afs_int32 C_PSetVolumeStatus; /* afs_pioctl.c */
- afs_int32 C_PFlush; /* afs_pioctl.c */
- afs_int32 C_PNewStatMount; /* afs_pioctl.c */
- afs_int32 C_PGetTokens; /* afs_pioctl.c */
- afs_int32 C_PUnlog; /* afs_pioctl.c */
- afs_int32 C_PCheckServers; /* afs_pioctl.c */
- afs_int32 C_PMariner; /* afs_pioctl.c */
- afs_int32 C_PCheckAuth; /* afs_pioctl.c */
- afs_int32 C_PCheckVolNames; /* afs_pioctl.c */
- afs_int32 C_PFindVolume; /* afs_pioctl.c */
- afs_int32 C_Prefetch; /* afs_pioctl.c */
- afs_int32 C_PGetCacheSize; /* afs_pioctl.c */
- afs_int32 C_PRemoveCallBack; /* afs_pioctl.c */
- afs_int32 C_PSetCacheSize; /* afs_pioctl.c */
- afs_int32 C_PViceAccess; /* afs_pioctl.c */
- afs_int32 C_PListCells; /* afs_pioctl.c */
- afs_int32 C_PNewCell; /* afs_pioctl.c */
- afs_int32 C_PRemoveMount; /* afs_pioctl.c */
- afs_int32 C_HandleIoctl; /* afs_pioctl.c */
- afs_int32 C__AFSIOCTL; /* afs_pioctl.c */
- afs_int32 C__VALIDAFSIOCTL; /* afs_pioctl.c */
- afs_int32 C_PGetCellStatus; /* afs_pioctl.c */
- afs_int32 C_PSetCellStatus; /* afs_pioctl.c */
- afs_int32 C_PVenusLogging; /* afs_pioctl.c */
- afs_int32 C_PFlushVolumeData; /* afs_pioctl.c */
- afs_int32 C_PSetSysName; /* afs_pioctl.c */
- afs_int32 C_PExportAfs; /* afs_pioctl.c */
- afs_int32 C_HandleClientContext; /* afs_pioctl.c */
- afs_int32 C_afs_ioctl; /* afs_pioctl.c */
- afs_int32 C_afs_xioctl; /* afs_pioctl.c */
- afs_int32 C_afs_pioctl; /* afs_pioctl.c */
- afs_int32 C_afs_syscall_pioctl; /* afs_pioctl.c */
- afs_int32 C_HandlePioctl; /* afs_pioctl.c */
- afs_int32 C_PGetAcl; /* afs_pioctl.c */
- afs_int32 C_PGetFID; /* afs_pioctl.c */
- afs_int32 C_PSetAcl; /* afs_pioctl.c */
- afs_int32 C_PBogus; /* afs_pioctl.c */
- afs_int32 C_PGetFileCell; /* afs_pioctl.c */
- afs_int32 C_PGetWSCell; /* afs_pioctl.c */
- afs_int32 C_PNoop; /* afs_pioctl.c */
- afs_int32 C_PGetUserCell; /* afs_pioctl.c */
- afs_int32 C_PSetTokens; /* afs_pioctl.c */
- afs_int32 C_PGetVolumeStatus; /* afs_pioctl.c */
- afs_int32 C_afs_ResetAccessCache; /* afs_resource.c */
- afs_int32 C_afs_FindUser; /* afs_resource.c */
- afs_int32 C_afs_ResetUserConns; /* afs_resource.c */
- afs_int32 C_afs_ResourceInit; /* afs_resource.c */
- afs_int32 C_afs_GetCell; /* afs_resource.c */
- afs_int32 C_afs_GetCellByIndex; /* afs_resource.c */
- afs_int32 C_afs_GetCellByName; /* afs_resource.c */
- afs_int32 C_afs_GetRealCellByIndex; /* afs_resource.c */
- afs_int32 C_afs_NewCell; /* afs_resource.c */
- afs_int32 C_afs_GetUser; /* afs_resource.c */
- afs_int32 C_afs_PutUser; /* afs_resource.c */
- afs_int32 C_afs_SetPrimary; /* afs_resource.c */
- afs_int32 C_CheckVLDB; /* afs_resource.c */
- afs_int32 C_afs_GetVolume; /* afs_resource.c */
- afs_int32 C_afs_GetVolumeByName; /* afs_resource.c */
- afs_int32 C_InstallVolumeEntry; /* afs_resource.c */
- afs_int32 C_InstallVolumeInfo; /* afs_resource.c */
- afs_int32 C_afs_FindServer; /* afs_resource.c */
- afs_int32 C_afs_PutVolume; /* afs_resource.c */
- afs_int32 C_afs_random; /* afs_resource.c */
- afs_int32 C_ranstage; /* afs_resource.c */
- afs_int32 C_RemoveUserConns; /* afs_resource.c */
- afs_int32 C_afs_MarinerLog; /* afs_resource.c */
- afs_int32 C_afs_vtoi; /* afs_resource.c */
- afs_int32 C_afs_GetServer; /* afs_resource.c */
- afs_int32 C_afs_SortServers; /* afs_resource.c */
- afs_int32 C_afs_Conn; /* afs_resource.c */
- afs_int32 C_afs_ConnByHost; /* afs_resource.c */
- afs_int32 C_afs_ConnByMHosts; /* afs_resource.c */
- afs_int32 C_afs_Analyze; /* afs_resource.c */
- afs_int32 C_afs_PutConn; /* afs_resource.c */
- afs_int32 C_afs_ResetVolumeInfo; /* afs_resource.c */
- afs_int32 C_StartLogFile; /* afs_resource.c */
- afs_int32 C_afs_SetLogFile; /* afs_resource.c */
- afs_int32 C_EndLogFile; /* afs_resource.c */
- afs_int32 C_afs_dp; /* afs_resource.c */
- afs_int32 C_fprf; /* afs_resource.c */
- afs_int32 C_fprint; /* afs_resource.c */
- afs_int32 C_fprintn; /* afs_resource.c */
- afs_int32 C_afs_CheckLocks; /* afs_resource.c */
- afs_int32 C_puttofile; /* afs_resource.c */
- afs_int32 C_shutdown_AFS; /* afs_resource.c */
- afs_int32 C_afs_CheckCacheResets; /* afs_resource.c */
- afs_int32 C_afs_GCUserData; /* afs_resource.c */
- afs_int32 C_VSleep; /* afs_resource.c */
- afs_int32 C_afs_CheckCode; /* afs_resource.c */
- afs_int32 C_afs_CopyError; /* afs_resource.c */
- afs_int32 C_afs_FinalizeReq; /* afs_resource.c */
- afs_int32 C_afs_cv2string; /* afs_resource.c */
- afs_int32 C_afs_FindVolCache; /* afs_resource.c */
- afs_int32 C_afs_GetVolCache; /* afs_resource.c */
- afs_int32 C_afs_GetVolSlot; /* afs_resource.c */
- afs_int32 C_afs_WriteVolCache; /* afs_resource.c */
- afs_int32 C_afs_UFSGetVolSlot; /* afs_resource.c */
- afs_int32 C_afs_CheckVolumeNames; /* afs_resource.c */
- afs_int32 C_afs_MemGetVolSlot; /* afs_resource.c */
- afs_int32 C_print_internet_address; /* afs_resource.c */
- afs_int32 C_CheckVLServer; /* afs_resource.c */
- afs_int32 C_HaveCallBacksFrom; /* afs_resource.c */
- afs_int32 C_ServerDown; /* afs_resource.c */
- afs_int32 C_afs_CheckServers; /* afs_resource.c */
- afs_int32 C_afs_AddToMean; /* afs_stat.c */
- afs_int32 C_afs_GetCMStat; /* afs_stat.c */
- afs_int32 C_afs_getpage; /* afs_sun_subr.c */
- afs_int32 C_afs_putpage; /* afs_sun_subr.c */
- afs_int32 C_afs_nfsrdwr; /* afs_sun_subr.c */
- afs_int32 C_afs_map; /* afs_sun_subr.c */
- afs_int32 C_afs_cmp; /* afs_sun_subr.c */
- afs_int32 C_afs_cntl; /* afs_sun_subr.c */
- afs_int32 C_afs_dump; /* afs_sun_subr.c */
- afs_int32 C_afs_realvp; /* afs_sun_subr.c */
- afs_int32 C_afs_PageLeft; /* afs_sun_subr.c */
- afs_int32 C_afsinit; /* afs_vfsops.c */
- afs_int32 C_afs_mount; /* afs_vfsops.c */
- afs_int32 C_afs_unmount; /* afs_vfsops.c */
- afs_int32 C_afs_root; /* afs_vfsops.c */
- afs_int32 C_afs_statfs; /* afs_vfsops.c */
- afs_int32 C_afs_sync; /* afs_vfsops.c */
- afs_int32 C_afs_vget; /* afs_vfsops.c */
- afs_int32 C_afs_mountroot; /* afs_vfsops.c */
- afs_int32 C_afs_swapvp; /* afs_vfsops.c */
- afs_int32 C_afs_AddMarinerName; /* afs_vnodeops.c */
- afs_int32 C_afs_setpag; /* afs_vnodeops.c */
- afs_int32 C_genpag; /* afs_vnodeops.c */
- afs_int32 C_getpag; /* afs_vnodeops.c */
- afs_int32 C_afs_GetMariner; /* afs_vnodeops.c */
- afs_int32 C_afs_badop; /* afs_vnodeops.c */
- afs_int32 C_afs_index; /* afs_vnodeops.c */
- afs_int32 C_afs_noop; /* afs_vnodeops.c */
- afs_int32 C_afs_open; /* afs_vnodeops.c */
- afs_int32 C_afs_closex; /* afs_vnodeops.c */
- afs_int32 C_afs_close; /* afs_vnodeops.c */
- afs_int32 C_afs_MemWrite; /* afs_vnodeops.c */
- afs_int32 C_afs_write; /* afs_vnodeops.c */
- afs_int32 C_afs_UFSWrite; /* afs_vnodeops.c */
- afs_int32 C_afs_rdwr; /* afs_vnodeops.c */
- afs_int32 C_afs_MemRead; /* afs_vnodeops.c */
- afs_int32 C_afs_read; /* afs_vnodeops.c */
- afs_int32 C_FIXUPSTUPIDINODE; /* afs_vnodeops.c */
- afs_int32 C_afs_UFSRead; /* afs_vnodeops.c */
- afs_int32 C_afs_CopyOutAttrs; /* afs_vnodeops.c */
- afs_int32 C_afs_getattr; /* afs_vnodeops.c */
- afs_int32 C_afs_VAttrToAS; /* afs_vnodeops.c */
- afs_int32 C_afs_setattr; /* afs_vnodeops.c */
- afs_int32 C_EvalMountPoint; /* afs_vnodeops.c */
- afs_int32 C_afs_access; /* afs_vnodeops.c */
- afs_int32 C_ENameOK; /* afs_vnodeops.c */
- afs_int32 C_HandleAtName; /* afs_vnodeops.c */
- afs_int32 C_getsysname; /* afs_vnodeops.c */
- afs_int32 C_strcat; /* afs_vnodeops.c */
- afs_int32 C_afs_lookup; /* afs_vnodeops.c */
- afs_int32 C_afs_create; /* afs_vnodeops.c */
- afs_int32 C_afs_LocalHero; /* afs_vnodeops.c */
- afs_int32 C_FetchWholeEnchilada; /* afs_vnodeops.c */
- afs_int32 C_afs_remove; /* afs_vnodeops.c */
- afs_int32 C_afs_link; /* afs_vnodeops.c */
- afs_int32 C_afs_rename; /* afs_vnodeops.c */
- afs_int32 C_afs_InitReq; /* afs_vnodeops.c */
- afs_int32 C_afs_mkdir; /* afs_vnodeops.c */
- afs_int32 C_BlobScan; /* afs_vnodeops.c */
- afs_int32 C_afs_rmdir; /* afs_vnodeops.c */
- afs_int32 C_RecLen; /* afs_vnodeops.c */
- afs_int32 C_RoundToInt; /* afs_vnodeops.c */
- afs_int32 C_afs_readdir_with_offlist; /* afs_vnodeops.c */
- afs_int32 C_DIRSIZ_LEN; /* afs_vnodeops.c */
- afs_int32 C_afs_readdir_move; /* afs_vnodeops.c */
- afs_int32 C_afs_readdir_iter; /* afs_vnodeops.c */
- afs_int32 C_HandleFlock; /* afs_vnodeops.c */
- afs_int32 C_afs_readdir; /* afs_vnodeops.c */
- afs_int32 C_afs_symlink; /* afs_vnodeops.c */
- afs_int32 C_afs_HandleLink; /* afs_vnodeops.c */
- afs_int32 C_afs_MemHandleLink; /* afs_vnodeops.c */
- afs_int32 C_afs_UFSHandleLink; /* afs_vnodeops.c */
- afs_int32 C_afs_readlink; /* afs_vnodeops.c */
- afs_int32 C_afs_fsync; /* afs_vnodeops.c */
- afs_int32 C_afs_inactive; /* afs_vnodeops.c */
- afs_int32 C_afs_ustrategy; /* afs_vnodeops.c */
- afs_int32 C_afs_bread; /* afs_vnodeops.c */
- afs_int32 C_afs_brelse; /* afs_vnodeops.c */
- afs_int32 C_afs_bmap; /* afs_vnodeops.c */
- afs_int32 C_afs_fid; /* afs_vnodeops.c */
- afs_int32 C_afs_strategy; /* afs_vnodeops.c */
- afs_int32 C_afs_FakeClose; /* afs_vnodeops.c */
- afs_int32 C_afs_FakeOpen; /* afs_vnodeops.c */
- afs_int32 C_afs_StoreOnLastReference; /* afs_vnodeops.c */
- afs_int32 C_afs_GetAccessBits; /* afs_vnodeops.c */
- afs_int32 C_afs_AccessOK; /* afs_vnodeops.c */
- afs_int32 C_shutdown_vnodeops; /* afs_vnodeops.c */
- afs_int32 C_afsio_copy; /* afs_vnodeops.c */
- afs_int32 C_afsio_trim; /* afs_vnodeops.c */
- afs_int32 C_afs_page_read; /* afs_vnodeops.c */
- afs_int32 C_afs_page_write; /* afs_vnodeops.c */
- afs_int32 C_afsio_skip; /* afs_vnodeops.c */
- afs_int32 C_afs_read1dir; /* afs_vnodeops.c */
- afs_int32 C_afs_get_groups_from_pag; /* afs_vnodeops.c */
- afs_int32 C_afs_get_pag_from_groups; /* afs_vnodeops.c */
- afs_int32 C_PagInCred; /* afs_vnodeops.c */
- afs_int32 C_afs_getgroups; /* afs_vnodeops.c */
- afs_int32 C_setpag; /* afs_vnodeops.c */
- afs_int32 C_afs_setgroups; /* afs_vnodeops.c */
- afs_int32 C_afs_page_in; /* afs_vnodeops.c */
- afs_int32 C_afs_page_out; /* afs_vnodeops.c */
- afs_int32 C_AddPag; /* afs_vnodeops.c */
- afs_int32 C_afs_AdvanceFD; /* afs_vnodeops.c */
- afs_int32 C_afs_lockf; /* afs_vnodeops.c */
- afs_int32 C_afs_xsetgroups; /* afs_vnodeops.c */
- afs_int32 C_afs_nlinks; /* afs_vnodeops.c */
- afs_int32 C_DoLockWarning; /* afs_vnodeops.c */
- afs_int32 C_afs_lockctl; /* afs_vnodeops.c */
- afs_int32 C_afs_xflock; /* afs_vnodeops.c */
- afs_int32 C_PSetSPrefs; /* afs_pioctl.c */
- afs_int32 C_PGetSPrefs; /* afs_pioctl.c */
- afs_int32 C_afs_warn; /* afs_resource.c */
- afs_int32 C_afs_warnuser; /* afs_resource.c */
- afs_int32 C_afs_pagein; /* afs_hp_subr.c */
- afs_int32 C_afs_pageout; /* afs_hp_subr.c */
- afs_int32 C_afs_hp_strategy; /* afs_hp_subr.c */
- afs_int32 C_PGetCPrefs; /* afs_pioctl.c */
- afs_int32 C_PSetCPrefs; /* afs_pioctl.c */
- afs_int32 C_SRXAFSCB_WhoAreYou; /* afs_callback.c */
- afs_int32 C_afs_DiscardDCache; /* afs_dcache.c */
- afs_int32 C_afs_FreeDiscardedDCache; /* afs_dcache.c */
- afs_int32 C_afs_MaybeFreeDiscardedDCache; /* afs_dcache.c */
- afs_int32 C_PFlushMount; /* afs_pioctl.c */
- afs_int32 C_SRXAFSCB_GetServerPrefs; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetCellServDB; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetLocalCell; /* afs_callback.c */
- afs_int32 C_afs_MarshallCacheConfig; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetCacheConfig; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetCE64; /* afs_callback.c */
- afs_int32 C_SRXAFSCB_GetCellByNum; /* afs_callback.c */
-};
-
-struct afs_CMMeanStats {
- struct afs_MeanStats something; /* fill this in */
-};
-
-struct afs_CMStats {
- struct afs_CMCallStats callInfo;
- struct afs_CMMeanStats meanInfo;
-};
-
-/*
- * This is the structure accessible by specifying the
- * AFSCB_XSTATSCOLL_CALL_INFO collection to the xstat package.
- */
-extern struct afs_CMStats afs_cmstats;
-
-/*
- * Constants to track downtime durations:
- * Bucket 0: dur <= 10 min
- * Bucket 1: 10 min < dur <= 30 min
- * Bucket 2: 30 min < dur <= 1 hour
- * Bucket 3: 1 hour < dur <= 2 hours
- * Bucket 4: 2 hours < dur <= 4 hours
- * Bucket 5: 4 hours < dur <= 8 hours
- * Bucket 6: dur >= 8 hours
- */
-#define AFS_STATS_NUM_DOWNTIME_DURATION_BUCKETS 7
-
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0 600 /*10 minutes */
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1 1800 /*30 minutes */
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2 3600 /*60 minutes */
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3 7200 /*2 hours */
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4 14400 /*4 hours */
-#define AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5 28800 /*8 hours */
-
-/*
- * Constants to track downtime incidents:
- * Bucket 0: down = 0 times
- * Bucket 1: down = 1 time
- * Bucket 2: 1 time < down <= 5 times
- * Bucket 3: 5 times < down <= 10 times
- * Bucket 4: 10 times < down <= 50 times
- * Bucket 5: down > 50 times
- */
-#define AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS 6
-
-#define AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0 0
-#define AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1 1
-#define AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2 5
-#define AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3 10
-#define AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4 50
-
-/*
- * Numbers used to track aggregate up/downtime stats for servers. We'll
- * keep these numbers separately for FS and VL server records, and then
- * again separately for servers in the same cell as this client machine
- * and those outside the client's cell.
- */
-struct afs_stats_SrvUpDownInfo {
- afs_int32 numTtlRecords; /*# records, active or inactive */
- afs_int32 numUpRecords; /*# (active) records currently marked up */
- afs_int32 numDownRecords; /*# (active) records currently marked down */
- afs_int32 sumOfRecordAges; /*Sum of server record lifetimes */
- afs_int32 ageOfYoungestRecord; /*Age of youngest server record */
- afs_int32 ageOfOldestRecord; /*Age of oldest server record */
- afs_int32 numDowntimeIncidents; /*Number of (completed) downtime incidents */
- afs_int32 numRecordsNeverDown; /*Number of server records never marked down */
- afs_int32 maxDowntimesInARecord; /*Max downtimes seen by any record */
- afs_int32 sumOfDowntimes; /*Sum of all (completed) downtimes, in seconds */
- afs_int32 shortestDowntime; /*Shortest downtime, in seconds */
- afs_int32 longestDowntime; /*Longest downtime, in seconds */
- /*
- * Arrays keeping distributions on downtime durations and number of
- * downtime incidents.
- */
- afs_int32 downDurations[AFS_STATS_NUM_DOWNTIME_DURATION_BUCKETS];
- afs_int32 downIncidents[AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS];
-};
-
-/*
- * Define indices for the server up/downtime arrays below.
- */
-#define AFS_STATS_UPDOWN_IDX_SAME_CELL 0
-#define AFS_STATS_UPDOWN_IDX_DIFF_CELL 1
-
-/*
- * Performance numbers for the Cache Manager.
- */
-struct afs_stats_CMPerf {
- afs_int32 numPerfCalls; /*# of performance calls rcvd */
-
- afs_int32 epoch; /*Cache Manager epoch time */
- afs_int32 numCellsVisible; /*# cells we know about */
- afs_int32 numCellsContacted; /*# cells corresponded with */
- afs_int32 dlocalAccesses; /*# data accesses to files within cell */
- afs_int32 vlocalAccesses; /*# stat accesses to files within cell */
- afs_int32 dremoteAccesses; /*# data accesses to files outside of cell */
- afs_int32 vremoteAccesses; /*# stat accesses to files outside of cell */
- afs_int32 cacheNumEntries; /*# cache entries */
- afs_int32 cacheBlocksTotal; /*# (1K) blocks configured for cache */
- afs_int32 cacheBlocksInUse; /*# cache blocks actively in use */
- afs_int32 cacheBlocksOrig; /*# cache blocks at bootup */
- afs_int32 cacheMaxDirtyChunks; /*Max # dirty cache chunks tolerated */
- afs_int32 cacheCurrDirtyChunks; /*Current # dirty cache chunks */
- afs_int32 dcacheHits; /*# data files found in local cache */
- afs_int32 vcacheHits; /*# stat entries found in local cache */
- afs_int32 dcacheMisses; /*# data files NOT found in local cache */
- afs_int32 vcacheMisses; /*# stat entries NOT found in local cache */
- afs_int32 cacheFlushes; /*# files flushed from cache */
- afs_int32 cacheFilesReused; /*# cache files reused */
- afs_int32 ProtServerAddr; /*Addr of Protection Server used */
- afs_int32 vcacheXAllocs; /* Additionally allocated vcaches */
- afs_int32 dcacheXAllocs; /* Additionally allocated dcaches */
-
- /*
- * Some stats related to our buffer package
- */
- afs_int32 bufAlloced; /* # of buffers allocated by afs */
- afs_int32 bufHits; /* # of pages found on buffer cache */
- afs_int32 bufMisses; /* # of pages NOT found on buffer cache */
- afs_int32 bufFlushDirty; /* # of cached dirty bufs flushed because all busy */
-
- /*
- * Stats that keep track of all allocated/used objects in CM
- */
- afs_int32 LargeBlocksActive; /* # of currently used large free pool entries */
- afs_int32 LargeBlocksAlloced; /* # of allocated large free pool entries */
- afs_int32 SmallBlocksActive; /* # of currently used small free pool entries */
- afs_int32 SmallBlocksAlloced; /* # of allocated used small free pool entries */
- afs_int32 MediumBlocksActive; /* # of currently used medium free pool entries */
- afs_int32 MediumBlocksAlloced; /* # of allocated used medium free pool entries */
- afs_int32 OutStandingMemUsage; /* # of alloced memory */
- afs_int32 OutStandingAllocs; /* Outstanding osi_allocs (no osi_frees yet) */
- afs_int32 CallBackAlloced; /* # callback structures allocated */
- afs_int32 CallBackFlushes; /* # callback flush operations performed */
-
- /*
- * Accounting stats having to do with the server table & records.
- */
- afs_int32 srvRecords; /*# of servers currently on record */
- afs_int32 srvRecordsHWM; /* Server record high water mark */
- afs_int32 srvNumBuckets; /* Num server hash chain buckets */
- afs_int32 srvMaxChainLength; /* Max server hash chain length */
- afs_int32 srvMaxChainLengthHWM; /* Server hash chain high water mark */
-
- /*
- * Stats having to do with the systype upon which the Cache Manager
- * is running.
- */
- afs_int32 sysName_ID; /*Sysname ID for host hardware */
-
- /*
- * Stats recording downtime characteristics for each File Server and Volume
- * Location Server we've dealt with, both within the same cell and in
- * other cells.
- */
- struct afs_stats_SrvUpDownInfo fs_UpDown[2];
- struct afs_stats_SrvUpDownInfo vl_UpDown[2];
-
- afs_uint32 cbloops;
- afs_uint32 osiread_efaults;
- afs_int32 cacheBlocksDiscarded; /*# cache blocks free but not truncated */
- /*
- * Spares for future expansion.
- */
- afs_int32 spare[13]; /*Spares */
-};
-
-
-/*
- * Values denoting the File Server and Cache Manager opcodes.
- */
-#define AFS_STATS_FS_RPCIDX_FETCHDATA 0
-#define AFS_STATS_FS_RPCIDX_FETCHACL 1
-#define AFS_STATS_FS_RPCIDX_FETCHSTATUS 2
-#define AFS_STATS_FS_RPCIDX_STOREDATA 3
-#define AFS_STATS_FS_RPCIDX_STOREACL 4
-#define AFS_STATS_FS_RPCIDX_STORESTATUS 5
-#define AFS_STATS_FS_RPCIDX_REMOVEFILE 6
-#define AFS_STATS_FS_RPCIDX_CREATEFILE 7
-#define AFS_STATS_FS_RPCIDX_RENAME 8
-#define AFS_STATS_FS_RPCIDX_SYMLINK 9
-#define AFS_STATS_FS_RPCIDX_LINK 10
-#define AFS_STATS_FS_RPCIDX_MAKEDIR 11
-#define AFS_STATS_FS_RPCIDX_REMOVEDIR 12
-#define AFS_STATS_FS_RPCIDX_SETLOCK 13
-#define AFS_STATS_FS_RPCIDX_EXTENDLOCK 14
-#define AFS_STATS_FS_RPCIDX_RELEASELOCK 15
-#define AFS_STATS_FS_RPCIDX_GETSTATISTICS 16
-#define AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS 17
-#define AFS_STATS_FS_RPCIDX_GETVOLUMEINFO 18
-#define AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS 19
-#define AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS 20
-#define AFS_STATS_FS_RPCIDX_GETROOTVOLUME 21
-#define AFS_STATS_FS_RPCIDX_CHECKTOKEN 22
-#define AFS_STATS_FS_RPCIDX_GETTIME 23
-#define AFS_STATS_FS_RPCIDX_NGETVOLUMEINFO 24
-#define AFS_STATS_FS_RPCIDX_BULKSTATUS 25
-#define AFS_STATS_FS_RPCIDX_XSTATSVERSION 26
-#define AFS_STATS_FS_RPCIDX_GETXSTATS 27
-#define AFS_STATS_FS_RPCIDX_XLOOKUP 28
-#define AFS_STATS_FS_RPCIDX_RESIDENCYRPCS 29
-
-#define AFS_STATS_NUM_FS_RPC_OPS 29
-
-#define AFS_STATS_FS_XFERIDX_FETCHDATA 0
-#define AFS_STATS_FS_XFERIDX_STOREDATA 1
-
-#define AFS_STATS_NUM_FS_XFER_OPS 2
-
-#define AFS_STATS_CM_RPCIDX_CALLBACK 0
-#define AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE 1
-#define AFS_STATS_CM_RPCIDX_PROBE 2
-#define AFS_STATS_CM_RPCIDX_GETLOCK 3
-#define AFS_STATS_CM_RPCIDX_GETCE 4
-#define AFS_STATS_CM_RPCIDX_XSTATSVERSION 5
-#define AFS_STATS_CM_RPCIDX_GETXSTATS 6
-
-#define AFS_STATS_NUM_CM_RPC_OPS 7
-
-
-/*
- * Record to track timing numbers for each Cache Manager RPC operation.
- */
-struct afs_stats_opTimingData {
- afs_int32 numOps; /*Number of operations executed */
- afs_int32 numSuccesses; /*Number of successful ops */
- osi_timeval_t sumTime; /*Sum of sample timings */
- osi_timeval_t sqrTime; /*Sum of squares of sample timings */
- osi_timeval_t minTime; /*Minimum timing value observed */
- osi_timeval_t maxTime; /*Minimum timing value observed */
-};
-
-/*
- * We discriminate byte size transfers into this many buckets.
- */
-#define AFS_STATS_NUM_XFER_BUCKETS 9
-
-#define AFS_STATS_MAXBYTES_BUCKET0 128
-#define AFS_STATS_MAXBYTES_BUCKET1 1024
-#define AFS_STATS_MAXBYTES_BUCKET2 8192
-#define AFS_STATS_MAXBYTES_BUCKET3 16384
-#define AFS_STATS_MAXBYTES_BUCKET4 32768
-#define AFS_STATS_MAXBYTES_BUCKET5 131072
-#define AFS_STATS_MAXBYTES_BUCKET6 524288
-#define AFS_STATS_MAXBYTES_BUCKET7 1048576
-
-/*
- * Record to track timings and byte sizes for data transfers.
- */
-struct afs_stats_xferData {
- afs_int32 numXfers; /*Number of successful xfers */
- afs_int32 numSuccesses; /*Number of successful xfers */
- osi_timeval_t sumTime; /*Sum of timing values */
- osi_timeval_t sqrTime; /*Sum of squares of timing values */
- osi_timeval_t minTime; /*Minimum xfer time recorded */
- osi_timeval_t maxTime; /*Maximum xfer time recorded */
- afs_int32 sumBytes; /*Sum of KBytes transferred */
- afs_int32 minBytes; /*Minimum value observed */
- afs_int32 maxBytes; /*Maximum value observed */
- afs_int32 count[AFS_STATS_NUM_XFER_BUCKETS]; /*Tally for each range of bytes */
-};
-
-/*
- * Macros to operate on time values.
- *
- * afs_stats_TimeLessThan(t1, t2) Non-zero if t1 is less than t2
- * afs_stats_TimeGreaterThan(t1, t2) Non-zero if t1 is greater than t2
- * afs_stats_GetDiff(t3, t1, t2) Set t3 to the difference between
- * t1 and t2 (t1 is less than or
- * equal to t2).
- * afs_stats_AddTo(t1, t2) Add t2 to t1
- * afs_stats_TimeAssign(t1, t2) Assign time t2 to t1
- * afs_stats_SquareAddTo(t1,t2) Add square of t2 to t1
- */
-#define afs_stats_TimeLessThan(t1, t2) \
- ((t1.tv_sec < t2.tv_sec) ? 1 : \
- (t1.tv_sec > t2.tv_sec) ? 0 : \
- (t1.tv_usec < t2.tv_usec) ? 1 : \
- 0)
-
-#define afs_stats_TimeGreaterThan(t1, t2) \
- ((t1.tv_sec > t2.tv_sec) ? 1 : \
- (t1.tv_sec < t2.tv_sec) ? 0 : \
- (t1.tv_usec > t2.tv_usec) ? 1 : \
- 0)
-
-#define afs_stats_GetDiff(t3, t1, t2) \
-{ \
- /* \
- * If the microseconds of the later time are smaller than \
- * the earlier time, set up for proper subtraction (doing \
- * the carry). \
- */ \
- if (t2.tv_usec < t1.tv_usec) { \
- t2.tv_usec += 1000000; \
- t2.tv_sec -= 1; \
- } \
- t3.tv_sec = t2.tv_sec - t1.tv_sec; \
- t3.tv_usec = t2.tv_usec - t1.tv_usec; \
-}
-
-#define afs_stats_AddTo(t1, t2) \
-{ \
- t1.tv_sec += t2.tv_sec; \
- t1.tv_usec += t2.tv_usec; \
- if (t1.tv_usec > 1000000) { \
- t1.tv_usec -= 1000000; \
- t1.tv_sec++; \
- } \
-}
-
-#define afs_stats_TimeAssign(t1, t2) \
-{ \
- t1.tv_sec = t2.tv_sec; \
- t1.tv_usec = t2.tv_usec; \
-}
-/*
- * We calculate the square of a timeval as follows:
- *
- * The timeval struct contains two ints - the number of seconds and the
- * number of microseconds. These two numbers together gives the correct
- * amount of time => t = t.tv_sec + (t.tv_usec / 1000000);
- *
- * if x = t.tv_sec and y = (t.tv_usec / 1000000) then the square is simply:
- *
- * x^2 + 2xy + y^2
- *
- * Since we are trying to avoid floating point math, we use the following
- * observations to simplify the above equation:
- *
- * The resulting t.tv_sec (x') only depends upon the x^2 + 2xy portion
- * of the equation. This is easy to see if you think about y^2 in
- * decimal notation. y^2 is always < 0 since y < 0. Therefore in calculating
- * x', we can ignore y^2 (we do need to take care of rounding which is
- * done below).
- *
- * Similarly, in calculating t.tv_usec (y') we can ignore x^2 and concentrate
- * on 2xy + y^2.
- *
- * You'll notice that both x' and y' depend upon 2xy. We can further
- * simplify things by realizing that x' depends on upon the integer
- * portion of the 2xy term. We can get part of this integer by
- * multiplying 2 * x * t.tv_usec and then truncating the result by
- * / 1000000. Similarly, we can get the decimal portion of this term
- * by performing the same multiplication and then % 1000000. It is
- * possible that the decimal portion will in fact contain some of the
- * integer portion (this will be taken care of when we ensure that y'
- * is less than 1000000).
- *
- * The only other non-obvious calculation involves y^2. The key to
- * understanding this part of the calculation is to expand y again
- * in a nonobvious manner. We do this via the following expansion:
- *
- * y = t.tv_usec / 1000000;
- * let abcdef represent the six digits of t.tv_usec then we have:
- * t.tv_usec / 1000000 = abc/1000 + def/1000000;
- *
- * squaring yields:
- *
- * y^2 = (abc/1000)^2 + 2 * (abc/1000) * (def/1000000) + (def/1000000)^2
- *
- * Examining this equation yields the following observations:
- *
- * The second term can be calculated by multiplying abc and def then
- * shifting the decimal correctly.
- *
- * (def/1000000)^2 contributes only to rounding and we only round up
- * if def > 707.
- *
- * These two observations are the basis for the somewhat cryptic
- * calculation of usec^2 (i.e. they are the "tricks").
- */
-
-#define afs_stats_SquareAddTo(t1, t2) \
-{ \
- /* \
- * We use some tricks here to avoid floating point arithmetic \
- */ \
- if(t2.tv_sec > 0 ) \
- { \
- t1.tv_sec += t2.tv_sec * t2.tv_sec \
- + 2 * t2.tv_sec * t2.tv_usec /1000000; \
- t1.tv_usec += (2 * t2.tv_sec * t2.tv_usec) % 1000000 \
- + (t2.tv_usec / 1000)*(t2.tv_usec / 1000) \
- + 2 * (t2.tv_usec / 1000) * (t2.tv_usec % 1000) / 1000 \
- + (((t2.tv_usec % 1000) > 707) ? 1 : 0); \
- } \
- else \
- { \
- t1.tv_usec += (t2.tv_usec / 1000)*(t2.tv_usec / 1000) \
- + 2 * (t2.tv_usec / 1000) * (t2.tv_usec % 1000) / 1000 \
- + (((t2.tv_usec % 1000) > 707) ? 1 : 0); \
- } \
- if (t1.tv_usec > 1000000) { \
- t1.tv_usec -= 1000000; \
- t1.tv_sec++; \
- } \
-}
-
-
-
-
-/*
- * Structure recording RPC outcomes.
- */
-struct afs_stats_RPCErrors {
- afs_int32 err_Server; /*Server down error */
- afs_int32 err_Network; /*Network error */
- afs_int32 err_Protection; /*Protection violation */
- afs_int32 err_Volume; /*Volume-related error */
- afs_int32 err_VolumeBusies; /*"Volume busy conditions encountered */
- afs_int32 err_Other; /*Misc other errors */
-};
-
-
-/*
- * Structure holding RPC interface opcode measurements for the Cache Manager.
- */
-struct afs_stats_RPCOpInfo {
- struct afs_stats_opTimingData
- fsRPCTimes[AFS_STATS_NUM_FS_RPC_OPS]; /*Individual FS RPC op timings */
- struct afs_stats_RPCErrors
- fsRPCErrors[AFS_STATS_NUM_FS_RPC_OPS]; /*Individual FS RPC op errors */
- struct afs_stats_xferData
- fsXferTimes[AFS_STATS_NUM_FS_XFER_OPS]; /*Individual FS RPC xfer timings */
- struct afs_stats_opTimingData
- cmRPCTimes[AFS_STATS_NUM_CM_RPC_OPS]; /*Individual CM RPC op timings */
-};
-
-/*
- * Structure holding authentication info for the CM.
- */
-struct afs_stats_AuthentInfo {
- /*
- * This first set of fields don't have any history - they are simply
- * snapshots of the system at the time of the probe.
- */
- afs_int32 curr_PAGs; /*Current number of PAGs */
- afs_int32 curr_Records; /*Current # of records in table */
- afs_int32 curr_AuthRecords; /*Current # of authenticated
- * records (w/valid ticket) */
- afs_int32 curr_UnauthRecords; /*Current # of unauthenticated
- * records (w/o any ticket at all) */
- afs_int32 curr_MaxRecordsInPAG; /*Max records for a single PAG */
- afs_int32 curr_LongestChain; /*Length of longest current hash chain */
-
- /*
- * This second set of fields are values accumulated over the lifetme
- * of the current CM incarnation.
- */
- afs_int32 PAGCreations; /*# PAG creations */
- afs_int32 TicketUpdates; /*# ticket additions/refreshes */
- afs_int32 HWM_PAGs; /*High water mark - # PAGs */
- afs_int32 HWM_Records; /* " - # records */
- afs_int32 HWM_MaxRecordsInPAG; /* " - max records for a single PAG */
- afs_int32 HWM_LongestChain; /* " - longest hash chain */
-};
-
-/*
- * [Un]replicated file access. These count the number of RXAFS_FetchData
- * calls get accomplished, and their need to call upon other replicas in
- * case of failure.
- */
-struct afs_stats_AccessInfo {
- afs_int32 unreplicatedRefs; /*# references to unreplicated data */
- afs_int32 replicatedRefs; /*# references to replicated data */
- afs_int32 numReplicasAccessed; /*# replicas accessed */
- afs_int32 maxReplicasPerRef; /*Max # replicas accessed per ref */
- afs_int32 refFirstReplicaOK; /*# references satisfied by 1st replica */
-};
-
-/*
- * Structure holding authoring info for the CM. We keep track of
- * the results of writes on files and directories independently.
- * Results cover all objects in the cache uniformly.
- */
-struct afs_stats_AuthorInfo {
- afs_int32 fileSameAuthor; /*File write by same author */
- afs_int32 fileDiffAuthor; /*File write by diff author */
- afs_int32 dirSameAuthor; /*Directory write by same author */
- afs_int32 dirDiffAuthor; /*Directory write by diff author */
-};
-
-/*
- * Structure holding ``full'' CM peformance measurements.
- */
-struct afs_stats_CMFullPerf {
- afs_int32 numFullPerfCalls; /*Number of accesses */
- struct afs_stats_CMPerf perf; /*General performance stats */
- struct afs_stats_RPCOpInfo rpc; /*RPC op stats */
- struct afs_stats_AuthentInfo authent; /*Authentication stats */
- struct afs_stats_AccessInfo accessinf; /*Access stats */
- struct afs_stats_AuthorInfo author; /*Authorship stats */
-};
-
-/*
- * These are the storage declarations for the structures accessible
- * via the xstat package.
- */
-/* extern struct afs_stats_CMPerf afs_stats_cmperf; */
-/* extern struct afs_stats_CMFullPerf afs_stats_cmfullperf; */
-/* extern afs_int32 afs_stats_XferSumBytes[]; */
-
-#ifndef AFS_NOSTATS
-/*
- * We define routines to keep running counts and means. For the
- * running count, we have to concatenate the ``C_'' prefix on to
- * the routine name passed in as an argument to get the right
- * field name.
- */
-#define AFS_STATCNT(arg) ((afs_cmstats.callInfo.C_ ## arg)++)
-
-#define AFS_MEANCNT(arg, value) \
- (afs_AddToMean(((afs_cmstats.meanInfo).(arg)),value))
-
-#endif /* AFS_NOSTATS */
-
-
-#endif /* __OPENAFS_AFS_STATS_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
-
-error_table 2 ZCM
- ec CM_TRACE_NULL, "dummy"
- ec CM_TRACE_PAGEIN, "getapage vp 0x%lx off (0x%x, 0x%x) len 0x%x rw=0x%x"
- ec CM_TRACE_PAGEINDONE, "getapage done code 0x%x pg 0x%lx (0x%x)"
- ec CM_TRACE_PAGEOUT, "putpage vp 0x%lx off (0x%x, 0x%x) len 0x%x flags=0x%x"
- ec CM_TRACE_PAGEOUTDONE, "putpage done code 0x%x #dirty 0x%x"
- ec CM_TRACE_PAGEOUTONE, "putApage vp 0x%lx pag 0x%lx len 0x%x off (0x%x, 0x%x)"
- ec CM_TRACE_VMRW, "vmrw vp 0x%lx, write=0x%x, off=(0x%x, 0x%x), len=(0x%x, 0x%x)"
- ec CM_TRACE_STRATEGYDONE, "strategy done vp 0x%lx code 0x%x left 0x%x"
- ec CM_TRACE_FLUSHV, "flushv vp 0x%lx states 0x%x"
- ec CM_TRACE_GETDOWND, "getdownd vp 0x%lx skip 0x%x index %d coff (0x%x, 0x%x)"
- ec CM_TRACE_ACTCCORE, "ActiveCore vp 0x%lx XoW 0x%x"
- ec CM_TRACE_WVCACHE, "RXAFS_StoreStatus vp 0x%lx len (0x%x, 0x%x)"
- ec CM_TRACE_TRYTOSMUSH, "TryToSmush vp 0x%lx len 0x%x"
- ec CM_TRACE_STOREPROC, "StoreProc vp 0x%lx fid (%x:%d.%d.%d) m.Length (0x%x, 0x%x) alen 0x%x"
- ec CM_TRACE_FETCHPROC, "FetchProc vp 0x%lx fid (%x:%d.%d.%d) pos (0x%x, 0x%x) size 0x%x"
- ec CM_TRACE_SIMPLEVSTAT, "SimpleVStat vp 0x%lx old len (0x%x, 0x%x) new len (0x%x, 0x%x)"
- ec CM_TRACE_PROCESSFS, "ProcessFS vp 0x%lx old len (0x%x, 0x%x) new len (0x%x, 0x%x)"
- ec CM_TRACE_STOREALL, "StoreAll vp 0x%lx len (0x%x, 0x%x)"
- ec CM_TRACE_INVALL, "InvalAll vp 0x%lx len 0x%x"
- ec CM_TRACE_TRUNCALL, "TruncAll vp 0x%lx old len (0x%x, 0x%x) new len (0x%x, 0x%x)"
-
- ec CM_TRACE_GNLINK, "Gn_link vp 0x%lx name %s (returns 0x%x)"
- ec CM_TRACE_GMKDIR, "Gn_mkdir vp 0x%lx name %s mode 0x%x (returns 0x%x)"
- ec CM_TRACE_GMKNOD, "Gn_mknod vp 0x%lx name %s mode 0x%x (returns 0x%x)"
- ec CM_TRACE_GREMOVE, "Gn_remove vp 0x%lx name %s (returns 0x%x)"
- ec CM_TRACE_GRENAME, "Gn_rename vp 0x%lx fname %s tname %s (returns 0x%x)"
- ec CM_TRACE_GRMDIR, "Gn_rmdir vp 0x%lx name %s (returns 0x%x)"
- ec CM_TRACE_GLOOKUP, "Gn_lookup vp 0x%lx name %s (returns 0x%x)"
- ec CM_TRACE_GFID, "Gn_fid vp 0x%lx fidp 0x%lx (returns 0x%x)"
- ec CM_TRACE_GOPEN, "Gn_open vp 0x%lx flags 0x%x (returns 0x%x)"
- ec CM_TRACE_GCREATE, "Gn_create vp 0x%lx name %s mode 0x%x (returns 0x%x)"
- ec CM_TRACE_GCLOSE, "Gn_close vp 0x%lx flags 0x%x (returns 0x%x)"
- ec CM_TRACE_GMAP, "Gn_map vp 0x%lx addr 0x%lx len 0x%x off 0x%x"
- ec CM_TRACE_GACCESS, "Gn_access vp 0x%lx mode 0x%x (returns 0x%x)"
- ec CM_TRACE_GGETATTR, "Gn_getattr vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_GSETATTR, "Gn_setattr vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_GFCLEAR, "Gn_fclear vp 0x%lx offset 0x%x len 0x%x (returns 0x%x)"
- ec CM_TRACE_GFSYNC, "Gn_fsync vp 0x%lx flags 0x%x (returns 0x%x)"
- ec CM_TRACE_GFTRUNC, "Gn_ftrunc vp 0x%lx flags 0x%x len (0x%x, 0x%x) (returns 0x%x)"
- ec CM_TRACE_GRDWR, "Gn_rdwr vp 0x%lx flags 0x%x op 0x%x (returns 0x%x)"
- ec CM_TRACE_GLOCKCTL, "Gn_locktl vp 0x%lx cmd 0x%x (returns 0x%x)"
- ec CM_TRACE_GIOCTL, "Gn_ioctl vp 0x%lx cmd 0x%x (returns 0x%x)"
- ec CM_TRACE_GREADLINK, "Gn_readlink vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_GSYMLINK, "Gn_symlink vp 0x%lx link %s target %s (returns 0x%x)"
- ec CM_TRACE_GREADDIR, "Gn_readdir vp 0x%lx (returns 0x%x)"
-
- ec CM_TRACE_STUFFVCACHE, "StuffVcache 0x%lx callback host 0x%lx expires %u (in %u secs)"
- ec CM_TRACE_GETDCACHE1, "Getdcache vp 0x%lx failed to find chunk 0x%x"
- ec CM_TRACE_GETDCACHE2, "GetdCache vp 0x%lx dcache 0x%lx dcache low-version 0x%x, vcache low-version 0x%x"
- ec CM_TRACE_GETDCACHE3, "GetdCache tlen 0x%x flags 0x%x abyte (0x%x, 0x%x) Position (0x%x, 0x%x)"
- ec CM_TRACE_STOREMINI, "storemini vp 0x%lx length (0x%x, 0x%x)"
- ec CM_TRACE_STOREDCACHE, "StoreDCache vp 0x%lx chunk 0x%x length 0x%x at position 0x%x"
- ec CM_TRACE_STOREDCACHEDONE, "StoreDCache Done for vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_STOREALLDONE, "StoreAll Done vp 0x%lx length 0x%x (returns 0x%x)"
- ec CM_TRACE_PROBEDOWN, "GC Daemon: Checking down servers (every %d secs)"
- ec CM_TRACE_PROBEUP, "GC Daemon: Checking up servers/gc users (every %d secs)"
- ec CM_TRACE_PROBEVOLUME, "GC Daemon: Checking volumes (every %d secs)"
- ec CM_TRACE_BKG1, "Bkg daemon executing 0x%x request"
- ec CM_TRACE_HPSTRAT, "Strategy vp 0x%lx offset 0x%x size 0x%x count 0x%x"
- ec CM_TRACE_HPPAGEOUT, "pageout vp 0x%lx start 0x%x end 0x%x flags 0x%x"
- ec CM_TRACE_HPPAGEIN, "pagein vp 0x%lx type 0x%x bpages 0x%lx mmf 0x%lx"
- ec CM_TRACE_NFSREQH, "Nfsreq pag 0x%x uid 0x%x host 0x%x nfsclnt struct 0x%lx"
- ec CM_TRACE_NFSOUT, "NfsOut op 0x%x vp 0x%lx fid (%x:%d.%d.%d)"
- ec CM_TRACE_NFSIN, "NfsIn op 0x%x"
- ec CM_TRACE_NFSIN1, "Nfs Root fid client 0x%lx fid (%x:%d.%d.%d)"
- ec CM_TRACE_FLUSHPAGES, "flushpages vp 0x%lx data version low 0x%x length 0x%x"
- ec CM_TRACE_SYNCVM, "SyncVM vp 0x%lx length 0x%x"
- ec CM_TRACE_PIOCTL, "Pioctl command 0x%x for vp 0x%lx, follow=%d"
- ec CM_TRACE_CHECKCODE, "Returning code %d from %d"
- ec CM_TRACE_CHECKVLDB, "Did a CheckVLDB call for fid (%x:%d.%d.%d) = %x"
- ec CM_TRACE_GETVOL, "RPC GetVolumeByName for %s ( at 0x%x)"
- ec CM_TRACE_ANALYZE, "Analyze RPC op %d conn 0x%lx code 0x%x user 0x%x"
- ec CM_TRACE_SETPAG, "Setpag returns 0x%x"
- ec CM_TRACE_OPEN, "Open 0x%x flags 0x%x"
- ec CM_TRACE_CLOSE, "Close 0x%lx flags 0x%x"
- ec CM_TRACE_WRITE, "Write vp 0x%lx off (0x%x, 0x%x) resid (0x%x, 0x%x) file length (0x%x, 0x%x)"
- ec CM_TRACE_READ, "Read vp 0x%lx off (0x%x, 0x%x) resid 0x%x file length (0x%x, 0x%x)"
- ec CM_TRACE_PARTIALWRITE, "Partial write vp 0x%lx length (0x%x, 0x%x)"
- ec CM_TRACE_GETATTR, "Getattr vp 0x%lx len (0x%x, 0x%x)"
- ec CM_TRACE_SETATTR, "Setattr vp 0x%lx mask 0x%x newlen (0x%x, 0x%x) oldlen (0x%x, 0x%x)"
- ec CM_TRACE_ACCESS, "Access vp 0x%lx mode 0x%x len (0x%x, 0x%x)"
- ec CM_TRACE_LOOKUP, "Lookup adp 0x%lx name %s fid (%d:%d.%d.%d), code=%d"
- ec CM_TRACE_LOOKUP1, "Mount point is to vp 0x%lx fid (%d:%d.%d.%d)"
- ec CM_TRACE_CREATE, "create file in vp 0x%lx name %s mode 0x%x"
- ec CM_TRACE_REMOVE, "remove dir 0x%lx name %s"
- ec CM_TRACE_LINK, "hard link dir 0x%lx vp 0x%lx name %s"
- ec CM_TRACE_RENAME, "Rename d1 0x%lx name %s to d2 0x%lx name %s"
- ec CM_TRACE_MKDIR, "Mkdir parent 0x%lx entry %s"
- ec CM_TRACE_RMDIR, "Rmdir parent 0x%lx entry %s"
- ec CM_TRACE_SYMLINK, "Symlink dir 0x%lx link %s"
- ec CM_TRACE_READLINK, "readlink 0x%lx"
- ec CM_TRACE_FSYNC, "fsync 0x%lx"
-
- ec CM_TRACE_LOCKDONE, "%s line %d: Released lock 0x%lx level %d"
- ec CM_TRACE_LOCKDOWN, "%s line %d: Downgraded lock 0x%lx to %d"
- ec CM_TRACE_LOCKOBTAIN,"%s line %d: Obtained lock 0x%lx level %d"
- ec CM_TRACE_LOCKSLEPT, "Slept %lu us for lock 0x%lx level %d"
-
- ec CM_TRACE_PAGE_READ, "0x%lx called page_read (returned %d) states 0x%x"
- ec CM_TRACE_PAGE_WRITE, "0x%lx called page_write (returned %d) states 0x%x"
- ec CM_TRACE_STOREALLDC, "StoreAllDCache vp 0x%lx nchunks %x length 0x%x truncpos 0x%x"
- ec CM_TRACE_STOREALLDCDONE, "StoreAllDCache Done for vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_AVCLOCKER, "Vnode Lock vp 0x%lx wait 0x%x excl 0x%x"
- ec CM_TRACE_AVCLOCKEE, "Vnode Lock vp 0x%lx wait 0x%x readers %d waiters %d"
- ec CM_TRACE_SHORTREAD, "osi_Read want %d short %d err 0x%x"
- ec CM_TRACE_READFAILED, "osi_Read failed len %d err 0x%x"
- ec CM_TRACE_GETVCDOTDOT, "GetVCache .. fid (%d.%d.%d.%d) returned 0x%x (err %d)"
- ec CM_TRACE_CALLBACK, "Breaking callback for %lx states %d (volume %d)"
- ec CM_TRACE_VREF, "vcache 0x%lx has ref %d at %d"
- ec CM_TRACE_TMP_1S3L, "%s: %lx %lx %lx"
- ec CM_TRACE_TMP_2S2L, "%s: %s %lx %lx"
- ec CM_TRACE_NFS3OUT, "Nfs3Out op 0x%x vp 0x%lx fid (%x:%d.%d.%d)"
- ec CM_TRACE_NFS3IN, "Nfs3In op 0x%x"
- ec CM_TRACE_NFS3IN1, "Nfs3 Root fid client 0x%lx fid (%x:%d.%d.%d)"
- ec CM_TRACE_VGET, "Vget vp 0x%lx uid %x fid (%x:%d.%d.%d)"
- ec CM_TRACE_VFSROOT, "vfs root vp 0x%lx, code %d"
- ec CM_TRACE_READOP, "Iread ip x%lx pos (0x%x, 0x%x) count 0x%x code %x"
- ec CM_TRACE_WRITEOP, "Iwrite ip 0x%lx pos (0x%x, 0x%x) count 0x%x code %x"
- ec CM_TRACE_READPAGE, "Ireadpage ip 0x%lx pp 0x%x count 0x%x code %x"
- ec CM_TRACE_UPDATEPAGE, "Iupdatepage ip 0x%lx pp 0x%x count 0x%x code %d"
- ec CM_TRACE_VM_CLOSE, "VMclose ip 0x%lx mapcnt %d opens %d XoW %d"
- ec CM_TRACE_FETCH64, "FetchProc for vp = 0x%lx oldserver was %d, found length (0x%x, 0x%x)"
- ec CM_TRACE_UFSLINK, "UFSHandleLink: vp = 0x%lx, tdc 0x%lx, len (0x%x, 0x%x)"
- ec CM_TRACE_VMRDWR, "afs_vm_rdwr: vp = 0x%lx, xfrSize 0x%lx, toffset 0x%x"
- ec CM_TRACE_READFAST, "ReadFast vp 0x%lx off (0x%x, 0x%x) resid 0x%x file length (0x%x, 0x%x)"
- ec CM_TRACE_FETCH64CODE, "StartRX_FetchData64 for vp 0x%lx returned %d"
- ec CM_TRACE_FETCH64LENG, "FetchData64 for vp 0xl%x code = %d, length = (0x%x, 0x%x)"
- ec CM_TRACE_FETCH64READ, "FetchData64 for vp 0xl%x code = %d, length = 0x%x"
- ec CM_TRACE_VMWRITE, "afs_vm_rdwr: vp 0x%lx offset (0x%x, 0x%x) length (0x%x, 0x%x)"
- ec CM_TRACE_VMWRITE2, "afs_vm_rdwr: vp 0x%lx first page 0x%x pages %d"
- ec CM_TRACE_VMSTOREALL, "osi_VM_StoreAllSegments for vp 0x%lx call %d"
- ec CM_TRACE_PARTIALWRITE0, "Partial write currDirty %d maxDirty %d"
- ec CM_TRACE_DIRECTRDWR, "direct_rdwr: vp 0x%lx offset (0x%x, 0x%x) resid 0x%x"
- ec CM_TRACE_GOPRDWR, "gop_rdwr: offset (0x%x, 0x%x) len 0x%x resid 0x%x code %d"
- ec CM_TRACE_GRDWR1, "Gn_rdwr error vp 0x%lx returns %d"
- ec CM_TRACE_READTDC, "UFSRead: vp 0x%lx tdc 0x%lx at %d refcount 0x%x"
- ec CM_TRACE_MEMFETCH, "MemFetch: vp 0x%lx mceP 0x%lx offset (0x%x, 0x%x) length 0x%x"
- ec CM_TRACE_VMWRITE3, "afs_vm_rdwr: vp 0x%lx code %d"
- ec CM_TRACE_STOREALL2, "StoreAll 2 vp 0x%lx chunk 0x%x index %d inode %d"
- ec CM_TRACE_MEMOPEN, "MemOpen blkno %d mceP 0x%x data 0x%x = %s"
- ec CM_TRACE_VCACHE2INODE, "vcache2inode: avc 0x%x event %d"
- ec CM_TRACE_STOREDATA64, "StoreData64: fid (%d:%d.%d.%d) offs (0x%x, 0x%x) len (0x%x, 0x%x) file length (0x%x, 0x%x)"
- ec CM_TRACE_RESIDCMD, "ResidencyCmd tvc 0x%x command %d fid (%d:%d.%d.%d)"
- ec CM_TRACE_PREFETCHCMD, "PrefetchCmd tvc 0x%x tfid (%d:%d.%d.%d) fid (%d:%d.%d.%d)"
- ec CM_TRACE_STOREPROC2, "StoreProc got (0x%x, 0x%x) length 0x%x"
- ec CM_TRACE_ADJUSTSIZE, "AdjustSize index %d oldSize %d newSize %d blocksUsed %d"
- ec CM_TRACE_SETLENGTH, "%s line %d: m.Length was (0x%x, 0x%x), now (0x%x, 0x%x)"
- ec CM_TRACE_DCACHEWAIT, "%s line %d: waiting for 0x%x flags 0x%x"
- ec CM_TRACE_VNODEREAD, "UFSRead: tdc 0x%lx, offset (0x%x, 0x%x) len (0x%x 0x%x)"
- ec CM_TRACE_SLEEP, "Sleep: evp 0x%lx, count %d seq 0x%x evp->seq 0x%x"
- ec CM_TRACE_WAKE, "Wakeup: evp 0x%lx, evp->seq 0x%x"
- ec CM_TRACE_DENTRYDELETE, "d_delete inode 0x%x d_name %s/%s"
- ec CM_TRACE_DENTRYIPUT, "d_iput inode 0x%x d_name %s/%s"
- ec CM_TRACE_TRYFLUSHDCACHECHILDREN, "TryFlushDcacheChildren ip 0x%x name %s parent %s"
- ec CM_TRACE_DCACHEWAKE, "%s line %d: waking up waiters for 0x%x flags 0x%x"
- ec CM_TRACE_VERSIONNO, "At offset (0x%x, 0x%x) vc shows (0x%x, 0x%x), dc (0x%x, 0x%x)"
- ec CM_TRACE_TIMESTAMP, "%s"
- ec CM_TRACE_RXSLEEP, "osi_rxSleep() at %s line %d"
- ec CM_TRACE_RXWAKE, "osi_rxWakeup() at %s line %d"
- ec CM_TRACE_GNGETACL, "Gn_getacl vp 0x%lx (returns 0x%x)"
- ec CM_TRACE_EINVAL, "EINVAL in %s at line %d"
- ec CM_TRACE_VNODEREAD2, "negative length tdc 0x%lx validPos (0x%x, 0x%x) chunkBytes 0x%x dflags 0x%x"
- ec CM_TRACE_WASHERE, "Was here: %s line %d, code = %d"
- ec CM_TRACE_LOCKWAIT,"%s line %d: Waiting for lock 0x%lx level %d"
- ec CM_TRACE_WRITEFAILED, "osi_Write failed len %ld resid %ld err %ld"
- ec CM_TRACE_ADJUSTSIZE2, "AdjustSize dc = 0x%lx, chunkBytes = 0x%x used = %ld, diff = %ld"
-end
-
+++ /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
- */
-
-/*
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_user.c,v 1.15 2003/07/15 23:14:13 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* ! AFS_HPUX110_ENV */
-#endif /* !defined(UKERNEL) */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-
-/* Exported variables */
-afs_rwlock_t afs_xuser;
-struct unixuser *afs_users[NUSERS];
-
-
-/* Forward declarations */
-void afs_ResetAccessCache(afs_int32 uid, int alock);
-
-/*
- * Called with afs_xuser, afs_xserver and afs_xconn locks held, to delete
- * appropriate conn structures for au
- */
-static void
-RemoveUserConns(register struct unixuser *au)
-{
- register int i;
- register struct server *ts;
- register struct srvAddr *sa;
- register struct conn *tc, **lc;
-
- AFS_STATCNT(RemoveUserConns);
- for (i = 0; i < NSERVERS; i++) {
- for (ts = afs_servers[i]; ts; ts = ts->next) {
- for (sa = ts->addr; sa; sa = sa->next_sa) {
- lc = &sa->conns;
- for (tc = *lc; tc; lc = &tc->next, tc = *lc) {
- if (tc->user == au && tc->refCount == 0) {
- *lc = tc->next;
- AFS_GUNLOCK();
- rx_DestroyConnection(tc->id);
- AFS_GLOCK();
- afs_osi_Free(tc, sizeof(struct conn));
- break; /* at most one instance per server */
- } /*Found unreferenced connection for user */
- } /*For each connection on the server */
- }
- } /*For each server on chain */
- } /*For each chain */
-
-} /*RemoveUserConns */
-
-
-/* Called from afs_Daemon to garbage collect unixusers no longer using system,
- * and their conns. The aforce parameter tells the function to flush all
- * *unauthenticated* conns, no matter what their expiration time; it exists
- * because after we choose our final rx epoch, we want to stop using calls with
- * other epochs as soon as possible (old file servers act bizarrely when they
- * see epoch changes).
- */
-void
-afs_GCUserData(int aforce)
-{
- register struct unixuser *tu, **lu, *nu;
- register int i;
- afs_int32 now, delFlag;
-
- AFS_STATCNT(afs_GCUserData);
- /* Obtain locks in valid order */
- ObtainWriteLock(&afs_xuser, 95);
- ObtainReadLock(&afs_xserver);
- ObtainWriteLock(&afs_xconn, 96);
- now = osi_Time();
- for (i = 0; i < NUSERS; i++) {
- for (lu = &afs_users[i], tu = *lu; tu; tu = nu) {
- delFlag = 0; /* should we delete this dude? */
- /* Don't garbage collect users in use now (refCount) */
- if (tu->refCount == 0) {
- if (tu->states & UHasTokens) {
- /*
- * Give ourselves a little extra slack, in case we
- * reauthenticate
- */
- if (tu->ct.EndTimestamp < now - NOTOKTIMEOUT)
- delFlag = 1;
- } else {
- if (aforce || (tu->tokenTime < now - NOTOKTIMEOUT))
- delFlag = 1;
- }
- }
- nu = tu->next;
- if (delFlag) {
- *lu = tu->next;
- RemoveUserConns(tu);
- if (tu->stp)
- afs_osi_Free(tu->stp, tu->stLen);
- if (tu->exporter)
- EXP_RELE(tu->exporter);
- afs_osi_Free(tu, sizeof(struct unixuser));
- } else {
- lu = &tu->next;
- }
- }
- }
- ReleaseWriteLock(&afs_xconn);
- ReleaseWriteLock(&afs_xuser);
- ReleaseReadLock(&afs_xserver);
-
-} /*afs_GCUserData */
-
-
-/*
- * Check for unixusers who encountered bad tokens, and reset the access
- * cache for these guys. Can't do this when token expiration detected,
- * since too many locks are set then.
- */
-void
-afs_CheckTokenCache(void)
-{
- register int i;
- register struct unixuser *tu;
- afs_int32 now;
-
- AFS_STATCNT(afs_CheckCacheResets);
- ObtainReadLock(&afs_xvcache);
- ObtainReadLock(&afs_xuser);
- now = osi_Time();
- for (i = 0; i < NUSERS; i++) {
- for (tu = afs_users[i]; tu; tu = tu->next) {
- register afs_int32 uid;
-
- /*
- * If tokens are still good and user has Kerberos tickets,
- * check expiration
- */
- if (!(tu->states & UTokensBad) && tu->vid != UNDEFVID) {
- if (tu->ct.EndTimestamp < now) {
- /*
- * This token has expired, warn users and reset access
- * cache.
- */
-#ifdef notdef
- /* I really hate this message - MLK */
- afs_warn
- ("afs: Tokens for user of AFS id %d for cell %s expired now\n",
- tu->vid, afs_GetCell(tu->cell)->cellName);
-#endif
- tu->states |= (UTokensBad | UNeedsReset);
- }
- }
- if (tu->states & UNeedsReset) {
- tu->states &= ~UNeedsReset;
- uid = tu->uid;
- afs_ResetAccessCache(uid, 0);
- }
- }
- }
- ReleaseReadLock(&afs_xuser);
- ReleaseReadLock(&afs_xvcache);
-
-} /*afs_CheckTokenCache */
-
-
-void
-afs_ResetAccessCache(afs_int32 uid, int alock)
-{
- register int i;
- register struct vcache *tvc;
- struct axscache *ac;
-
- AFS_STATCNT(afs_ResetAccessCache);
- if (alock)
- ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- /* really should do this under cache write lock, but that.
- * is hard to under locking hierarchy */
- if (tvc->Access && (ac = afs_FindAxs(tvc->Access, uid))) {
- afs_RemoveAxs(&tvc->Access, ac);
- }
- }
- }
- if (alock)
- ReleaseReadLock(&afs_xvcache);
-
-} /*afs_ResetAccessCache */
-
-
-/*
- * Ensure all connections make use of new tokens. Discard incorrectly-cached
- * access info.
- */
-void
-afs_ResetUserConns(register struct unixuser *auser)
-{
- int i;
- struct srvAddr *sa;
- struct conn *tc;
-
- AFS_STATCNT(afs_ResetUserConns);
- ObtainReadLock(&afs_xsrvAddr);
- ObtainWriteLock(&afs_xconn, 98);
-
- for (i = 0; i < NSERVERS; i++) {
- for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
- for (tc = sa->conns; tc; tc = tc->next) {
- if (tc->user == auser) {
- tc->forceConnectFS = 1;
- }
- }
- }
- }
-
- ReleaseWriteLock(&afs_xconn);
- ReleaseReadLock(&afs_xsrvAddr);
- afs_ResetAccessCache(auser->uid, 1);
- auser->states &= ~UNeedsReset;
-} /*afs_ResetUserConns */
-
-
-struct unixuser *
-afs_FindUser(afs_int32 auid, afs_int32 acell, afs_int32 locktype)
-{
- register struct unixuser *tu;
- register afs_int32 i;
-
- AFS_STATCNT(afs_FindUser);
- i = UHash(auid);
- ObtainWriteLock(&afs_xuser, 99);
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->uid == auid && ((tu->cell == acell) || (acell == -1))) {
- tu->refCount++;
- ReleaseWriteLock(&afs_xuser);
- return tu;
- }
- }
- ReleaseWriteLock(&afs_xuser);
- return NULL;
-
-} /*afs_FindUser */
-
-
-/*------------------------------------------------------------------------
- * EXPORTED afs_ComputePAGStats
- *
- * Description:
- * Compute a set of stats concerning PAGs used by this machine.
- *
- * Arguments:
- * None.
- *
- * Returns:
- * Nothing.
- *
- * Environment:
- * The results are put in the structure responsible for keeping
- * detailed CM stats. Note: entries corresponding to a single PAG
- * will appear on the identical hash chain, so sweeping the chain
- * will find all entries related to a single PAG.
- *
- * Side Effects:
- * As advertised.
- *------------------------------------------------------------------------*/
-
-void
-afs_ComputePAGStats(void)
-{
- register struct unixuser *currPAGP; /*Ptr to curr PAG */
- register struct unixuser *cmpPAGP; /*Ptr to PAG being compared */
- register struct afs_stats_AuthentInfo *authP; /*Ptr to stats area */
- int curr_Record; /*Curr record */
- int currChain; /*Curr hash chain */
- int currChainLen; /*Length of curr hash chain */
- int currPAGRecords; /*# records in curr PAG */
-
- /*
- * Lock out everyone else from scribbling on the PAG entries.
- */
- ObtainReadLock(&afs_xuser);
-
- /*
- * Initialize the tallies, then sweep through each hash chain. We
- * can't bzero the structure, since some fields are cumulative over
- * the CM's lifetime.
- */
- curr_Record = 0;
- authP = &(afs_stats_cmfullperf.authent);
- authP->curr_PAGs = 0;
- authP->curr_Records = 0;
- authP->curr_AuthRecords = 0;
- authP->curr_UnauthRecords = 0;
- authP->curr_MaxRecordsInPAG = 0;
- authP->curr_LongestChain = 0;
-
- for (currChain = 0; currChain < NUSERS; currChain++) {
- currChainLen = 0;
- for (currPAGP = afs_users[currChain]; currPAGP;
- currPAGP = currPAGP->next) {
- /*
- * Bump the number of records on this current chain, along with
- * the total number of records in existence.
- */
- currChainLen++;
- curr_Record++;
- /*
- * We've found a previously-uncounted PAG. If it's been deleted
- * but just not garbage-collected yet, we step over it.
- */
- if (currPAGP->vid == UNDEFVID)
- continue;
-
- /*
- * If this PAG record has already been ``counted', namely
- * associated with a PAG and tallied, clear its bit and move on.
- */
- (authP->curr_Records)++;
- if (currPAGP->states & UPAGCounted) {
- currPAGP->states &= ~UPAGCounted;
- continue;
- }
-
-
-
- /*We've counted this one already */
- /*
- * Jot initial info down, then sweep down the rest of the hash
- * chain, looking for matching PAG entries. Note: to properly
- * ``count'' the current record, we first compare it to itself
- * in the following loop.
- */
- (authP->curr_PAGs)++;
- currPAGRecords = 0;
-
- for (cmpPAGP = currPAGP; cmpPAGP; cmpPAGP = cmpPAGP->next) {
- if (currPAGP->uid == cmpPAGP->uid) {
- /*
- * The records belong to the same PAG. First, mark the
- * new record as ``counted'' and bump the PAG size.
- * Then, record the state of its ticket, if any.
- */
- cmpPAGP->states |= UPAGCounted;
- currPAGRecords++;
- if ((cmpPAGP->states & UHasTokens)
- && !(cmpPAGP->states & UTokensBad))
- (authP->curr_AuthRecords)++;
- else
- (authP->curr_UnauthRecords)++;
- } /*Records belong to same PAG */
- } /*Compare to rest of PAG records in chain */
-
- /*
- * In the above comparisons, the current PAG record has been
- * marked as counted. Erase this mark before moving on.
- */
- currPAGP->states &= ~UPAGCounted;
-
- /*
- * We've compared our current PAG record with all remaining
- * PAG records in the hash chain. Update our tallies, and
- * perhaps even our lifetime high water marks. After that,
- * remove our search mark and advance to the next comparison
- * pair.
- */
- if (currPAGRecords > authP->curr_MaxRecordsInPAG) {
- authP->curr_MaxRecordsInPAG = currPAGRecords;
- if (currPAGRecords > authP->HWM_MaxRecordsInPAG)
- authP->HWM_MaxRecordsInPAG = currPAGRecords;
- }
- } /*Sweep a hash chain */
-
- /*
- * If the chain we just finished zipping through is the longest we've
- * seen yet, remember this fact before advancing to the next chain.
- */
- if (currChainLen > authP->curr_LongestChain) {
- authP->curr_LongestChain = currChainLen;
- if (currChainLen > authP->HWM_LongestChain)
- authP->HWM_LongestChain = currChainLen;
- }
-
- } /*For each hash chain in afs_user */
-
- /*
- * Now that we've counted everything up, we can consider all-time
- * numbers.
- */
- if (authP->curr_PAGs > authP->HWM_PAGs)
- authP->HWM_PAGs = authP->curr_PAGs;
- if (authP->curr_Records > authP->HWM_Records)
- authP->HWM_Records = authP->curr_Records;
-
- /*
- * People are free to manipulate the PAG structures now.
- */
- ReleaseReadLock(&afs_xuser);
-
-} /*afs_ComputePAGStats */
-
-
-struct unixuser *
-afs_GetUser(register afs_int32 auid, afs_int32 acell, afs_int32 locktype)
-{
- register struct unixuser *tu, *pu = 0;
- register afs_int32 i;
- register afs_int32 RmtUser = 0;
-
- AFS_STATCNT(afs_GetUser);
- i = UHash(auid);
- ObtainWriteLock(&afs_xuser, 104);
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->uid == auid) {
- RmtUser = 0;
- pu = NULL;
- if (tu->exporter) {
- RmtUser = 1;
- pu = tu;
- }
- if (tu->cell == -1 && acell != -1) {
- /* Here we setup the real cell for the client */
- tu->cell = acell;
- tu->refCount++;
- ReleaseWriteLock(&afs_xuser);
- return tu;
- } else if (tu->cell == acell || acell == -1) {
- tu->refCount++;
- ReleaseWriteLock(&afs_xuser);
- return tu;
- }
- }
- }
- tu = (struct unixuser *)afs_osi_Alloc(sizeof(struct unixuser));
-#ifndef AFS_NOSTATS
- afs_stats_cmfullperf.authent.PAGCreations++;
-#endif /* AFS_NOSTATS */
- memset((char *)tu, 0, sizeof(struct unixuser));
- tu->next = afs_users[i];
- afs_users[i] = tu;
- if (RmtUser) {
- /*
- * This is for the case where an additional unixuser struct is
- * created because the remote client is accessing a different cell;
- * we simply rerecord relevant information from the original
- * structure
- */
- if (pu && pu->exporter) {
- (void)EXP_HOLD(tu->exporter = pu->exporter);
- }
- }
- tu->uid = auid;
- tu->cell = acell;
- tu->vid = UNDEFVID;
- tu->refCount = 1;
- tu->tokenTime = osi_Time();
- ReleaseWriteLock(&afs_xuser);
- return tu;
-
-} /*afs_GetUser */
-
-
-void
-afs_PutUser(register struct unixuser *au, afs_int32 locktype)
-{
- AFS_STATCNT(afs_PutUser);
- --au->refCount;
-} /*afs_PutUser */
-
-
-/*
- * Set the primary flag on a unixuser structure, ensuring that exactly one
- * dude has the flag set at any time for a particular unix uid.
- */
-void
-afs_SetPrimary(register struct unixuser *au, register int aflag)
-{
- register struct unixuser *tu;
- register int i;
- struct unixuser *pu;
-
- AFS_STATCNT(afs_SetPrimary);
- i = UHash(au->uid);
- pu = NULL;
- ObtainWriteLock(&afs_xuser, 105);
- /*
- * See if anyone is this uid's primary cell yet; recording in pu the
- * corresponding user
- */
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->uid == au->uid && (tu->states & UPrimary)) {
- pu = tu;
- }
- }
- if (pu && !(pu->states & UHasTokens)) {
- /*
- * Primary user has unlogged, don't treat him as primary any longer;
- * note that we want to treat him as primary until now, so that
- * people see a primary identity until now.
- */
- pu->states &= ~UPrimary;
- pu = NULL;
- }
- if (aflag == 1) {
- /* setting au to be primary */
- if (pu)
- pu->states &= ~UPrimary;
- au->states |= UPrimary;
- } else if (aflag == 0) {
- /* we don't know if we're supposed to be primary or not */
- if (!pu || au == pu) {
- au->states |= UPrimary;
- } else
- au->states &= ~UPrimary;
- }
- ReleaseWriteLock(&afs_xuser);
-
-} /*afs_SetPrimary */
-
-
-#if AFS_GCPAGS
-
-/*
- * Called by osi_TraverseProcTable (from afs_GCPAGs) for each
- * process in the system.
- * If the specified process uses a PAG, clear that PAG's temporary
- * 'deleteme' flag.
- */
-
-/*
- * This variable keeps track of the number of UID-base
- * tokens in the afs_users table. When it's zero
- * the per process loop in GCPAGs doesn't have to
- * check processes without pags against the afs_users table.
- */
-static afs_int32 afs_GCPAGs_UIDBaseTokenCount = 0;
-
-/*
- * These variables keep track of the number of times
- * afs_GCPAGs_perproc_func() is called. If it is not called at all when
- * walking the process table, there is something wrong and we should not
- * prematurely expire any tokens.
- */
-static size_t afs_GCPAGs_perproc_count = 0;
-static size_t afs_GCPAGs_cred_count = 0;
-
-/*
- * LOCKS: afs_GCPAGs_perproc_func requires write lock on afs_xuser
- */
-void
-afs_GCPAGs_perproc_func(AFS_PROC * pproc)
-{
- afs_int32 pag, hash, uid;
- const struct AFS_UCRED *pcred;
-
- afs_GCPAGs_perproc_count++;
-
- pcred = afs_osi_proc2cred(pproc);
- if (!pcred)
- return;
-
- afs_GCPAGs_cred_count++;
-
- pag = PagInCred(pcred);
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD40_ENV) || defined(AFS_LINUX22_ENV)
- uid = (pag != NOPAG ? pag : pcred->cr_uid);
-#else
- uid = (pag != NOPAG ? pag : pcred->cr_ruid);
-#endif
- hash = UHash(uid);
-
- /* if this token is PAG based, or it's UID based and
- * UID-based tokens exist */
- if ((pag != NOPAG) || (afs_GCPAGs_UIDBaseTokenCount)) {
- /* find the entries for this uid in all cells and clear the not
- * referenced flag. Can't use afs_FindUser, because it just returns
- * the specific cell asked for, or the first one found.
- */
- struct unixuser *pu;
- for (pu = afs_users[hash]; pu; pu = pu->next) {
- if (pu->uid == uid) {
- if (pu->states & TMP_UPAGNotReferenced) {
- /* clear the 'deleteme' flag for this entry */
- pu->states &= ~TMP_UPAGNotReferenced;
- if (pag == NOPAG) {
- /* This is a uid based token that hadn't
- * previously been cleared, so decrement the
- * outstanding uid based token count */
- afs_GCPAGs_UIDBaseTokenCount--;
- }
- }
- }
- }
- }
-}
-
-/*
- * Go through the process table, find all unused PAGs
- * and cause them to be deleted during the next GC.
- *
- * returns the number of PAGs marked for deletion
- *
- * On AIX we free PAGs when the last accessing process exits,
- * so this routine is not needed.
- *
- * In AFS WebSecure, we explicitly call unlog when we remove
- * an entry in the login cache, so this routine is not needed.
- */
-
-afs_int32
-afs_GCPAGs(afs_int32 * ReleasedCount)
-{
- struct unixuser *pu;
- int i;
-
- if (afs_gcpags != AFS_GCPAGS_OK) {
- return 0;
- }
-
- *ReleasedCount = 0;
-
- /* first, loop through afs_users, setting the temporary 'deleteme' flag */
- ObtainWriteLock(&afs_xuser, 419);
- afs_GCPAGs_UIDBaseTokenCount = 0;
- for (i = 0; i < NUSERS; i++) {
- for (pu = afs_users[i]; pu; pu = pu->next) {
- pu->states |= TMP_UPAGNotReferenced;
- if (((pu->uid >> 24) & 0xff) != 'A') {
- /* this is a uid-based token, */
- /* increment the count */
- afs_GCPAGs_UIDBaseTokenCount++;
- }
- }
- }
-
- /* Now, iterate through the systems process table,
- * for each process, mark it's PAGs (if any) in use.
- * i.e. clear the temporary deleteme flag.
- */
- afs_GCPAGs_perproc_count = 0;
- afs_GCPAGs_cred_count = 0;
-
- afs_osi_TraverseProcTable();
-
- /* If there is an internal problem and afs_GCPAGs_perproc_func()
- * does not get called, disable gcpags so that we do not
- * accidentally expire all the tokens in the system.
- */
- if (afs_gcpags == AFS_GCPAGS_OK && !afs_GCPAGs_perproc_count) {
- afs_gcpags = AFS_GCPAGS_EPROCWALK;
- }
-
- if (afs_gcpags == AFS_GCPAGS_OK && !afs_GCPAGs_cred_count) {
- afs_gcpags = AFS_GCPAGS_ECREDWALK;
- }
-
- /* Now, go through afs_users again, any that aren't in use
- * (temp deleteme flag still set) will be marked for later deletion,
- * by setting their expire times to 0.
- */
- for (i = 0; i < NUSERS; i++) {
- for (pu = afs_users[i]; pu; pu = pu->next) {
- if (pu->states & TMP_UPAGNotReferenced) {
-
- /* clear the temp flag */
- pu->states &= ~TMP_UPAGNotReferenced;
-
- /* Is this entry on behalf of a 'remote' user ?
- * i.e. nfs translator, etc.
- */
- if (!pu->exporter && afs_gcpags == AFS_GCPAGS_OK) {
- /* set the expire times to 0, causes
- * afs_GCUserData to remove this entry
- */
- pu->ct.EndTimestamp = 0;
- pu->tokenTime = 0;
-
- (*ReleasedCount)++; /* remember how many we marked (info only) */
- }
- }
- }
- }
-
- ReleaseWriteLock(&afs_xuser);
-
- return 0;
-}
-
-#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
- */
-
-/*
- * afs_util.c - miscellaneous AFS client utility functions
- *
- * Implements:
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_util.c,v 1.17 2003/07/15 23:14:13 shadow Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* ! AFS_HPUX110_ENV */
-#endif /* !defined(UKERNEL) */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-#if defined(AFS_AIX_ENV)
-#include <sys/fp_io.h>
-#endif
-
-#ifndef afs_cv2string
-char *
-afs_cv2string(char *ttp, afs_uint32 aval)
-{
- register char *tp = ttp;
- register int i;
- int any;
-
- AFS_STATCNT(afs_cv2string);
- any = 0;
- *(--tp) = 0;
- while (aval != 0) {
- i = aval % 10;
- *(--tp) = '0' + i;
- aval /= 10;
- any = 1;
- }
- if (!any)
- *(--tp) = '0';
- return tp;
-
-} /*afs_cv2string */
-#endif
-
-#ifndef afs_strcasecmp
-int
-afs_strcasecmp(char *s1, char *s2)
-{
- while (*s1 && *s2) {
- char c1, c2;
-
- c1 = *s1++;
- c2 = *s2++;
- if (c1 >= 'A' && c1 <= 'Z')
- c1 += 0x20;
- if (c2 >= 'A' && c2 <= 'Z')
- c2 += 0x20;
- if (c1 != c2)
- return c1 - c2;
- }
-
- return *s1 - *s2;
-}
-#endif
-
-#ifndef afs_strcat
-char *
-afs_strcat(char *s1, char *s2)
-{
- char *os1;
-
- os1 = s1;
- while (*s1++);
- --s1;
- while ((*s1++ = *s2++));
- return (os1);
-}
-#endif
-
-#ifdef AFS_OBSD34_ENV
-char *
-afs_strcpy(char *s1, char *s2)
-{
- char *os1;
-
- os1 = s1;
- while ((*s1++ = *s2++) != '\0');
- return os1;
-}
-#endif
-
-#ifndef afs_strchr
-char *
-afs_strchr(char *s, int c)
-{
- char *p;
-
- for (p = s; *p; p++)
- if (*p == c)
- return p;
- return NULL;
-}
-#endif
-
-char *
-afs_strdup(char *s)
-{
- char *n;
- int cc;
-
- cc = strlen(s) + 1;
- n = (char *)afs_osi_Alloc(cc);
- if (n)
- memcpy(n, s, cc);
-
- return n;
-}
-
-void
-print_internet_address(char *preamble, struct srvAddr *sa, char *postamble,
- int flag)
-{
- register struct server *aserver = sa->server;
- char *ptr = "\n";
- afs_uint32 address;
-
- AFS_STATCNT(print_internet_address);
- address = ntohl(sa->sa_ip);
- if (aserver->flags & SRVR_MULTIHOMED) {
- if (flag == 1) { /* server down mesg */
- if (!(aserver->flags & SRVR_ISDOWN))
- ptr =
- " (multi-homed address; other same-host interfaces maybe up)\n";
- else
- ptr = " (all multi-homed ip addresses down for the server)\n";
- } else if (flag == 2) { /* server up mesg */
- ptr =
- " (multi-homed address; other same-host interfaces may still be down)\n";
- }
- }
- afs_warn("%s%d.%d.%d.%d in cell %s%s%s", preamble, (address >> 24),
- (address >> 16) & 0xff, (address >> 8) & 0xff, (address) & 0xff,
- aserver->cell->cellName, postamble, ptr);
- afs_warnuser("%s%d.%d.%d.%d in cell %s%s%s", preamble, (address >> 24),
- (address >> 16) & 0xff, (address >> 8) & 0xff,
- (address) & 0xff, aserver->cell->cellName, postamble, ptr);
-
-} /*print_internet_address */
-
-
-
-/* * * * * * *
- * this code badly needs to be cleaned up... too many ugly ifdefs.
- * XXX
- */
-#if 0
-void
-afs_warn(char *a, long b, long c, long d, long e, long f, long g, long h,
- long i, long j)
-#else
-void
-afs_warn(a, b, c, d, e, f, g, h, i, j)
- char *a;
-#if defined( AFS_USE_VOID_PTR)
- void *b, *c, *d, *e, *f, *g, *h, *i, *j;
-#else
- long b, c, d, e, f, g, h, i, j;
-#endif
-#endif
-{
- AFS_STATCNT(afs_warn);
-
- if (afs_showflags & GAGCONSOLE) {
-#if defined(AFS_AIX_ENV)
- struct file *fd;
-
- /* cf. console_printf() in oncplus/kernext/nfs/serv/shared.c */
- if (fp_open
- ("/dev/console", O_WRONLY | O_NOCTTY | O_NDELAY, 0666, 0, FP_SYS,
- &fd) == 0) {
- char buf[1024];
- ssize_t len;
- ssize_t count;
-
- sprintf(buf, a, b, c, d, e, f, g, h, i, j);
- len = strlen(buf);
- fp_write(fd, buf, len, 0, UIO_SYSSPACE, &count);
- fp_close(fd);
- }
-#else
- printf(a, b, c, d, e, f, g, h, i, j);
-#endif
- }
-}
-
-#if 0
-void
-afs_warnuser(char *a, long b, long c, long d, long e, long f, long g, long h,
- long i, long j)
-#else
-void
-afs_warnuser(a, b, c, d, e, f, g, h, i, j)
- char *a;
- long b, c, d, e, f, g, h, i, j;
-#endif
-{
- AFS_STATCNT(afs_warnuser);
- if (afs_showflags & GAGUSER) {
-#ifdef AFS_GLOBAL_SUNLOCK
- int haveGlock = ISAFS_GLOCK();
- if (haveGlock)
- AFS_GUNLOCK();
-#endif /* AFS_GLOBAL_SUNLOCK */
-
- uprintf(a, b, c, d, e, f, g, h, i, j);
-
-#ifdef AFS_GLOBAL_SUNLOCK
- if (haveGlock)
- AFS_GLOCK();
-#endif /* AFS_GLOBAL_SUNLOCK */
- }
-}
-
-
-/* run everywhere, checking locks */
-void
-afs_CheckLocks(void)
-{
- register int i;
-
- afs_warn("Looking for locked data structures.\n");
- afs_warn("conn %x, volume %x, user %x, cell %x, server %x\n", afs_xconn,
- afs_xvolume, afs_xuser, afs_xcell, afs_xserver);
- {
- register struct vcache *tvc;
- AFS_STATCNT(afs_CheckLocks);
-
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-#ifdef AFS_OSF_ENV
- if (VREFCOUNT(tvc) > 1)
-#else /* AFS_OSF_ENV */
- if (VREFCOUNT(tvc))
-#endif
- afs_warn("Stat cache entry at %x is held\n", tvc);
- if (CheckLock(&tvc->lock))
- afs_warn("Stat entry at %x is locked\n", tvc);
- }
- }
- }
- {
- register struct dcache *tdc;
- for (i = 0; i < afs_cacheFiles; i++) {
- tdc = afs_indexTable[i];
- if (tdc) {
- if (tdc->refCount)
- afs_warn("Disk entry %d at %x is held\n", i, tdc);
- }
- if (afs_indexFlags[i] & IFDataMod)
- afs_warn("Disk entry %d at %x has IFDataMod flag set.\n", i,
- tdc);
- }
- }
- {
- struct srvAddr *sa;
- struct server *ts;
- struct conn *tc;
- for (i = 0; i < NSERVERS; i++) {
- for (ts = afs_servers[i]; ts; ts = ts->next) {
- if (ts->flags & SRVR_ISDOWN)
- printf("Server entry %x is marked down\n", ts);
- for (sa = ts->addr; sa; sa = sa->next_sa) {
- for (tc = sa->conns; tc; tc = tc->next) {
- if (tc->refCount)
- afs_warn("conn at %x (server %x) is held\n", tc,
- sa->sa_ip);
- }
- }
- }
- }
- }
- {
- struct volume *tv;
- for (i = 0; i < NVOLS; i++) {
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (CheckLock(&tv->lock))
- afs_warn("volume at %x is locked\n", tv);
- if (tv->refCount)
- afs_warn("volume at %x is held\n", tv);
- }
- }
- }
- {
- struct unixuser *tu;
-
- for (i = 0; i < NUSERS; i++) {
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (tu->refCount)
- printf("user at %x is held\n", tu);
- }
- }
- }
- afs_warn("Done.\n");
-}
-
-
-int
-afs_noop(void)
-{
- AFS_STATCNT(afs_noop);
-#ifdef AFS_OSF30_ENV
- return (EOPNOTSUPP);
-#else
- return EINVAL;
-#endif
-}
-
-int
-afs_badop(void)
-{
- AFS_STATCNT(afs_badop);
- osi_Panic("afs bad vnode op");
- return 0;
-}
-
-/*
- * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
- * given data pointer, without triggering "cast truncates pointer"
- * warnings. We use this where we explicitly don't care whether a
- * pointer is truncated -- it loses information where a pointer is
- * larger than an afs_int32.
- */
-
-afs_int32
-afs_data_pointer_to_int32(const void *p)
-{
- union {
- afs_int32 i32[sizeof(void *) / sizeof(afs_int32)];
- const void *p;
- } ip;
-
- int i32_sub; /* subscript of least significant afs_int32 in ip.i32[] */
-
- /* set i32_sub */
-
- {
- /* used to determine the byte order of the system */
-
- union {
- char c[sizeof(int) / sizeof(char)];
- int i;
- } ci;
-
- ci.i = 1;
- if (ci.c[0] == 1) {
- /* little-endian system */
- i32_sub = 0;
- } else {
- /* big-endian system */
- i32_sub = (sizeof ip.i32 / sizeof ip.i32[0]) - 1;
- }
- }
-
- ip.p = p;
- return ip.i32[i32_sub];
-}
+++ /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
- */
-
-/*
- * Header file exporting afs_util.c
- */
-#ifndef _AFS_UTIL_H_
-#define _AFS_UTIL_H_
-
-/* Handy max length of a numeric string. */
-#define CVBS 12 /* max afs_int32 is 2^32 ~ 4*10^9, +1 for NULL, +luck */
-
-#endif /* _AFS_UTIL_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
- */
-
-/*
- * Implements:
- * afs_FlushVCache
- * afs_AllocCBR
- * afs_FreeCBR
- * afs_FlushVCBs
- * afs_QueueVCB
- * afs_RemoveVCB
- * afs_NewVCache
- * afs_FlushActiveVcaches
- * afs_VerifyVCache2
- * afs_WriteVCache
- * afs_SimpleVStat
- * afs_ProcessFS
- * TellALittleWhiteLie
- * afs_RemoteLookup
- * afs_GetVCache
- * afs_LookupVCache
- * afs_GetRootVCache
- * afs_FetchStatus
- * afs_StuffVcache
- * afs_PutVCache
- * afs_FindVCache
- * afs_NFSFindVCache
- * afs_vcacheInit
- * shutdown_vcache
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.62 2004/05/08 04:20:39 shadow Exp $");
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-#include "afs/afs_stats.h"
-#include "afs/afs_cbqueue.h"
-#include "afs/afs_osidnlc.h"
-
-#ifdef AFS_OSF_ENV
-afs_int32 afs_maxvcount = 0; /* max number of vcache entries */
-afs_int32 afs_vcount = 0; /* number of vcache in use now */
-#endif /* AFS_OSF_ENV */
-
-#ifdef AFS_SGI_ENV
-int afsvnumbers = 0;
-#endif
-
-#ifdef AFS_SGI64_ENV
-char *makesname();
-#endif /* AFS_SGI64_ENV */
-
-/* Exported variables */
-afs_rwlock_t afs_xvcache; /*Lock: alloc new stat cache entries */
-afs_lock_t afs_xvcb; /*Lock: fids on which there are callbacks */
-struct vcache *freeVCList; /*Free list for stat cache entries */
-struct vcache *Initial_freeVCList; /*Initial list for above */
-struct afs_q VLRU; /*vcache LRU */
-afs_int32 vcachegen = 0;
-unsigned int afs_paniconwarn = 0;
-struct vcache *afs_vhashT[VCSIZE];
-static struct afs_cbr *afs_cbrHashT[CBRSIZE];
-afs_int32 afs_bulkStatsLost;
-int afs_norefpanic = 0;
-
-/* Forward declarations */
-static afs_int32 afs_QueueVCB(struct vcache *avc);
-
-/*
- * afs_HashCBRFid
- *
- * Generate an index into the hash table for a given Fid.
- */
-static int
-afs_HashCBRFid(struct AFSFid *fid) {
- return (fid->Volume + fid->Vnode + fid->Unique) % CBRSIZE;
-}
-
-/*
- * afs_InsertHashCBR
- *
- * Insert a CBR entry into the hash table.
- * Must be called with afs_xvcb held.
- */
-static void
-afs_InsertHashCBR(struct afs_cbr *cbr) {
- int slot = afs_HashCBRFid(&cbr->fid);
-
- cbr->hash_next = afs_cbrHashT[slot];
- if (afs_cbrHashT[slot])
- afs_cbrHashT[slot]->hash_pprev = &cbr->hash_next;
-
- cbr->hash_pprev = &afs_cbrHashT[slot];
- afs_cbrHashT[slot] = cbr;
-}
-
-/*
- * afs_FlushVCache
- *
- * Description:
- * Flush the given vcache entry.
- *
- * Parameters:
- * avc : Pointer to vcache entry to flush.
- * slept : Pointer to int to set 1 if we sleep/drop locks, 0 if we don't.
- *
- * Environment:
- * afs_xvcache lock must be held for writing upon entry to
- * prevent people from changing the vrefCount field, and to
- * protect the lruq and hnext fields.
- * LOCK: afs_FlushVCache afs_xvcache W
- * REFCNT: vcache ref count must be zero on entry except for osf1
- * RACE: lock is dropped and reobtained, permitting race in caller
- */
-
-int
-afs_FlushVCache(struct vcache *avc, int *slept)
-{ /*afs_FlushVCache */
-
- register afs_int32 i, code;
- register struct vcache **uvc, *wvc;
-
- *slept = 0;
- AFS_STATCNT(afs_FlushVCache);
- afs_Trace2(afs_iclSetp, CM_TRACE_FLUSHV, ICL_TYPE_POINTER, avc,
- ICL_TYPE_INT32, avc->states);
-#ifdef AFS_OSF_ENV
- AFS_GUNLOCK();
- VN_LOCK(AFSTOV(avc));
- AFS_GLOCK();
-#endif
-
- code = osi_VM_FlushVCache(avc, slept);
- if (code)
- goto bad;
-
- if (avc->states & CVFlushed) {
- code = EBUSY;
- goto bad;
- }
- if (avc->nextfree || !avc->vlruq.prev || !avc->vlruq.next) { /* qv afs.h */
- refpanic("LRU vs. Free inconsistency");
- }
- avc->states |= CVFlushed;
- /* pull the entry out of the lruq and put it on the free list */
- QRemove(&avc->vlruq);
- avc->vlruq.prev = avc->vlruq.next = (struct afs_q *)0;
-
- /* keep track of # of files that we bulk stat'd, but never used
- * before they got recycled.
- */
- if (avc->states & CBulkStat)
- afs_bulkStatsLost++;
- vcachegen++;
- /* remove entry from the hash chain */
- i = VCHash(&avc->fid);
- uvc = &afs_vhashT[i];
- for (wvc = *uvc; wvc; uvc = &wvc->hnext, wvc = *uvc) {
- if (avc == wvc) {
- *uvc = avc->hnext;
- avc->hnext = (struct vcache *)NULL;
- break;
- }
- }
- if (!wvc)
- osi_Panic("flushvcache"); /* not in correct hash bucket */
- if (avc->mvid)
- osi_FreeSmallSpace(avc->mvid);
- avc->mvid = (struct VenusFid *)0;
- if (avc->linkData) {
- afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
- avc->linkData = NULL;
- }
-#if defined(AFS_XBSD_ENV)
- /* OK, there are no internal vrefCounts, so there shouldn't
- * be any more refs here. */
- if (avc->v) {
- avc->v->v_data = NULL; /* remove from vnode */
- avc->v = NULL; /* also drop the ptr to vnode */
- }
-#endif
- afs_FreeAllAxs(&(avc->Access));
-
- /* we can't really give back callbacks on RO files, since the
- * server only tracks them on a per-volume basis, and we don't
- * know whether we still have some other files from the same
- * volume. */
- if ((avc->states & CRO) == 0 && avc->callback) {
- afs_QueueVCB(avc);
- }
- ObtainWriteLock(&afs_xcbhash, 460);
- afs_DequeueCallback(avc); /* remove it from queued callbacks list */
- avc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- afs_symhint_inval(avc);
- if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
- else
- osi_dnlc_purgevp(avc);
-
- /*
- * Next, keep track of which vnodes we've deleted for create's
- * optimistic synchronization algorithm
- */
- afs_allZaps++;
- if (avc->fid.Fid.Vnode & 1)
- afs_oddZaps++;
- else
- afs_evenZaps++;
-
-#if !defined(AFS_OSF_ENV)
- /* put the entry in the free list */
- avc->nextfree = freeVCList;
- freeVCList = avc;
- if (avc->vlruq.prev || avc->vlruq.next) {
- refpanic("LRU vs. Free inconsistency");
- }
-#else
- /* This should put it back on the vnode free list since usecount is 1 */
- afs_vcount--;
- vSetType(avc, VREG);
- if (VREFCOUNT(avc) > 0) {
- VN_UNLOCK(AFSTOV(avc));
- AFS_RELE(AFSTOV(avc));
- } else {
- if (afs_norefpanic) {
- printf("flush vc refcnt < 1");
- afs_norefpanic++;
- (void)vgone(avc, VX_NOSLEEP, NULL);
- AFS_GLOCK();
- VN_UNLOCK(AFSTOV(avc));
- } else
- osi_Panic("flush vc refcnt < 1");
- }
-#endif /* AFS_OSF_ENV */
- avc->states |= CVFlushed;
- return 0;
-
- bad:
-#ifdef AFS_OSF_ENV
- VN_UNLOCK(AFSTOV(avc));
-#endif
- return code;
-
-} /*afs_FlushVCache */
-
-#ifndef AFS_SGI_ENV
-/*
- * afs_InactiveVCache
- *
- * The core of the inactive vnode op for all but IRIX.
- */
-void
-afs_InactiveVCache(struct vcache *avc, struct AFS_UCRED *acred)
-{
- AFS_STATCNT(afs_inactive);
- if (avc->states & CDirty) {
- /* we can't keep trying to push back dirty data forever. Give up. */
- afs_InvalidateAllSegments(avc); /* turns off dirty bit */
- }
- avc->states &= ~CMAPPED; /* mainly used by SunOS 4.0.x */
- avc->states &= ~CDirty; /* Turn it off */
- if (avc->states & CUnlinked) {
- if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) {
- avc->states |= CUnlinkedDel;
- return;
- }
- afs_remunlink(avc, 1); /* ignore any return code */
- }
-
-}
-#endif
-
-/*
- * afs_AllocCBR
- *
- * Description: allocate a callback return structure from the
- * free list and return it.
- *
- * Env: The alloc and free routines are both called with the afs_xvcb lock
- * held, so we don't have to worry about blocking in osi_Alloc.
- */
-static struct afs_cbr *afs_cbrSpace = 0;
-struct afs_cbr *
-afs_AllocCBR(void)
-{
- register struct afs_cbr *tsp;
- int i;
-
- while (!afs_cbrSpace) {
- if (afs_stats_cmperf.CallBackAlloced >= 2) {
- /* don't allocate more than 2 * AFS_NCBRS for now */
- afs_FlushVCBs(0);
- afs_stats_cmperf.CallBackFlushes++;
- } else {
- /* try allocating */
- tsp =
- (struct afs_cbr *)afs_osi_Alloc(AFS_NCBRS *
- sizeof(struct afs_cbr));
- for (i = 0; i < AFS_NCBRS - 1; i++) {
- tsp[i].next = &tsp[i + 1];
- }
- tsp[AFS_NCBRS - 1].next = 0;
- afs_cbrSpace = tsp;
- afs_stats_cmperf.CallBackAlloced++;
- }
- }
- tsp = afs_cbrSpace;
- afs_cbrSpace = tsp->next;
- return tsp;
-}
-
-/*
- * afs_FreeCBR
- *
- * Description: free a callback return structure, removing it from all lists.
- *
- * Parameters:
- * asp -- the address of the structure to free.
- *
- * Environment: the xvcb lock is held over these calls.
- */
-int
-afs_FreeCBR(register struct afs_cbr *asp)
-{
- *(asp->pprev) = asp->next;
- if (asp->next)
- asp->next->pprev = asp->pprev;
-
- *(asp->hash_pprev) = asp->hash_next;
- if (asp->hash_next)
- asp->hash_next->hash_pprev = asp->hash_pprev;
-
- asp->next = afs_cbrSpace;
- afs_cbrSpace = asp;
- return 0;
-}
-
-/*
- * afs_FlushVCBs
- *
- * Description: flush all queued callbacks to all servers.
- *
- * Parameters: none.
- *
- * Environment: holds xvcb lock over RPC to guard against race conditions
- * when a new callback is granted for the same file later on.
- */
-afs_int32
-afs_FlushVCBs(afs_int32 lockit)
-{
- struct AFSFid *tfids;
- struct AFSCallBack callBacks[1];
- struct AFSCBFids fidArray;
- struct AFSCBs cbArray;
- afs_int32 code;
- struct afs_cbr *tcbrp;
- int tcount;
- struct server *tsp;
- int i;
- struct vrequest treq;
- struct conn *tc;
- int safety1, safety2, safety3;
- XSTATS_DECLS if ((code = afs_InitReq(&treq, afs_osi_credp)))
- return code;
- treq.flags |= O_NONBLOCK;
- tfids = afs_osi_Alloc(sizeof(struct AFSFid) * AFS_MAXCBRSCALL);
-
- if (lockit)
- MObtainWriteLock(&afs_xvcb, 273);
- ObtainReadLock(&afs_xserver);
- for (i = 0; i < NSERVERS; i++) {
- for (safety1 = 0, tsp = afs_servers[i];
- tsp && safety1 < afs_totalServers + 10;
- tsp = tsp->next, safety1++) {
- /* don't have any */
- if (tsp->cbrs == (struct afs_cbr *)0)
- continue;
-
- /* otherwise, grab a block of AFS_MAXCBRSCALL from the list
- * and make an RPC, over and over again.
- */
- tcount = 0; /* number found so far */
- for (safety2 = 0; safety2 < afs_cacheStats; safety2++) {
- if (tcount >= AFS_MAXCBRSCALL || !tsp->cbrs) {
- /* if buffer is full, or we've queued all we're going
- * to from this server, we should flush out the
- * callbacks.
- */
- fidArray.AFSCBFids_len = tcount;
- fidArray.AFSCBFids_val = (struct AFSFid *)tfids;
- cbArray.AFSCBs_len = 1;
- cbArray.AFSCBs_val = callBacks;
- memset(&callBacks[0], 0, sizeof(callBacks[0]));
- callBacks[0].CallBackType = CB_EXCLUSIVE;
- for (safety3 = 0; safety3 < MAXHOSTS * 2; safety3++) {
- tc = afs_ConnByHost(tsp, tsp->cell->fsport,
- tsp->cell->cellNum, &treq, 0,
- SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME
- (AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_GiveUpCallBacks(tc->id, &fidArray,
- &cbArray);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- if (!afs_Analyze
- (tc, code, 0, &treq,
- AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK,
- tsp->cell)) {
- break;
- }
- }
- /* ignore return code, since callbacks may have
- * been returned anyway, we shouldn't leave them
- * around to be returned again.
- *
- * Next, see if we are done with this server, and if so,
- * break to deal with the next one.
- */
- if (!tsp->cbrs)
- break;
- tcount = 0;
- }
- /* if to flush full buffer */
- /* if we make it here, we have an entry at the head of cbrs,
- * which we should copy to the file ID array and then free.
- */
- tcbrp = tsp->cbrs;
- tfids[tcount++] = tcbrp->fid;
-
- /* Freeing the CBR will unlink it from the server's CBR list */
- afs_FreeCBR(tcbrp);
- } /* while loop for this one server */
- if (safety2 > afs_cacheStats) {
- afs_warn("possible internal error afs_flushVCBs (%d)\n",
- safety2);
- }
- } /* for loop for this hash chain */
- } /* loop through all hash chains */
- if (safety1 > afs_totalServers + 2) {
- afs_warn
- ("AFS internal error (afs_flushVCBs) (%d > %d), continuing...\n",
- safety1, afs_totalServers + 2);
- if (afs_paniconwarn)
- osi_Panic("afs_flushVCBS safety1");
- }
-
- ReleaseReadLock(&afs_xserver);
- if (lockit)
- MReleaseWriteLock(&afs_xvcb);
- afs_osi_Free(tfids, sizeof(struct AFSFid) * AFS_MAXCBRSCALL);
- return 0;
-}
-
-/*
- * afs_QueueVCB
- *
- * Description:
- * Queue a callback on the given fid.
- *
- * Parameters:
- * avc: vcache entry
- *
- * Environment:
- * Locks the xvcb lock.
- * Called when the xvcache lock is already held.
- */
-
-static afs_int32
-afs_QueueVCB(struct vcache *avc)
-{
- struct server *tsp;
- struct afs_cbr *tcbp;
-
- AFS_STATCNT(afs_QueueVCB);
- /* The callback is really just a struct server ptr. */
- tsp = (struct server *)(avc->callback);
-
- /* we now have a pointer to the server, so we just allocate
- * a queue entry and queue it.
- */
- MObtainWriteLock(&afs_xvcb, 274);
- tcbp = afs_AllocCBR();
- tcbp->fid = avc->fid.Fid;
-
- tcbp->next = tsp->cbrs;
- if (tsp->cbrs)
- tsp->cbrs->pprev = &tcbp->next;
-
- tsp->cbrs = tcbp;
- tcbp->pprev = &tsp->cbrs;
-
- afs_InsertHashCBR(tcbp);
-
- /* now release locks and return */
- MReleaseWriteLock(&afs_xvcb);
- return 0;
-}
-
-
-/*
- * afs_RemoveVCB
- *
- * Description:
- * Remove a queued callback for a given Fid.
- *
- * Parameters:
- * afid: The fid we want cleansed of queued callbacks.
- *
- * Environment:
- * Locks xvcb and xserver locks.
- * Typically called with xdcache, xvcache and/or individual vcache
- * entries locked.
- */
-
-void
-afs_RemoveVCB(struct VenusFid *afid)
-{
- int slot;
- struct afs_cbr *cbr, *ncbr;
-
- AFS_STATCNT(afs_RemoveVCB);
- MObtainWriteLock(&afs_xvcb, 275);
-
- slot = afs_HashCBRFid(&afid->Fid);
- ncbr = afs_cbrHashT[slot];
-
- while (ncbr) {
- cbr = ncbr;
- ncbr = cbr->hash_next;
-
- if (afid->Fid.Volume == cbr->fid.Volume &&
- afid->Fid.Vnode == cbr->fid.Vnode &&
- afid->Fid.Unique == cbr->fid.Unique) {
- afs_FreeCBR(cbr);
- }
- }
-
- MReleaseWriteLock(&afs_xvcb);
-}
-
-#if defined(AFS_LINUX22_ENV) && !defined(AFS_LINUX26_ENV)
-
-static void
-__shrink_dcache_parent(struct dentry *parent)
-{
- struct dentry *this_parent = parent;
- struct list_head *next;
- int found = 0;
- LIST_HEAD(afs_dentry_unused);
-
- repeat:
- next = this_parent->d_subdirs.next;
- resume:
- while (next != &this_parent->d_subdirs) {
- struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
- next = tmp->next;
- if (!DCOUNT(dentry)) {
- list_del(&dentry->d_lru);
- list_add(&dentry->d_lru, afs_dentry_unused.prev);
- found++;
- }
- /*
- * Descend a level if the d_subdirs list is non-empty.
- */
- if (!list_empty(&dentry->d_subdirs)) {
- this_parent = dentry;
- goto repeat;
- }
- }
- /*
- * All done at this level ... ascend and resume the search.
- */
- if (this_parent != parent) {
- next = this_parent->d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
- }
-
- for (;;) {
- struct dentry *dentry;
- struct list_head *tmp;
-
- tmp = afs_dentry_unused.prev;
-
- if (tmp == &afs_dentry_unused)
- break;
-#ifdef AFS_LINUX24_ENV
- list_del_init(tmp);
-#else
- list_del(tmp);
- INIT_LIST_HEAD(tmp);
-#endif /* AFS_LINUX24_ENV */
- dentry = list_entry(tmp, struct dentry, d_lru);
-
-#ifdef AFS_LINUX24_ENV
- /* Unused dentry with a count? */
- if (DCOUNT(dentry))
- BUG();
-#endif
- DGET(dentry);
-#ifdef AFS_LINUX24_ENV
- list_del_init(&dentry->d_hash); /* d_drop */
-#else
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
- DUNLOCK();
- dput(dentry);
- DLOCK();
- if (!--found)
- break;
- }
-}
-
-/* afs_TryFlushDcacheChildren -- Shakes loose vcache references held by
- * children of the dentry
- *
- * LOCKS -- Called with afs_xvcache write locked. Drops and reaquires
- * AFS_GLOCK, so it can call dput, which may call iput, but
- * keeps afs_xvcache exclusively.
- *
- * Tree traversal algorithm from fs/dcache.c: select_parent()
- */
-static void
-afs_TryFlushDcacheChildren(struct vcache *tvc)
-{
- struct inode *ip = AFSTOI(tvc);
- struct dentry *this_parent;
- struct list_head *next;
- struct list_head *cur;
- struct list_head *head = &ip->i_dentry;
- struct dentry *dentry;
-
- AFS_GUNLOCK();
- restart:
-#ifndef old_vcache_scheme
- DLOCK();
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
-
- afs_Trace3(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
- ICL_TYPE_POINTER, ip, ICL_TYPE_STRING,
- dentry->d_parent->d_name.name, ICL_TYPE_STRING,
- dentry->d_name.name);
-
- if (!list_empty(&dentry->d_hash) && !list_empty(&dentry->d_subdirs))
- __shrink_dcache_parent(dentry);
-
- if (!DCOUNT(dentry)) {
- DGET(dentry);
-#ifdef AFS_LINUX24_ENV
- list_del_init(&dentry->d_hash); /* d_drop */
-#else
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
- DUNLOCK();
- dput(dentry);
- goto restart;
- }
- }
- DUNLOCK();
- AFS_GLOCK();
-#else
- restart:
- DLOCK();
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
-
- afs_Trace3(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
- ICL_TYPE_POINTER, ip, ICL_TYPE_STRING,
- dentry->d_parent->d_name.name, ICL_TYPE_STRING,
- dentry->d_name.name);
-
- if (!DCOUNT(dentry)) {
- AFS_GUNLOCK();
- DGET(dentry);
- DUNLOCK();
- d_drop(dentry);
- dput(dentry);
- AFS_GLOCK();
- goto restart;
- }
- }
- DUNLOCK();
-#endif
-}
-#endif /* AFS_LINUX22_ENV && !AFS_LINUX26_ENV */
-
-/*
- * afs_NewVCache
- *
- * Description:
- * This routine is responsible for allocating a new cache entry
- * from the free list. It formats the cache entry and inserts it
- * into the appropriate hash tables. It must be called with
- * afs_xvcache write-locked so as to prevent several processes from
- * trying to create a new cache entry simultaneously.
- *
- * Parameters:
- * afid : The file id of the file whose cache entry is being
- * created.
- */
-/* LOCK: afs_NewVCache afs_xvcache W */
-struct vcache *
-afs_NewVCache(struct VenusFid *afid, struct server *serverp)
-{
- struct vcache *tvc;
- afs_int32 i;
- afs_int32 anumber = VCACHE_FREE;
-#ifdef AFS_AIX_ENV
- struct gnode *gnodepnt;
-#endif
-#ifdef AFS_MACH_ENV
- struct vm_info *vm_info_ptr;
-#endif /* AFS_MACH_ENV */
-#ifdef AFS_OSF_ENV
- struct vcache *nvc;
-#endif /* AFS_OSF_ENV */
- struct afs_q *tq, *uq;
- int code, fv_slept;
-
- AFS_STATCNT(afs_NewVCache);
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
- if (afs_vcount >= afs_maxvcount) {
-#else
- /*
- * If we are using > 33 % of the total system vnodes for AFS vcache
- * entries or we are using the maximum number of vcache entries,
- * then free some. (if our usage is > 33% we should free some, if
- * our usage is > afs_maxvcount, set elsewhere to 0.5*nvnode,
- * we _must_ free some -- no choice).
- */
- if (((3 * afs_vcount) > nvnode) || (afs_vcount >= afs_maxvcount)) {
-#endif
- struct afs_q *tq, *uq;
- int i;
- char *panicstr;
-
- i = 0;
- for (tq = VLRU.prev; tq != &VLRU && anumber > 0; tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
- if (tvc->states & CVFlushed)
- refpanic("CVFlushed on VLRU");
- else if (i++ > afs_maxvcount)
- refpanic("Exceeded pool of AFS vnodes(VLRU cycle?)");
- else if (QNext(uq) != tq)
- refpanic("VLRU inconsistent");
- else if (VREFCOUNT(tvc) < 1)
- refpanic("refcnt 0 on VLRU");
-
- if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
- && (tvc->states & CUnlinkedDel) == 0) {
- code = afs_FlushVCache(tvc, &fv_slept);
- if (code == 0) {
- anumber--;
- }
- if (fv_slept) {
- uq = VLRU.prev;
- i = 0;
- continue; /* start over - may have raced. */
- }
- }
- if (tq == uq)
- break;
- }
- if (anumber == VCACHE_FREE) {
- printf("NewVCache: warning none freed, using %d of %d\n",
- afs_vcount, afs_maxvcount);
- if (afs_vcount >= afs_maxvcount) {
- osi_Panic("NewVCache - none freed");
- /* XXX instead of panicing, should do afs_maxvcount++
- * and magic up another one */
- }
- }
- }
-
- AFS_GUNLOCK();
- if (getnewvnode(MOUNT_AFS, &Afs_vnodeops, &nvc)) {
- /* What should we do ???? */
- osi_Panic("afs_NewVCache: no more vnodes");
- }
- AFS_GLOCK();
-
- tvc = nvc;
- tvc->nextfree = NULL;
- afs_vcount++;
-#else /* AFS_OSF_ENV */
- /* pull out a free cache entry */
- if (!freeVCList) {
- i = 0;
- for (tq = VLRU.prev; (anumber > 0) && (tq != &VLRU); tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
-
- if (tvc->states & CVFlushed) {
- refpanic("CVFlushed on VLRU");
- } else if (i++ > 2 * afs_cacheStats) { /* even allowing for a few xallocs... */
- refpanic("Increase -stat parameter of afsd(VLRU cycle?)");
- } else if (QNext(uq) != tq) {
- refpanic("VLRU inconsistent");
- }
-#ifdef AFS_DARWIN_ENV
- if (tvc->opens == 0 && ((tvc->states & CUnlinkedDel) == 0)
- && VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
- osi_VM_TryReclaim(tvc, &fv_slept);
- if (fv_slept) {
- uq = VLRU.prev;
- i = 0;
- continue; /* start over - may have raced. */
- }
- }
-#elif defined(AFS_LINUX22_ENV)
- if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) {
-#if defined(AFS_LINUX26_ENV)
- AFS_GUNLOCK();
- d_prune_aliases(AFSTOI(tvc));
- AFS_GLOCK();
-#else
- afs_TryFlushDcacheChildren(tvc);
-#endif
- }
-#endif
-
- if (VREFCOUNT(tvc) == 0 && tvc->opens == 0
- && (tvc->states & CUnlinkedDel) == 0) {
-#if defined(AFS_XBSD_ENV)
- /*
- * vgone() reclaims the vnode, which calls afs_FlushVCache(),
- * then it puts the vnode on the free list.
- * If we don't do this we end up with a cleaned vnode that's
- * not on the free list.
- * XXX assume FreeBSD is the same for now.
- */
- vgone(AFSTOV(tvc));
- code = fv_slept = 0;
-#else
- code = afs_FlushVCache(tvc, &fv_slept);
-#endif
- if (code == 0) {
- anumber--;
- }
- if (fv_slept) {
- uq = VLRU.prev;
- i = 0;
- continue; /* start over - may have raced. */
- }
- }
- if (tq == uq)
- break;
- }
- }
- if (!freeVCList) {
- /* none free, making one is better than a panic */
- afs_stats_cmperf.vcacheXAllocs++; /* count in case we have a leak */
- tvc = (struct vcache *)afs_osi_Alloc(sizeof(struct vcache));
-#ifdef KERNEL_HAVE_PIN
- pin((char *)tvc, sizeof(struct vcache)); /* XXX */
-#endif
-#ifdef AFS_MACH_ENV
- /* In case it still comes here we need to fill this */
- tvc->v.v_vm_info = VM_INFO_NULL;
- vm_info_init(tvc->v.v_vm_info);
- /* perhaps we should also do close_flush on non-NeXT mach systems;
- * who knows; we don't currently have the sources.
- */
-#endif /* AFS_MACH_ENV */
-#if defined(AFS_SGI_ENV)
- {
- char name[METER_NAMSZ];
- memset(tvc, 0, sizeof(struct vcache));
- tvc->v.v_number = ++afsvnumbers;
- tvc->vc_rwlockid = OSI_NO_LOCKID;
- initnsema(&tvc->vc_rwlock, 1,
- makesname(name, "vrw", tvc->v.v_number));
-#ifndef AFS_SGI53_ENV
- initnsema(&tvc->v.v_sync, 0,
- makesname(name, "vsy", tvc->v.v_number));
-#endif
-#ifndef AFS_SGI62_ENV
- initnlock(&tvc->v.v_lock,
- makesname(name, "vlk", tvc->v.v_number));
-#endif
- }
-#endif /* AFS_SGI_ENV */
- } else {
- tvc = freeVCList; /* take from free list */
- freeVCList = tvc->nextfree;
- tvc->nextfree = NULL;
- }
-#endif /* AFS_OSF_ENV */
-
-#ifdef AFS_MACH_ENV
- vm_info_ptr = tvc->v.v_vm_info;
-#endif /* AFS_MACH_ENV */
-
-#if defined(AFS_XBSD_ENV)
- if (tvc->v)
- panic("afs_NewVCache(): free vcache with vnode attached");
-#endif
-
-#if !defined(AFS_SGI_ENV) && !defined(AFS_OSF_ENV)
- memset((char *)tvc, 0, sizeof(struct vcache));
-#else
- tvc->uncred = 0;
-#endif
-
- RWLOCK_INIT(&tvc->lock, "vcache lock");
-#if defined(AFS_SUN5_ENV)
- RWLOCK_INIT(&tvc->vlock, "vcache vlock");
-#endif /* defined(AFS_SUN5_ENV) */
-
-#ifdef AFS_MACH_ENV
- tvc->v.v_vm_info = vm_info_ptr;
- tvc->v.v_vm_info->pager = MEMORY_OBJECT_NULL;
-#endif /* AFS_MACH_ENV */
-#ifdef AFS_OBSD_ENV
- AFS_GUNLOCK();
- afs_nbsd_getnewvnode(tvc); /* includes one refcount */
- AFS_GLOCK();
- lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0);
-#endif
-#ifdef AFS_FBSD_ENV
- {
- struct vnode *vp;
-
- AFS_GUNLOCK();
-#ifdef AFS_FBSD50_ENV
- if (getnewvnode(MOUNT_AFS, afs_globalVFS, afs_vnodeop_p, &vp))
-#else
- if (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &vp))
-#endif
- panic("afs getnewvnode"); /* can't happen */
- AFS_GLOCK();
- if (tvc->v != NULL) {
- /* I'd like to know if this ever happens...
- We don't drop global for the rest of this function,
- so if we do lose the race, the other thread should
- have found the same vnode and finished initializing
- the vcache entry. Is it conceivable that this vcache
- entry could be recycled during this interval? If so,
- then there probably needs to be some sort of additional
- mutual exclusion (an Embryonic flag would suffice).
- -GAW */
- printf("afs_NewVCache: lost the race\n");
- return (tvc);
- }
- tvc->v = vp;
- tvc->v->v_data = tvc;
- lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0);
- }
-#endif
- tvc->parentVnode = 0;
- tvc->mvid = NULL;
- tvc->linkData = NULL;
- tvc->cbExpires = 0;
- tvc->opens = 0;
- tvc->execsOrWriters = 0;
- tvc->flockCount = 0;
- tvc->anyAccess = 0;
- tvc->states = 0;
- tvc->last_looker = 0;
- tvc->fid = *afid;
- tvc->asynchrony = -1;
- tvc->vc_error = 0;
- afs_symhint_inval(tvc);
-#ifdef AFS_TEXT_ENV
- tvc->flushDV.low = tvc->flushDV.high = AFS_MAXDV;
-#endif
- hzero(tvc->mapDV);
- tvc->truncPos = AFS_NOTRUNC; /* don't truncate until we need to */
- hzero(tvc->m.DataVersion); /* in case we copy it into flushDV */
-#if defined(AFS_LINUX22_ENV)
-{
- struct inode *ip = AFSTOI(tvc);
- struct address_space *mapping = &ip->i_data;
-
-#if defined(AFS_LINUX26_ENV)
- inode_init_once(ip);
-#else
- sema_init(&ip->i_sem, 1);
- INIT_LIST_HEAD(&ip->i_hash);
- INIT_LIST_HEAD(&ip->i_dentry);
-#if defined(AFS_LINUX24_ENV)
- sema_init(&ip->i_zombie, 1);
- init_waitqueue_head(&ip->i_wait);
- spin_lock_init(&ip->i_data.i_shared_lock);
-#ifdef STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
- spin_lock_init(&ip->i_data.page_lock);
-#endif
- INIT_LIST_HEAD(&ip->i_data.clean_pages);
- INIT_LIST_HEAD(&ip->i_data.dirty_pages);
- INIT_LIST_HEAD(&ip->i_data.locked_pages);
- INIT_LIST_HEAD(&ip->i_dirty_buffers);
-#ifdef STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
- INIT_LIST_HEAD(&ip->i_dirty_data_buffers);
-#endif
-#ifdef STRUCT_INODE_HAS_I_DEVICES
- INIT_LIST_HEAD(&ip->i_devices);
-#endif
-#ifdef STRUCT_INODE_HAS_I_TRUNCATE_SEM
- init_rwsem(&ip->i_truncate_sem);
-#endif
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- init_rwsem(&ip->i_alloc_sem);
-#endif
-
-#else /* AFS_LINUX22_ENV */
- sema_init(&ip->i_atomic_write, 1);
- init_waitqueue(&ip->i_wait);
-#endif
-#endif
-
-#if defined(AFS_LINUX24_ENV)
- mapping->host = ip;
- ip->i_mapping = mapping;
-#ifdef STRUCT_ADDRESS_SPACE_HAS_GFP_MASK
- ip->i_data.gfp_mask = GFP_HIGHUSER;
-#endif
-#if defined(AFS_LINUX26_ENV)
- mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
-{
- extern struct backing_dev_info afs_backing_dev_info;
-
- mapping->backing_dev_info = &afs_backing_dev_info;
-}
-#endif
-#endif
-
-#if !defined(AFS_LINUX26_ENV)
- if (afs_globalVFS)
- ip->i_dev = afs_globalVFS->s_dev;
-#endif
- ip->i_sb = afs_globalVFS;
- put_inode_on_dummy_list(ip);
-}
-#endif
-
-#ifdef AFS_OSF_ENV
- /* Hold it for the LRU (should make count 2) */
- VN_HOLD(AFSTOV(tvc));
-#else /* AFS_OSF_ENV */
-#if !defined(AFS_XBSD_ENV)
- VREFCOUNT_SET(tvc, 1); /* us */
-#endif /* AFS_XBSD_ENV */
-#endif /* AFS_OSF_ENV */
-#ifdef AFS_AIX32_ENV
- LOCK_INIT(&tvc->pvmlock, "vcache pvmlock");
- tvc->vmh = tvc->segid = NULL;
- tvc->credp = NULL;
-#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
-#if defined(AFS_SUN5_ENV)
- rw_init(&tvc->rwlock, "vcache rwlock", RW_DEFAULT, NULL);
-
-#if defined(AFS_SUN55_ENV)
- /* This is required if the kaio (kernel aynchronous io)
- ** module is installed. Inside the kernel, the function
- ** check_vp( common/os/aio.c) checks to see if the kernel has
- ** to provide asynchronous io for this vnode. This
- ** function extracts the device number by following the
- ** v_data field of the vnode. If we do not set this field
- ** then the system panics. The value of the v_data field
- ** is not really important for AFS vnodes because the kernel
- ** does not do asynchronous io for regular files. Hence,
- ** for the time being, we fill up the v_data field with the
- ** vnode pointer itself. */
- tvc->v.v_data = (char *)tvc;
-#endif /* AFS_SUN55_ENV */
-#endif
- afs_BozonInit(&tvc->pvnLock, tvc);
-#endif
-
- tvc->Access = NULL;
- tvc->callback = serverp; /* to minimize chance that clear
- * request is lost */
- /* initialize vnode data, note vrefCount is v.v_count */
-#ifdef AFS_AIX_ENV
- /* Don't forget to free the gnode space */
- tvc->v.v_gnode = gnodepnt =
- (struct gnode *)osi_AllocSmallSpace(sizeof(struct gnode));
- memset((char *)gnodepnt, 0, sizeof(struct gnode));
-#endif
-#ifdef AFS_SGI64_ENV
- memset((void *)&(tvc->vc_bhv_desc), 0, sizeof(tvc->vc_bhv_desc));
- bhv_desc_init(&(tvc->vc_bhv_desc), tvc, tvc, &Afs_vnodeops);
-#ifdef AFS_SGI65_ENV
- vn_bhv_head_init(&(tvc->v.v_bh), "afsvp");
- vn_bhv_insert_initial(&(tvc->v.v_bh), &(tvc->vc_bhv_desc));
-#else
- bhv_head_init(&(tvc->v.v_bh));
- bhv_insert_initial(&(tvc->v.v_bh), &(tvc->vc_bhv_desc));
-#endif
-#ifdef AFS_SGI65_ENV
- tvc->v.v_mreg = tvc->v.v_mregb = (struct pregion *)tvc;
-#ifdef VNODE_TRACING
- tvc->v.v_trace = ktrace_alloc(VNODE_TRACE_SIZE, 0);
-#endif
- init_bitlock(&tvc->v.v_pcacheflag, VNODE_PCACHE_LOCKBIT, "afs_pcache",
- tvc->v.v_number);
- init_mutex(&tvc->v.v_filocksem, MUTEX_DEFAULT, "afsvfl", (long)tvc);
- init_mutex(&tvc->v.v_buf_lock, MUTEX_DEFAULT, "afsvnbuf", (long)tvc);
-#endif
- vnode_pcache_init(&tvc->v);
-#if defined(DEBUG) && defined(VNODE_INIT_BITLOCK)
- /* Above define is never true execpt in SGI test kernels. */
- init_bitlock(&(tvc->v.v_flag, VLOCK, "vnode", tvc->v.v_number);
-#endif
-#ifdef INTR_KTHREADS
- AFS_VN_INIT_BUF_LOCK(&(tvc->v));
-#endif
-#else
- SetAfsVnode(AFSTOV(tvc));
-#endif /* AFS_SGI64_ENV */
-#ifdef AFS_DARWIN_ENV
- tvc->v.v_ubcinfo = UBC_INFO_NULL;
- lockinit(&tvc->rwlock, PINOD, "vcache rwlock", 0, 0);
- cache_purge(AFSTOV(tvc));
- tvc->v.v_data = tvc;
- tvc->v.v_tag = VT_AFS;
- /* VLISTNONE(&tvc->v); */
- tvc->v.v_freelist.tqe_next = 0;
- tvc->v.v_freelist.tqe_prev = (struct vnode **)0xdeadb;
- /*tvc->vrefCount++; */
-#endif
- /*
- * The proper value for mvstat (for root fids) is setup by the caller.
- */
- tvc->mvstat = 0;
- if (afid->Fid.Vnode == 1 && afid->Fid.Unique == 1)
- tvc->mvstat = 2;
- if (afs_globalVFS == 0)
- osi_Panic("afs globalvfs");
- vSetVfsp(tvc, afs_globalVFS);
- vSetType(tvc, VREG);
-#ifdef AFS_AIX_ENV
- tvc->v.v_vfsnext = afs_globalVFS->vfs_vnodes; /* link off vfs */
- tvc->v.v_vfsprev = NULL;
- afs_globalVFS->vfs_vnodes = &tvc->v;
- if (tvc->v.v_vfsnext != NULL)
- tvc->v.v_vfsnext->v_vfsprev = &tvc->v;
- tvc->v.v_next = gnodepnt->gn_vnode; /*Single vnode per gnode for us! */
- gnodepnt->gn_vnode = &tvc->v;
-#endif
-#ifdef AFS_DEC_ENV
- tvc->v.g_dev = ((struct mount *)afs_globalVFS->vfs_data)->m_dev;
-#endif
-#if defined(AFS_DUX40_ENV)
- insmntque(tvc, afs_globalVFS, &afs_ubcops);
-#else
-#ifdef AFS_OSF_ENV
- /* Is this needed??? */
- insmntque(tvc, afs_globalVFS);
-#endif /* AFS_OSF_ENV */
-#endif /* AFS_DUX40_ENV */
-#if defined(AFS_SGI_ENV)
- VN_SET_DPAGES(&(tvc->v), (struct pfdat *)NULL);
- osi_Assert((tvc->v.v_flag & VINACT) == 0);
- tvc->v.v_flag = 0;
- osi_Assert(VN_GET_PGCNT(&(tvc->v)) == 0);
- osi_Assert(tvc->mapcnt == 0 && tvc->vc_locktrips == 0);
- osi_Assert(tvc->vc_rwlockid == OSI_NO_LOCKID);
- osi_Assert(tvc->v.v_filocks == NULL);
-#if !defined(AFS_SGI65_ENV)
- osi_Assert(tvc->v.v_filocksem == NULL);
-#endif
- osi_Assert(tvc->cred == NULL);
-#ifdef AFS_SGI64_ENV
- vnode_pcache_reinit(&tvc->v);
- tvc->v.v_rdev = NODEV;
-#endif
- vn_initlist((struct vnlist *)&tvc->v);
- tvc->lastr = 0;
-#endif /* AFS_SGI_ENV */
- tvc->h1.dchint = 0;
- osi_dnlc_purgedp(tvc); /* this may be overkill */
- memset((char *)&(tvc->quick), 0, sizeof(struct vtodc));
- memset((char *)&(tvc->callsort), 0, sizeof(struct afs_q));
- tvc->slocks = NULL;
- i = VCHash(afid);
-
- tvc->hnext = afs_vhashT[i];
- afs_vhashT[i] = tvc;
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("NewVCache VLRU inconsistent");
- }
- QAdd(&VLRU, &tvc->vlruq); /* put in lruq */
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("NewVCache VLRU inconsistent2");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("NewVCache VLRU inconsistent3");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("NewVCache VLRU inconsistent4");
- }
- vcachegen++;
-
- return tvc;
-
-} /*afs_NewVCache */
-
-
-/*
- * afs_FlushActiveVcaches
- *
- * Description:
- * ???
- *
- * Parameters:
- * doflocks : Do we handle flocks?
- */
-/* LOCK: afs_FlushActiveVcaches afs_xvcache N */
-void
-afs_FlushActiveVcaches(register afs_int32 doflocks)
-{
- register struct vcache *tvc;
- register int i;
- register struct conn *tc;
- register afs_int32 code;
- register struct AFS_UCRED *cred = NULL;
- struct vrequest treq, ureq;
- struct AFSVolSync tsync;
- int didCore;
- XSTATS_DECLS AFS_STATCNT(afs_FlushActiveVcaches);
- ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (doflocks && tvc->flockCount != 0) {
- /* if this entry has an flock, send a keep-alive call out */
- osi_vnhold(tvc, 0);
- ReleaseReadLock(&afs_xvcache);
- ObtainWriteLock(&tvc->lock, 51);
- do {
- afs_InitReq(&treq, afs_osi_credp);
- treq.flags |= O_NONBLOCK;
-
- tc = afs_Conn(&tvc->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_EXTENDLOCK);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_ExtendLock(tc->id,
- (struct AFSFid *)&tvc->fid.Fid,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &tvc->fid, &treq,
- AFS_STATS_FS_RPCIDX_EXTENDLOCK, SHARED_LOCK, NULL));
-
- ReleaseWriteLock(&tvc->lock);
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- }
- didCore = 0;
- if ((tvc->states & CCore) || (tvc->states & CUnlinkedDel)) {
- /*
- * Don't let it evaporate in case someone else is in
- * this code. Also, drop the afs_xvcache lock while
- * getting vcache locks.
- */
- osi_vnhold(tvc, 0);
- ReleaseReadLock(&afs_xvcache);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV)
- afs_BozonLock(&tvc->pvnLock, tvc);
-#endif
-#if defined(AFS_SGI_ENV)
- /*
- * That's because if we come in via the CUnlinkedDel bit state path we'll be have 0 refcnt
- */
- osi_Assert(VREFCOUNT(tvc) > 0);
- AFS_RWLOCK((vnode_t *) tvc, VRWLOCK_WRITE);
-#endif
- ObtainWriteLock(&tvc->lock, 52);
- if (tvc->states & CCore) {
- tvc->states &= ~CCore;
- /* XXXX Find better place-holder for cred XXXX */
- cred = (struct AFS_UCRED *)tvc->linkData;
- tvc->linkData = NULL; /* XXX */
- afs_InitReq(&ureq, cred);
- afs_Trace2(afs_iclSetp, CM_TRACE_ACTCCORE,
- ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
- tvc->execsOrWriters);
- code = afs_StoreOnLastReference(tvc, &ureq);
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- hzero(tvc->flushDV);
- osi_FlushText(tvc);
- didCore = 1;
- if (code && code != VNOVNODE) {
- afs_StoreWarn(code, tvc->fid.Fid.Volume,
- /* /dev/console */ 1);
- }
- } else if (tvc->states & CUnlinkedDel) {
- /*
- * Ignore errors
- */
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) tvc, VRWLOCK_WRITE);
-#endif
- afs_remunlink(tvc, 0);
-#if defined(AFS_SGI_ENV)
- AFS_RWLOCK((vnode_t *) tvc, VRWLOCK_WRITE);
-#endif
- } else {
- /* lost (or won, perhaps) the race condition */
- ReleaseWriteLock(&tvc->lock);
-#if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV)
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
- }
-#if defined(AFS_SGI_ENV)
- AFS_RWUNLOCK((vnode_t *) tvc, VRWLOCK_WRITE);
-#endif
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- if (didCore) {
-#ifdef AFS_GFS_ENV
- VREFCOUNT_DEC(tvc);
-#else
- AFS_RELE(AFSTOV(tvc));
-#endif
- /* Matches write code setting CCore flag */
- crfree(cred);
- }
- }
-#ifdef AFS_DARWIN_ENV
- if (VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
- if (tvc->opens)
- panic("flushactive open, hasubc, but refcnt 1");
- osi_VM_TryReclaim(tvc, 0);
- }
-#endif
- }
- }
- ReleaseReadLock(&afs_xvcache);
-}
-
-
-/*
- * afs_VerifyVCache
- *
- * Description:
- * Make sure a cache entry is up-to-date status-wise.
- *
- * NOTE: everywhere that calls this can potentially be sped up
- * by checking CStatd first, and avoiding doing the InitReq
- * if this is up-to-date.
- *
- * Anymore, the only places that call this KNOW already that the
- * vcache is not up-to-date, so we don't screw around.
- *
- * Parameters:
- * avc : Ptr to vcache entry to verify.
- * areq : ???
- */
-
-int
-afs_VerifyVCache2(struct vcache *avc, struct vrequest *areq)
-{
- register struct vcache *tvc;
-
- AFS_STATCNT(afs_VerifyVCache);
-
-#if defined(AFS_OSF_ENV)
- ObtainReadLock(&avc->lock);
- if (afs_IsWired(avc)) {
- ReleaseReadLock(&avc->lock);
- return 0;
- }
- ReleaseReadLock(&avc->lock);
-#endif /* AFS_OSF_ENV */
- /* otherwise we must fetch the status info */
-
- ObtainWriteLock(&avc->lock, 53);
- if (avc->states & CStatd) {
- ReleaseWriteLock(&avc->lock);
- return 0;
- }
- ObtainWriteLock(&afs_xcbhash, 461);
- avc->states &= ~(CStatd | CUnique);
- avc->callback = NULL;
- afs_DequeueCallback(avc);
- ReleaseWriteLock(&afs_xcbhash);
- ReleaseWriteLock(&avc->lock);
-
- /* since we've been called back, or the callback has expired,
- * it's possible that the contents of this directory, or this
- * file's name have changed, thus invalidating the dnlc contents.
- */
- if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc);
- else
- osi_dnlc_purgevp(avc);
-
- /* fetch the status info */
- tvc = afs_GetVCache(&avc->fid, areq, NULL, avc);
- if (!tvc)
- return ENOENT;
- /* Put it back; caller has already incremented vrefCount */
- afs_PutVCache(tvc);
- return 0;
-
-} /*afs_VerifyVCache */
-
-
-/*
- * afs_SimpleVStat
- *
- * Description:
- * Simple copy of stat info into cache.
- *
- * Parameters:
- * avc : Ptr to vcache entry involved.
- * astat : Ptr to stat info to copy.
- *
- * Environment:
- * Nothing interesting.
- *
- * Callers: as of 1992-04-29, only called by WriteVCache
- */
-static void
-afs_SimpleVStat(register struct vcache *avc,
- register struct AFSFetchStatus *astat, struct vrequest *areq)
-{
- afs_size_t length;
- AFS_STATCNT(afs_SimpleVStat);
-
-#ifdef AFS_SGI_ENV
- if ((avc->execsOrWriters <= 0) && !afs_DirtyPages(avc)
- && !AFS_VN_MAPPED((vnode_t *) avc)) {
-#else
- if ((avc->execsOrWriters <= 0) && !afs_DirtyPages(avc)) {
-#endif
-#ifdef AFS_64BIT_CLIENT
- FillInt64(length, astat->Length_hi, astat->Length);
-#else /* AFS_64BIT_CLIENT */
- length = astat->Length;
-#endif /* AFS_64BIT_CLIENT */
-#if defined(AFS_SGI_ENV)
- osi_Assert((valusema(&avc->vc_rwlock) <= 0)
- && (OSI_GET_LOCKID() == avc->vc_rwlockid));
- if (length < avc->m.Length) {
- vnode_t *vp = (vnode_t *) avc;
-
- osi_Assert(WriteLocked(&avc->lock));
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- PTOSSVP(vp, (off_t) length, (off_t) MAXLONG);
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock, 67);
- }
-#endif
- /* if writing the file, don't fetch over this value */
- afs_Trace3(afs_iclSetp, CM_TRACE_SIMPLEVSTAT, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(length));
- avc->m.Length = length;
- avc->m.Date = astat->ClientModTime;
- }
- avc->m.Owner = astat->Owner;
- avc->m.Group = astat->Group;
- avc->m.Mode = astat->UnixModeBits;
- if (vType(avc) == VREG) {
- avc->m.Mode |= S_IFREG;
- } else if (vType(avc) == VDIR) {
- avc->m.Mode |= S_IFDIR;
- } else if (vType(avc) == VLNK) {
- avc->m.Mode |= S_IFLNK;
- if ((avc->m.Mode & 0111) == 0)
- avc->mvstat = 1;
- }
- if (avc->states & CForeign) {
- struct axscache *ac;
- avc->anyAccess = astat->AnonymousAccess;
-#ifdef badidea
- if ((astat->CallerAccess & ~astat->AnonymousAccess))
- /* USED TO SAY :
- * Caller has at least one bit not covered by anonymous, and
- * thus may have interesting rights.
- *
- * HOWEVER, this is a really bad idea, because any access query
- * for bits which aren't covered by anonymous, on behalf of a user
- * who doesn't have any special rights, will result in an answer of
- * the form "I don't know, lets make a FetchStatus RPC and find out!"
- * It's an especially bad idea under Ultrix, since (due to the lack of
- * a proper access() call) it must perform several afs_access() calls
- * in order to create magic mode bits that vary according to who makes
- * the call. In other words, _every_ stat() generates a test for
- * writeability...
- */
-#endif /* badidea */
- if (avc->Access && (ac = afs_FindAxs(avc->Access, areq->uid)))
- ac->axess = astat->CallerAccess;
- else /* not found, add a new one if possible */
- afs_AddAxs(avc->Access, areq->uid, astat->CallerAccess);
- }
-
-
-} /*afs_SimpleVStat */
-
-
-/*
- * afs_WriteVCache
- *
- * Description:
- * Store the status info *only* back to the server for a
- * fid/vrequest.
- *
- * Parameters:
- * avc : Ptr to the vcache entry.
- * astatus : Ptr to the status info to store.
- * areq : Ptr to the associated vrequest.
- *
- * Environment:
- * Must be called with a shared lock held on the vnode.
- */
-
-int
-afs_WriteVCache(register struct vcache *avc,
- register struct AFSStoreStatus *astatus,
- struct vrequest *areq)
-{
- afs_int32 code;
- struct conn *tc;
- struct AFSFetchStatus OutStatus;
- struct AFSVolSync tsync;
- XSTATS_DECLS AFS_STATCNT(afs_WriteVCache);
- afs_Trace2(afs_iclSetp, CM_TRACE_WVCACHE, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
-
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STORESTATUS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_StoreStatus(tc->id, (struct AFSFid *)&avc->fid.Fid,
- astatus, &OutStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STORESTATUS,
- SHARED_LOCK, NULL));
-
- UpgradeSToWLock(&avc->lock, 20);
- if (code == 0) {
- /* success, do the changes locally */
- afs_SimpleVStat(avc, &OutStatus, areq);
- /*
- * Update the date, too. SimpleVStat didn't do this, since
- * it thought we were doing this after fetching new status
- * over a file being written.
- */
- avc->m.Date = OutStatus.ClientModTime;
- } else {
- /* failure, set up to check with server next time */
- ObtainWriteLock(&afs_xcbhash, 462);
- afs_DequeueCallback(avc);
- avc->states &= ~(CStatd | CUnique); /* turn off stat valid flag */
- ReleaseWriteLock(&afs_xcbhash);
- if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
- }
- ConvertWToSLock(&avc->lock);
- return code;
-
-} /*afs_WriteVCache */
-
-/*
- * afs_ProcessFS
- *
- * Description:
- * Copy astat block into vcache info
- *
- * Parameters:
- * avc : Ptr to vcache entry.
- * astat : Ptr to stat block to copy in.
- * areq : Ptr to associated request.
- *
- * Environment:
- * Must be called under a write lock
- *
- * Note: this code may get dataversion and length out of sync if the file has
- * been modified. This is less than ideal. I haven't thought about
- * it sufficiently to be certain that it is adequate.
- */
-void
-afs_ProcessFS(register struct vcache *avc,
- register struct AFSFetchStatus *astat, struct vrequest *areq)
-{
- afs_size_t length;
- AFS_STATCNT(afs_ProcessFS);
-
-#ifdef AFS_64BIT_CLIENT
- FillInt64(length, astat->Length_hi, astat->Length);
-#else /* AFS_64BIT_CLIENT */
- length = astat->Length;
-#endif /* AFS_64BIT_CLIENT */
- /* WARNING: afs_DoBulkStat uses the Length field to store a sequence
- * number for each bulk status request. Under no circumstances
- * should afs_DoBulkStat store a sequence number if the new
- * length will be ignored when afs_ProcessFS is called with
- * new stats. If you change the following conditional then you
- * also need to change the conditional in afs_DoBulkStat. */
-#ifdef AFS_SGI_ENV
- if ((avc->execsOrWriters <= 0) && !afs_DirtyPages(avc)
- && !AFS_VN_MAPPED((vnode_t *) avc)) {
-#else
- if ((avc->execsOrWriters <= 0) && !afs_DirtyPages(avc)) {
-#endif
- /* if we're writing or mapping this file, don't fetch over these
- * values.
- */
- afs_Trace3(afs_iclSetp, CM_TRACE_PROCESSFS, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(length));
- avc->m.Length = length;
- avc->m.Date = astat->ClientModTime;
- }
- hset64(avc->m.DataVersion, astat->dataVersionHigh, astat->DataVersion);
- avc->m.Owner = astat->Owner;
- avc->m.Mode = astat->UnixModeBits;
- avc->m.Group = astat->Group;
- avc->m.LinkCount = astat->LinkCount;
- if (astat->FileType == File) {
- vSetType(avc, VREG);
- avc->m.Mode |= S_IFREG;
- } else if (astat->FileType == Directory) {
- vSetType(avc, VDIR);
- avc->m.Mode |= S_IFDIR;
- } else if (astat->FileType == SymbolicLink) {
- if (afs_fakestat_enable && (avc->m.Mode & 0111) == 0) {
- vSetType(avc, VDIR);
- avc->m.Mode |= S_IFDIR;
- } else {
- vSetType(avc, VLNK);
- avc->m.Mode |= S_IFLNK;
- }
- if ((avc->m.Mode & 0111) == 0) {
- avc->mvstat = 1;
- }
- }
- avc->anyAccess = astat->AnonymousAccess;
-#ifdef badidea
- if ((astat->CallerAccess & ~astat->AnonymousAccess))
- /* USED TO SAY :
- * Caller has at least one bit not covered by anonymous, and
- * thus may have interesting rights.
- *
- * HOWEVER, this is a really bad idea, because any access query
- * for bits which aren't covered by anonymous, on behalf of a user
- * who doesn't have any special rights, will result in an answer of
- * the form "I don't know, lets make a FetchStatus RPC and find out!"
- * It's an especially bad idea under Ultrix, since (due to the lack of
- * a proper access() call) it must perform several afs_access() calls
- * in order to create magic mode bits that vary according to who makes
- * the call. In other words, _every_ stat() generates a test for
- * writeability...
- */
-#endif /* badidea */
- {
- struct axscache *ac;
- if (avc->Access && (ac = afs_FindAxs(avc->Access, areq->uid)))
- ac->axess = astat->CallerAccess;
- else /* not found, add a new one if possible */
- afs_AddAxs(avc->Access, areq->uid, astat->CallerAccess);
- }
-#ifdef AFS_LINUX22_ENV
- vcache2inode(avc); /* Set the inode attr cache */
-#endif
-#ifdef AFS_DARWIN_ENV
- osi_VM_Setup(avc, 1);
-#endif
-
-} /*afs_ProcessFS */
-
-
-int
-afs_RemoteLookup(register struct VenusFid *afid, struct vrequest *areq,
- char *name, struct VenusFid *nfid,
- struct AFSFetchStatus *OutStatusp,
- struct AFSCallBack *CallBackp, struct server **serverp,
- struct AFSVolSync *tsyncp)
-{
- afs_int32 code;
- afs_uint32 start;
- register struct conn *tc;
- struct AFSFetchStatus OutDirStatus;
- XSTATS_DECLS if (!name)
- name = ""; /* XXX */
- do {
- tc = afs_Conn(afid, areq, SHARED_LOCK);
- if (tc) {
- if (serverp)
- *serverp = tc->srvr->server;
- start = osi_Time();
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_XLOOKUP);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_Lookup(tc->id, (struct AFSFid *)&afid->Fid, name,
- (struct AFSFid *)&nfid->Fid, OutStatusp,
- &OutDirStatus, CallBackp, tsyncp);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, afid, areq, AFS_STATS_FS_RPCIDX_XLOOKUP, SHARED_LOCK,
- NULL));
-
- return code;
-}
-
-
-/*
- * afs_GetVCache
- *
- * Description:
- * Given a file id and a vrequest structure, fetch the status
- * information associated with the file.
- *
- * Parameters:
- * afid : File ID.
- * areq : Ptr to associated vrequest structure, specifying the
- * user whose authentication tokens will be used.
- * avc : caller may already have a vcache for this file, which is
- * already held.
- *
- * Environment:
- * The cache entry is returned with an increased vrefCount field.
- * The entry must be discarded by calling afs_PutVCache when you
- * are through using the pointer to the cache entry.
- *
- * You should not hold any locks when calling this function, except
- * locks on other vcache entries. If you lock more than one vcache
- * entry simultaneously, you should lock them in this order:
- *
- * 1. Lock all files first, then directories.
- * 2. Within a particular type, lock entries in Fid.Vnode order.
- *
- * This locking hierarchy is convenient because it allows locking
- * of a parent dir cache entry, given a file (to check its access
- * control list). It also allows renames to be handled easily by
- * locking directories in a constant order.
- * NB. NewVCache -> FlushVCache presently (4/10/95) drops the xvcache lock.
- */
- /* might have a vcache structure already, which must
- * already be held by the caller */
-
-struct vcache *
-afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq,
- afs_int32 * cached, struct vcache *avc)
-{
-
- afs_int32 code, newvcache = 0;
- register struct vcache *tvc;
- struct volume *tvp;
- afs_int32 retry;
-
- AFS_STATCNT(afs_GetVCache);
-
- if (cached)
- *cached = 0; /* Init just in case */
-
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- loop:
-#endif
-
- ObtainSharedLock(&afs_xvcache, 5);
-
- tvc = afs_FindVCache(afid, &retry, DO_STATS | DO_VLRU);
- if (tvc && retry) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- ReleaseSharedLock(&afs_xvcache);
- spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
- goto loop;
-#endif
- }
-
- if (tvc) {
- if (cached)
- *cached = 1;
- if (tvc->states & CStatd) {
- ReleaseSharedLock(&afs_xvcache);
- return tvc;
- }
- } else {
- UpgradeSToWLock(&afs_xvcache, 21);
-
- /* no cache entry, better grab one */
- tvc = afs_NewVCache(afid, NULL);
- newvcache = 1;
-
- ConvertWToSLock(&afs_xvcache);
- afs_stats_cmperf.vcacheMisses++;
- }
-
- ReleaseSharedLock(&afs_xvcache);
-
- ObtainWriteLock(&tvc->lock, 54);
-
- if (tvc->states & CStatd) {
-#ifdef AFS_LINUX22_ENV
- vcache2inode(tvc);
-#endif
- ReleaseWriteLock(&tvc->lock);
-#ifdef AFS_DARWIN_ENV
- osi_VM_Setup(tvc, 0);
-#endif
- return tvc;
- }
-#if defined(AFS_OSF_ENV)
- if (afs_IsWired(tvc)) {
- ReleaseWriteLock(&tvc->lock);
- return tvc;
- }
-#endif /* AFS_OSF_ENV */
-#ifdef AFS_OBSD_ENV
- VOP_LOCK(AFSTOV(tvc), LK_EXCLUSIVE | LK_RETRY, curproc);
- uvm_vnp_uncache(AFSTOV(tvc));
- VOP_UNLOCK(AFSTOV(tvc), 0, curproc);
-#endif
-#ifdef AFS_FBSD_ENV
- /*
- * XXX - I really don't like this. Should try to understand better.
- * It seems that sometimes, when we get called, we already hold the
- * lock on the vnode (e.g., from afs_getattr via afs_VerifyVCache).
- * We can't drop the vnode lock, because that could result in a race.
- * Sometimes, though, we get here and don't hold the vnode lock.
- * I hate code paths that sometimes hold locks and sometimes don't.
- * In any event, the dodge we use here is to check whether the vnode
- * is locked, and if it isn't, then we gain and drop it around the call
- * to vinvalbuf; otherwise, we leave it alone.
- */
- {
- struct vnode *vp;
- int iheldthelock;
-
- vp = AFSTOV(tvc);
-#ifdef AFS_FBSD50_ENV
- iheldthelock = VOP_ISLOCKED(vp, curthread);
- if (!iheldthelock)
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
- vinvalbuf(vp, V_SAVE, osi_curcred(), curthread, PINOD, 0);
- if (!iheldthelock)
- VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
-#else
- iheldthelock = VOP_ISLOCKED(vp, curproc);
- if (!iheldthelock)
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
- vinvalbuf(vp, V_SAVE, osi_curcred(), curproc, PINOD, 0);
- if (!iheldthelock)
- VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc);
-#endif
- }
-#endif
-
- ObtainWriteLock(&afs_xcbhash, 464);
- tvc->states &= ~CUnique;
- tvc->callback = 0;
- afs_DequeueCallback(tvc);
- ReleaseWriteLock(&afs_xcbhash);
-
- /* It is always appropriate to throw away all the access rights? */
- afs_FreeAllAxs(&(tvc->Access));
- tvp = afs_GetVolume(afid, areq, READ_LOCK); /* copy useful per-volume info */
- if (tvp) {
- if ((tvp->states & VForeign)) {
- if (newvcache)
- tvc->states |= CForeign;
- if (newvcache && (tvp->rootVnode == afid->Fid.Vnode)
- && (tvp->rootUnique == afid->Fid.Unique)) {
- tvc->mvstat = 2;
- }
- }
- if (tvp->states & VRO)
- tvc->states |= CRO;
- if (tvp->states & VBackup)
- tvc->states |= CBackup;
- /* now copy ".." entry back out of volume structure, if necessary */
- if (tvc->mvstat == 2 && tvp->dotdot.Fid.Volume != 0) {
- if (!tvc->mvid)
- tvc->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- *tvc->mvid = tvp->dotdot;
- }
- afs_PutVolume(tvp, READ_LOCK);
- }
-
- /* stat the file */
- afs_RemoveVCB(afid);
- {
- struct AFSFetchStatus OutStatus;
-
- if (afs_DynrootNewVnode(tvc, &OutStatus)) {
- afs_ProcessFS(tvc, &OutStatus, areq);
- tvc->states |= CStatd | CUnique;
- code = 0;
- } else {
- code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
- }
- }
-
- if (code) {
- ReleaseWriteLock(&tvc->lock);
-
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- ReleaseReadLock(&afs_xvcache);
- return NULL;
- }
-
- ReleaseWriteLock(&tvc->lock);
- return tvc;
-
-} /*afs_GetVCache */
-
-
-
-struct vcache *
-afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
- afs_int32 * cached, struct vcache *adp, char *aname)
-{
- afs_int32 code, now, newvcache = 0;
- struct VenusFid nfid;
- register struct vcache *tvc;
- struct volume *tvp;
- struct AFSFetchStatus OutStatus;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- struct server *serverp = 0;
- afs_int32 origCBs;
- afs_int32 retry;
-
- AFS_STATCNT(afs_GetVCache);
- if (cached)
- *cached = 0; /* Init just in case */
-
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- loop1:
-#endif
-
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(afid, &retry, DO_STATS /* no vlru */ );
-
- if (tvc) {
- ReleaseReadLock(&afs_xvcache);
- if (retry) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
- goto loop1;
-#endif
- }
- ObtainReadLock(&tvc->lock);
-
- if (tvc->states & CStatd) {
- if (cached) {
- *cached = 1;
- }
- ReleaseReadLock(&tvc->lock);
- return tvc;
- }
- tvc->states &= ~CUnique;
-
- ReleaseReadLock(&tvc->lock);
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- }
- /* if (tvc) */
- ReleaseReadLock(&afs_xvcache);
-
- /* lookup the file */
- nfid = *afid;
- now = osi_Time();
- origCBs = afs_allCBs; /* if anything changes, we don't have a cb */
- code =
- afs_RemoteLookup(&adp->fid, areq, aname, &nfid, &OutStatus, &CallBack,
- &serverp, &tsync);
-
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- loop2:
-#endif
-
- ObtainSharedLock(&afs_xvcache, 6);
- tvc = afs_FindVCache(&nfid, &retry, DO_VLRU /* no xstats now */ );
- if (tvc && retry) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- ReleaseSharedLock(&afs_xvcache);
- spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
- goto loop2;
-#endif
- }
-
- if (!tvc) {
- /* no cache entry, better grab one */
- UpgradeSToWLock(&afs_xvcache, 22);
- tvc = afs_NewVCache(&nfid, serverp);
- newvcache = 1;
- ConvertWToSLock(&afs_xvcache);
- }
-
- ReleaseSharedLock(&afs_xvcache);
- ObtainWriteLock(&tvc->lock, 55);
-
- /* It is always appropriate to throw away all the access rights? */
- afs_FreeAllAxs(&(tvc->Access));
- tvp = afs_GetVolume(afid, areq, READ_LOCK); /* copy useful per-vol info */
- if (tvp) {
- if ((tvp->states & VForeign)) {
- if (newvcache)
- tvc->states |= CForeign;
- if (newvcache && (tvp->rootVnode == afid->Fid.Vnode)
- && (tvp->rootUnique == afid->Fid.Unique))
- tvc->mvstat = 2;
- }
- if (tvp->states & VRO)
- tvc->states |= CRO;
- if (tvp->states & VBackup)
- tvc->states |= CBackup;
- /* now copy ".." entry back out of volume structure, if necessary */
- if (tvc->mvstat == 2 && tvp->dotdot.Fid.Volume != 0) {
- if (!tvc->mvid)
- tvc->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- *tvc->mvid = tvp->dotdot;
- }
- }
-
- if (code) {
- ObtainWriteLock(&afs_xcbhash, 465);
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- if (tvp)
- afs_PutVolume(tvp, READ_LOCK);
- ReleaseWriteLock(&tvc->lock);
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- ReleaseReadLock(&afs_xvcache);
- return NULL;
- }
-
- ObtainWriteLock(&afs_xcbhash, 466);
- if (origCBs == afs_allCBs) {
- if (CallBack.ExpirationTime) {
- tvc->callback = serverp;
- tvc->cbExpires = CallBack.ExpirationTime + now;
- tvc->states |= CStatd | CUnique;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), tvp);
- } else if (tvc->states & CRO) {
- /* adapt gives us an hour. */
- tvc->cbExpires = 3600 + osi_Time();
- /*XXX*/ tvc->states |= CStatd | CUnique;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(3600), tvp);
- } else {
- tvc->callback = NULL;
- afs_DequeueCallback(tvc);
- tvc->states &= ~(CStatd | CUnique);
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- }
- } else {
- afs_DequeueCallback(tvc);
- tvc->states &= ~CStatd;
- tvc->states &= ~CUnique;
- tvc->callback = NULL;
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- }
- ReleaseWriteLock(&afs_xcbhash);
- if (tvp)
- afs_PutVolume(tvp, READ_LOCK);
- afs_ProcessFS(tvc, &OutStatus, areq);
-
- ReleaseWriteLock(&tvc->lock);
- return tvc;
-
-}
-
-struct vcache *
-afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq,
- afs_int32 * cached, struct volume *tvolp)
-{
- afs_int32 code = 0, i, newvcache = 0, haveStatus = 0;
- afs_int32 getNewFid = 0;
- afs_uint32 start;
- struct VenusFid nfid;
- register struct vcache *tvc;
- struct server *serverp = 0;
- struct AFSFetchStatus OutStatus;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- int origCBs = 0;
-
- start = osi_Time();
-
- newmtpt:
- if (!tvolp->rootVnode || getNewFid) {
- struct VenusFid tfid;
-
- tfid = *afid;
- tfid.Fid.Vnode = 0; /* Means get rootfid of volume */
- origCBs = afs_allCBs; /* ignore InitCallBackState */
- code =
- afs_RemoteLookup(&tfid, areq, NULL, &nfid, &OutStatus, &CallBack,
- &serverp, &tsync);
- if (code) {
- return NULL;
- }
-/* ReleaseReadLock(&tvolp->lock); */
- ObtainWriteLock(&tvolp->lock, 56);
- tvolp->rootVnode = afid->Fid.Vnode = nfid.Fid.Vnode;
- tvolp->rootUnique = afid->Fid.Unique = nfid.Fid.Unique;
- ReleaseWriteLock(&tvolp->lock);
-/* ObtainReadLock(&tvolp->lock);*/
- haveStatus = 1;
- } else {
- afid->Fid.Vnode = tvolp->rootVnode;
- afid->Fid.Unique = tvolp->rootUnique;
- }
-
- ObtainSharedLock(&afs_xvcache, 7);
- i = VCHash(afid);
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (!FidCmp(&(tvc->fid), afid)) {
-#ifdef AFS_OSF_ENV
- /* Grab this vnode, possibly reactivating from the free list */
- /* for the present (95.05.25) everything on the hash table is
- * definitively NOT in the free list -- at least until afs_reclaim
- * can be safely implemented */
- int vg;
- AFS_GUNLOCK();
- vg = vget(AFSTOV(tvc)); /* this bumps ref count */
- AFS_GLOCK();
- if (vg)
- continue;
-#endif /* AFS_OSF_ENV */
- break;
- }
- }
-
- if (!haveStatus && (!tvc || !(tvc->states & CStatd))) {
- /* Mount point no longer stat'd or unknown. FID may have changed. */
-#ifdef AFS_OSF_ENV
- if (tvc)
- AFS_RELE(AFSTOV(tvc));
-#endif
- tvc = NULL;
- getNewFid = 1;
- ReleaseSharedLock(&afs_xvcache);
- goto newmtpt;
- }
-
- if (!tvc) {
- UpgradeSToWLock(&afs_xvcache, 23);
- /* no cache entry, better grab one */
- tvc = afs_NewVCache(afid, NULL);
- newvcache = 1;
- afs_stats_cmperf.vcacheMisses++;
- } else {
- if (cached)
- *cached = 1;
- afs_stats_cmperf.vcacheHits++;
-#ifdef AFS_OSF_ENV
- /* we already bumped the ref count in the for loop above */
-#else /* AFS_OSF_ENV */
- osi_vnhold(tvc, 0);
-#endif
- UpgradeSToWLock(&afs_xvcache, 24);
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("GRVC VLRU inconsistent0");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("GRVC VLRU inconsistent1");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("GRVC VLRU inconsistent2");
- }
- QRemove(&tvc->vlruq); /* move to lruq head */
- QAdd(&VLRU, &tvc->vlruq);
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("GRVC VLRU inconsistent3");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("GRVC VLRU inconsistent4");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("GRVC VLRU inconsistent5");
- }
- vcachegen++;
- }
-
- ReleaseWriteLock(&afs_xvcache);
-
- if (tvc->states & CStatd) {
- return tvc;
- } else {
-
- ObtainReadLock(&tvc->lock);
- tvc->states &= ~CUnique;
- tvc->callback = NULL; /* redundant, perhaps */
- ReleaseReadLock(&tvc->lock);
- }
-
- ObtainWriteLock(&tvc->lock, 57);
-
- /* It is always appropriate to throw away all the access rights? */
- afs_FreeAllAxs(&(tvc->Access));
-
- if (newvcache)
- tvc->states |= CForeign;
- if (tvolp->states & VRO)
- tvc->states |= CRO;
- if (tvolp->states & VBackup)
- tvc->states |= CBackup;
- /* now copy ".." entry back out of volume structure, if necessary */
- if (newvcache && (tvolp->rootVnode == afid->Fid.Vnode)
- && (tvolp->rootUnique == afid->Fid.Unique)) {
- tvc->mvstat = 2;
- }
- if (tvc->mvstat == 2 && tvolp->dotdot.Fid.Volume != 0) {
- if (!tvc->mvid)
- tvc->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- *tvc->mvid = tvolp->dotdot;
- }
-
- /* stat the file */
- afs_RemoveVCB(afid);
-
- if (!haveStatus) {
- struct VenusFid tfid;
-
- tfid = *afid;
- tfid.Fid.Vnode = 0; /* Means get rootfid of volume */
- origCBs = afs_allCBs; /* ignore InitCallBackState */
- code =
- afs_RemoteLookup(&tfid, areq, NULL, &nfid, &OutStatus, &CallBack,
- &serverp, &tsync);
- }
-
- if (code) {
- ObtainWriteLock(&afs_xcbhash, 467);
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- ReleaseWriteLock(&tvc->lock);
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(tvc);
- ReleaseReadLock(&afs_xvcache);
- return NULL;
- }
-
- ObtainWriteLock(&afs_xcbhash, 468);
- if (origCBs == afs_allCBs) {
- tvc->states |= CTruth;
- tvc->callback = serverp;
- if (CallBack.ExpirationTime != 0) {
- tvc->cbExpires = CallBack.ExpirationTime + start;
- tvc->states |= CStatd;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), tvolp);
- } else if (tvc->states & CRO) {
- /* adapt gives us an hour. */
- tvc->cbExpires = 3600 + osi_Time();
- /*XXX*/ tvc->states |= CStatd;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(3600), tvolp);
- }
- } else {
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->states &= ~(CStatd | CUnique);
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- }
- ReleaseWriteLock(&afs_xcbhash);
- afs_ProcessFS(tvc, &OutStatus, areq);
-
- ReleaseWriteLock(&tvc->lock);
- return tvc;
-}
-
-
-
-/*
- * must be called with avc write-locked
- * don't absolutely have to invalidate the hint unless the dv has
- * changed, but be sure to get it right else there will be consistency bugs.
- */
-afs_int32
-afs_FetchStatus(struct vcache * avc, struct VenusFid * afid,
- struct vrequest * areq, struct AFSFetchStatus * Outsp)
-{
- int code;
- afs_uint32 start = 0;
- register struct conn *tc;
- struct AFSCallBack CallBack;
- struct AFSVolSync tsync;
- struct volume *volp;
- XSTATS_DECLS
- do {
- tc = afs_Conn(afid, areq, SHARED_LOCK);
- avc->quick.stamp = 0;
- avc->h1.dchint = NULL; /* invalidate hints */
- if (tc) {
- avc->callback = tc->srvr->server;
- start = osi_Time();
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_FetchStatus(tc->id, (struct AFSFid *)&afid->Fid, Outsp,
- &CallBack, &tsync);
- RX_AFS_GLOCK();
-
- XSTATS_END_TIME;
-
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, afid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
- SHARED_LOCK, NULL));
-
- if (!code) {
- afs_ProcessFS(avc, Outsp, areq);
- volp = afs_GetVolume(afid, areq, READ_LOCK);
- ObtainWriteLock(&afs_xcbhash, 469);
- avc->states |= CTruth;
- if (avc->callback /* check for race */ ) {
- if (CallBack.ExpirationTime != 0) {
- avc->cbExpires = CallBack.ExpirationTime + start;
- avc->states |= CStatd;
- avc->states &= ~CBulkFetching;
- afs_QueueCallback(avc, CBHash(CallBack.ExpirationTime), volp);
- } else if (avc->states & CRO) { /* ordinary callback on a read-only volume -- AFS 3.2 style */
- avc->cbExpires = 3600 + start;
- avc->states |= CStatd;
- avc->states &= ~CBulkFetching;
- afs_QueueCallback(avc, CBHash(3600), volp);
- } else {
- afs_DequeueCallback(avc);
- avc->callback = NULL;
- avc->states &= ~(CStatd | CUnique);
- if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
- }
- } else {
- afs_DequeueCallback(avc);
- avc->callback = NULL;
- avc->states &= ~(CStatd | CUnique);
- if ((avc->states & CForeign) || (avc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
- }
- ReleaseWriteLock(&afs_xcbhash);
- if (volp)
- afs_PutVolume(volp, READ_LOCK);
- } else {
- /* used to undo the local callback, but that's too extreme.
- * There are plenty of good reasons that fetchstatus might return
- * an error, such as EPERM. If we have the vnode cached, statd,
- * with callback, might as well keep track of the fact that we
- * don't have access...
- */
- if (code == EPERM || code == EACCES) {
- struct axscache *ac;
- if (avc->Access && (ac = afs_FindAxs(avc->Access, areq->uid)))
- ac->axess = 0;
- else /* not found, add a new one if possible */
- afs_AddAxs(avc->Access, areq->uid, 0);
- }
- }
- return code;
-}
-
-#if 0
-/*
- * afs_StuffVcache
- *
- * Description:
- * Stuff some information into the vcache for the given file.
- *
- * Parameters:
- * afid : File in question.
- * OutStatus : Fetch status on the file.
- * CallBack : Callback info.
- * tc : RPC connection involved.
- * areq : vrequest involved.
- *
- * Environment:
- * Nothing interesting.
- */
-void
-afs_StuffVcache(register struct VenusFid *afid,
- struct AFSFetchStatus *OutStatus,
- struct AFSCallBack *CallBack, register struct conn *tc,
- struct vrequest *areq)
-{
- register afs_int32 code, i, newvcache = 0;
- register struct vcache *tvc;
- struct AFSVolSync tsync;
- struct volume *tvp;
- struct axscache *ac;
- afs_int32 retry;
-
- AFS_STATCNT(afs_StuffVcache);
-#ifdef IFS_VCACHECOUNT
- ifs_gvcachecall++;
-#endif
-
- loop:
- ObtainSharedLock(&afs_xvcache, 8);
-
- tvc = afs_FindVCache(afid, &retry, DO_VLRU /* no stats */ );
- if (tvc && retry) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- ReleaseSharedLock(&afs_xvcache);
- spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
- goto loop;
-#endif
- }
-
- if (!tvc) {
- /* no cache entry, better grab one */
- UpgradeSToWLock(&afs_xvcache, 25);
- tvc = afs_NewVCache(afid, NULL);
- newvcache = 1;
- ConvertWToSLock(&afs_xvcache);
- }
-
- ReleaseSharedLock(&afs_xvcache);
- ObtainWriteLock(&tvc->lock, 58);
-
- tvc->states &= ~CStatd;
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
-
- /* Is it always appropriate to throw away all the access rights? */
- afs_FreeAllAxs(&(tvc->Access));
-
- /*Copy useful per-volume info */
- tvp = afs_GetVolume(afid, areq, READ_LOCK);
- if (tvp) {
- if (newvcache && (tvp->states & VForeign))
- tvc->states |= CForeign;
- if (tvp->states & VRO)
- tvc->states |= CRO;
- if (tvp->states & VBackup)
- tvc->states |= CBackup;
- /*
- * Now, copy ".." entry back out of volume structure, if
- * necessary
- */
- if (tvc->mvstat == 2 && tvp->dotdot.Fid.Volume != 0) {
- if (!tvc->mvid)
- tvc->mvid = (struct VenusFid *)
- osi_AllocSmallSpace(sizeof(struct VenusFid));
- *tvc->mvid = tvp->dotdot;
- }
- }
- /* store the stat on the file */
- afs_RemoveVCB(afid);
- afs_ProcessFS(tvc, OutStatus, areq);
- tvc->callback = tc->srvr->server;
-
- /* we use osi_Time twice below. Ideally, we would use the time at which
- * the FetchStatus call began, instead, but we don't have it here. So we
- * make do with "now". In the CRO case, it doesn't really matter. In
- * the other case, we hope that the difference between "now" and when the
- * call actually began execution on the server won't be larger than the
- * padding which the server keeps. Subtract 1 second anyway, to be on
- * the safe side. Can't subtract more because we don't know how big
- * ExpirationTime is. Possible consistency problems may arise if the call
- * timeout period becomes longer than the server's expiration padding. */
- ObtainWriteLock(&afs_xcbhash, 470);
- if (CallBack->ExpirationTime != 0) {
- tvc->cbExpires = CallBack->ExpirationTime + osi_Time() - 1;
- tvc->states |= CStatd;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(CallBack->ExpirationTime), tvp);
- } else if (tvc->states & CRO) {
- /* old-fashioned AFS 3.2 style */
- tvc->cbExpires = 3600 + osi_Time();
- /*XXX*/ tvc->states |= CStatd;
- tvc->states &= ~CBulkFetching;
- afs_QueueCallback(tvc, CBHash(3600), tvp);
- } else {
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->states &= ~(CStatd | CUnique);
- if ((tvc->states & CForeign) || (tvc->fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
- }
- ReleaseWriteLock(&afs_xcbhash);
- if (tvp)
- afs_PutVolume(tvp, READ_LOCK);
-
- /* look in per-pag cache */
- if (tvc->Access && (ac = afs_FindAxs(tvc->Access, areq->uid)))
- ac->axess = OutStatus->CallerAccess; /* substitute pags */
- else /* not found, add a new one if possible */
- afs_AddAxs(tvc->Access, areq->uid, OutStatus->CallerAccess);
-
- ReleaseWriteLock(&tvc->lock);
- afs_Trace4(afs_iclSetp, CM_TRACE_STUFFVCACHE, ICL_TYPE_POINTER, tvc,
- ICL_TYPE_POINTER, tvc->callback, ICL_TYPE_INT32,
- tvc->cbExpires, ICL_TYPE_INT32, tvc->cbExpires - osi_Time());
- /*
- * Release ref count... hope this guy stays around...
- */
- afs_PutVCache(tvc);
-} /*afs_StuffVcache */
-#endif
-
-/*
- * afs_PutVCache
- *
- * Description:
- * Decrements the reference count on a cache entry.
- *
- * Parameters:
- * avc : Pointer to the cache entry to decrement.
- *
- * Environment:
- * Nothing interesting.
- */
-void
-afs_PutVCache(register struct vcache *avc)
-{
- AFS_STATCNT(afs_PutVCache);
- /*
- * Can we use a read lock here?
- */
- ObtainReadLock(&afs_xvcache);
- AFS_FAST_RELE(avc);
- ReleaseReadLock(&afs_xvcache);
-} /*afs_PutVCache */
-
-/*
- * afs_FindVCache
- *
- * Description:
- * Find a vcache entry given a fid.
- *
- * Parameters:
- * afid : Pointer to the fid whose cache entry we desire.
- * retry: (SGI-specific) tell the caller to drop the lock on xvcache,
- * unlock the vnode, and try again.
- * flags: bit 1 to specify whether to compute hit statistics. Not
- * set if FindVCache is called as part of internal bookkeeping.
- *
- * Environment:
- * Must be called with the afs_xvcache lock at least held at
- * the read level. In order to do the VLRU adjustment, the xvcache lock
- * must be shared-- we upgrade it here.
- */
-
-struct vcache *
-afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
-{
-
- register struct vcache *tvc;
- afs_int32 i;
-
- AFS_STATCNT(afs_FindVCache);
-
- i = VCHash(afid);
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (FidMatches(afid, tvc)) {
-#ifdef AFS_OSF_ENV
- /* Grab this vnode, possibly reactivating from the free list */
- int vg;
- AFS_GUNLOCK();
- vg = vget(AFSTOV(tvc));
- AFS_GLOCK();
- if (vg)
- continue;
-#endif /* AFS_OSF_ENV */
- break;
- }
- }
-
- /* should I have a read lock on the vnode here? */
- if (tvc) {
- if (retry)
- *retry = 0;
-#if !defined(AFS_OSF_ENV)
- osi_vnhold(tvc, retry); /* already held, above */
- if (retry && *retry)
- return 0;
-#endif
- /*
- * only move to front of vlru if we have proper vcache locking)
- */
- if (flag & DO_VLRU) {
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent2");
- }
- UpgradeSToWLock(&afs_xvcache, 26);
- QRemove(&tvc->vlruq);
- QAdd(&VLRU, &tvc->vlruq);
- ConvertWToSLock(&afs_xvcache);
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent2");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent3");
- }
- }
- vcachegen++;
- }
-
- if (flag & DO_STATS) {
- if (tvc)
- afs_stats_cmperf.vcacheHits++;
- else
- afs_stats_cmperf.vcacheMisses++;
- if (afs_IsPrimaryCellNum(afid->Cell))
- afs_stats_cmperf.vlocalAccesses++;
- else
- afs_stats_cmperf.vremoteAccesses++;
- }
-#ifdef AFS_LINUX22_ENV
- if (tvc && (tvc->states & CStatd))
- vcache2inode(tvc); /* mainly to reset i_nlink */
-#endif
-#ifdef AFS_DARWIN_ENV
- if (tvc)
- osi_VM_Setup(tvc, 0);
-#endif
- return tvc;
-} /*afs_FindVCache */
-
-/*
- * afs_NFSFindVCache
- *
- * Description:
- * Find a vcache entry given a fid. Does a wildcard match on what we
- * have for the fid. If more than one entry, don't return anything.
- *
- * Parameters:
- * avcp : Fill in pointer if we found one and only one.
- * afid : Pointer to the fid whose cache entry we desire.
- * retry: (SGI-specific) tell the caller to drop the lock on xvcache,
- * unlock the vnode, and try again.
- * flags: bit 1 to specify whether to compute hit statistics. Not
- * set if FindVCache is called as part of internal bookkeeping.
- *
- * Environment:
- * Must be called with the afs_xvcache lock at least held at
- * the read level. In order to do the VLRU adjustment, the xvcache lock
- * must be shared-- we upgrade it here.
- *
- * Return value:
- * number of matches found.
- */
-
-int afs_duplicate_nfs_fids = 0;
-
-afs_int32
-afs_NFSFindVCache(struct vcache **avcp, struct VenusFid *afid)
-{
- register struct vcache *tvc;
- afs_int32 i;
- afs_int32 count = 0;
- struct vcache *found_tvc = NULL;
-
- AFS_STATCNT(afs_FindVCache);
-
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- loop:
-#endif
-
- ObtainSharedLock(&afs_xvcache, 331);
-
- i = VCHash(afid);
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- /* Match only on what we have.... */
- if (((tvc->fid.Fid.Vnode & 0xffff) == afid->Fid.Vnode)
- && (tvc->fid.Fid.Volume == afid->Fid.Volume)
- && ((tvc->fid.Fid.Unique & 0xffffff) == afid->Fid.Unique)
- && (tvc->fid.Cell == afid->Cell)) {
-#ifdef AFS_OSF_ENV
- /* Grab this vnode, possibly reactivating from the free list */
- int vg;
- AFS_GUNLOCK();
- vg = vget(AFSTOV(tvc));
- AFS_GLOCK();
- if (vg) {
- /* This vnode no longer exists. */
- continue;
- }
-#endif /* AFS_OSF_ENV */
- count++;
- if (found_tvc) {
- /* Duplicates */
-#ifdef AFS_OSF_ENV
- /* Drop our reference counts. */
- vrele(AFSTOV(tvc));
- vrele(AFSTOV(found_tvc));
-#endif
- afs_duplicate_nfs_fids++;
- ReleaseSharedLock(&afs_xvcache);
- return count;
- }
- found_tvc = tvc;
- }
- }
-
- tvc = found_tvc;
- /* should I have a read lock on the vnode here? */
- if (tvc) {
-#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
- afs_int32 retry = 0;
- osi_vnhold(tvc, &retry);
- if (retry) {
- count = 0;
- found_tvc = (struct vcache *)0;
- ReleaseSharedLock(&afs_xvcache);
- spunlock_psema(tvc->v.v_lock, retry, &tvc->v.v_sync, PINOD);
- goto loop;
- }
-#else
-#if !defined(AFS_OSF_ENV)
- osi_vnhold(tvc, (int *)0); /* already held, above */
-#endif
-#endif
- /*
- * We obtained the xvcache lock above.
- */
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent2");
- }
- UpgradeSToWLock(&afs_xvcache, 568);
- QRemove(&tvc->vlruq);
- QAdd(&VLRU, &tvc->vlruq);
- ConvertWToSLock(&afs_xvcache);
- if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
- refpanic("FindVC VLRU inconsistent1");
- }
- if (tvc->vlruq.next->prev != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent2");
- }
- if (tvc->vlruq.prev->next != &(tvc->vlruq)) {
- refpanic("FindVC VLRU inconsistent3");
- }
- }
- vcachegen++;
-
- if (tvc)
- afs_stats_cmperf.vcacheHits++;
- else
- afs_stats_cmperf.vcacheMisses++;
- if (afs_IsPrimaryCellNum(afid->Cell))
- afs_stats_cmperf.vlocalAccesses++;
- else
- afs_stats_cmperf.vremoteAccesses++;
-
- *avcp = tvc; /* May be null */
-
- ReleaseSharedLock(&afs_xvcache);
- return (tvc ? 1 : 0);
-
-} /*afs_NFSFindVCache */
-
-
-
-
-/*
- * afs_vcacheInit
- *
- * Initialize vcache related variables
- */
-void
-afs_vcacheInit(int astatSize)
-{
- register struct vcache *tvp;
- int i;
-#if defined(AFS_OSF_ENV)
- if (!afs_maxvcount) {
-#if defined(AFS_OSF30_ENV)
- afs_maxvcount = max_vnodes / 2; /* limit ourselves to half the total */
-#else
- afs_maxvcount = nvnode / 2; /* limit ourselves to half the total */
-#endif
- if (astatSize < afs_maxvcount) {
- afs_maxvcount = astatSize;
- }
- }
-#else /* AFS_OSF_ENV */
- freeVCList = NULL;
-#endif
-
- RWLOCK_INIT(&afs_xvcache, "afs_xvcache");
- LOCK_INIT(&afs_xvcb, "afs_xvcb");
-
-#if !defined(AFS_OSF_ENV)
- /* Allocate and thread the struct vcache entries */
- tvp = (struct vcache *)afs_osi_Alloc(astatSize * sizeof(struct vcache));
- memset((char *)tvp, 0, sizeof(struct vcache) * astatSize);
-
- Initial_freeVCList = tvp;
- freeVCList = &(tvp[0]);
- for (i = 0; i < astatSize - 1; i++) {
- tvp[i].nextfree = &(tvp[i + 1]);
- }
- tvp[astatSize - 1].nextfree = NULL;
-#ifdef KERNEL_HAVE_PIN
- pin((char *)tvp, astatSize * sizeof(struct vcache)); /* XXX */
-#endif
-#endif
-
-
-#if defined(AFS_SGI_ENV)
- for (i = 0; i < astatSize; i++) {
- char name[METER_NAMSZ];
- struct vcache *tvc = &tvp[i];
-
- tvc->v.v_number = ++afsvnumbers;
- tvc->vc_rwlockid = OSI_NO_LOCKID;
- initnsema(&tvc->vc_rwlock, 1,
- makesname(name, "vrw", tvc->v.v_number));
-#ifndef AFS_SGI53_ENV
- initnsema(&tvc->v.v_sync, 0, makesname(name, "vsy", tvc->v.v_number));
-#endif
-#ifndef AFS_SGI62_ENV
- initnlock(&tvc->v.v_lock, makesname(name, "vlk", tvc->v.v_number));
-#endif /* AFS_SGI62_ENV */
- }
-#endif
-
- QInit(&VLRU);
-
-
-}
-
-/*
- * shutdown_vcache
- *
- */
-void
-shutdown_vcache(void)
-{
- int i;
- struct afs_cbr *tsp, *nsp;
- /*
- * XXX We may potentially miss some of the vcaches because if when there're no
- * free vcache entries and all the vcache entries are active ones then we allocate
- * an additional one - admittedly we almost never had that occur.
- */
-
- {
- register struct afs_q *tq, *uq;
- register struct vcache *tvc;
- for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
- tvc = QTOV(tq);
- uq = QPrev(tq);
- if (tvc->mvid) {
- osi_FreeSmallSpace(tvc->mvid);
- tvc->mvid = (struct VenusFid *)0;
- }
-#ifdef AFS_AIX_ENV
- aix_gnode_rele(AFSTOV(tvc));
-#endif
- if (tvc->linkData) {
- afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
- tvc->linkData = 0;
- }
- }
- /*
- * Also free the remaining ones in the Cache
- */
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- if (tvc->mvid) {
- osi_FreeSmallSpace(tvc->mvid);
- tvc->mvid = (struct VenusFid *)0;
- }
-#ifdef AFS_AIX_ENV
- if (tvc->v.v_gnode)
- afs_osi_Free(tvc->v.v_gnode, sizeof(struct gnode));
-#ifdef AFS_AIX32_ENV
- if (tvc->segid) {
- AFS_GUNLOCK();
- vms_delete(tvc->segid);
- AFS_GLOCK();
- tvc->segid = tvc->vmh = NULL;
- if (VREFCOUNT(tvc))
- osi_Panic("flushVcache: vm race");
- }
- if (tvc->credp) {
- crfree(tvc->credp);
- tvc->credp = NULL;
- }
-#endif
-#endif
-#if defined(AFS_SUN5_ENV)
- if (tvc->credp) {
- crfree(tvc->credp);
- tvc->credp = NULL;
- }
-#endif
- if (tvc->linkData) {
- afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
- tvc->linkData = 0;
- }
-
- afs_FreeAllAxs(&(tvc->Access));
- }
- afs_vhashT[i] = 0;
- }
- }
- /*
- * Free any leftover callback queue
- */
- for (tsp = afs_cbrSpace; tsp; tsp = nsp) {
- nsp = tsp->next;
- afs_osi_Free((char *)tsp, AFS_NCBRS * sizeof(struct afs_cbr));
- }
- afs_cbrSpace = 0;
-
-#if !defined(AFS_OSF_ENV)
- afs_osi_Free(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
-#endif
-#ifdef KERNEL_HAVE_PIN
- unpin(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
-#endif
-#if !defined(AFS_OSF_ENV)
- freeVCList = Initial_freeVCList = 0;
-#endif
- RWLOCK_INIT(&afs_xvcache, "afs_xvcache");
- LOCK_INIT(&afs_xvcb, "afs_xvcb");
- QInit(&VLRU);
-
-}
+++ /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
- */
-
-/*
- * Implements:
- * afs_vtoi (local)
- * afs_UFSGetVolSlot
- * afs_MemGetVolSlot
- * afs_CheckVolumeNames
- * afs_FindVolume
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-RCSID
- ("$Header: /cvs/openafs/src/afs/afs_volume.c,v 1.26 2003/08/27 21:43:16 rees Exp $");
-
-#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* ! AFS_HPUX110_ENV */
-#endif /* !defined(UKERNEL) */
-
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-/* In case we don't have the vl error table yet. */
-#ifndef ERROR_TABLE_BASE_VL
-#define ERROR_TABLE_BASE_VL (363520L)
-#define VL_NOENT (363524L)
-#endif /* vlserver error base define */
-
-/* Exported variables */
-ino_t volumeInode; /*Inode for VolumeItems file */
-afs_rwlock_t afs_xvolume; /* allocation lock for volumes */
-struct volume *afs_freeVolList;
-struct volume *afs_volumes[NVOLS];
-afs_int32 afs_volCounter = 1; /* for allocating volume indices */
-afs_int32 fvTable[NFENTRIES];
-
-/* Forward declarations */
-static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell,
- int agood, struct vrequest *areq,
- afs_int32 locktype);
-static struct volume *afs_NewDynrootVolume(struct VenusFid *fid);
-static int inVolList(struct VenusFid *fid, afs_int32 nvols, afs_int32 * vID,
- afs_int32 * cID);
-
-
-/* Convert a volume name to a #; return 0 if can't parse as a number */
-static int
-afs_vtoi(register char *aname)
-{
- register afs_int32 temp;
- register int tc;
- temp = 0;
- AFS_STATCNT(afs_vtoi);
- while ((tc = *aname++)) {
- if (tc > '9' || tc < '0')
- return 0; /* invalid name */
- temp *= 10;
- temp += tc - '0';
- }
- return temp;
-
-} /*afs_vtoi */
-
-
-/*
- * All of the vol cache routines must be called with the afs_xvolume
- * lock held in exclusive mode, since they use static variables.
- * In addition, we don't want two people adding the same volume
- * at the same time.
- */
-
-static struct fvolume staticFVolume;
-afs_int32 afs_FVIndex = -1;
-
-/* UFS specific version of afs_GetVolSlot */
-
-struct volume *
-afs_UFSGetVolSlot(void)
-{
- register struct volume *tv, **lv;
- struct osi_file *tfile;
- register afs_int32 i, code;
- afs_int32 bestTime;
- struct volume *bestVp, **bestLp;
-
- AFS_STATCNT(afs_UFSGetVolSlot);
- if (!afs_freeVolList) {
- /* get free slot */
- bestTime = 0x7fffffff;
- bestVp = 0;
- bestLp = 0;
- for (i = 0; i < NVOLS; i++) {
- lv = &afs_volumes[i];
- for (tv = *lv; tv; lv = &tv->next, tv = *lv) {
- if (tv->refCount == 0) { /* is this one available? */
- if (tv->accessTime < bestTime) { /* best one available? */
- bestTime = tv->accessTime;
- bestLp = lv;
- bestVp = tv;
- }
- }
- }
- }
- if (!bestVp)
- osi_Panic("getvolslot none");
- tv = bestVp;
- *bestLp = tv->next;
- if (tv->name)
- afs_osi_Free(tv->name, strlen(tv->name) + 1);
- tv->name = NULL;
- /* now write out volume structure to file */
- if (tv->vtix < 0) {
- tv->vtix = afs_volCounter++;
- /* now put on hash chain */
- i = FVHash(tv->cell, tv->volume);
- staticFVolume.next = fvTable[i];
- fvTable[i] = tv->vtix;
- } else {
- /*
- * Haul the guy in from disk so we don't overwrite hash table
- * next chain
- */
- if (afs_FVIndex != tv->vtix) {
- tfile = osi_UFSOpen(volumeInode);
- code =
- afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix,
- &staticFVolume, sizeof(struct fvolume));
- if (code != sizeof(struct fvolume))
- osi_Panic("read volumeinfo");
- osi_UFSClose(tfile);
- afs_FVIndex = tv->vtix;
- }
- }
- afs_FVIndex = tv->vtix;
- staticFVolume.volume = tv->volume;
- staticFVolume.cell = tv->cell;
- staticFVolume.mtpoint = tv->mtpoint;
- staticFVolume.dotdot = tv->dotdot;
- staticFVolume.rootVnode = tv->rootVnode;
- staticFVolume.rootUnique = tv->rootUnique;
- tfile = osi_UFSOpen(volumeInode);
- code =
- afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex,
- &staticFVolume, sizeof(struct fvolume));
- if (code != sizeof(struct fvolume))
- osi_Panic("write volumeinfo");
- osi_UFSClose(tfile);
- } else {
- tv = afs_freeVolList;
- afs_freeVolList = tv->next;
- }
- return tv;
-
-} /*afs_UFSGetVolSlot */
-
-
-struct volume *
-afs_MemGetVolSlot(void)
-{
- register struct volume *tv;
-
- AFS_STATCNT(afs_MemGetVolSlot);
- if (!afs_freeVolList) {
- struct volume *newVp;
-
- newVp = (struct volume *)afs_osi_Alloc(sizeof(struct volume));
-
- newVp->next = NULL;
- afs_freeVolList = newVp;
- }
- tv = afs_freeVolList;
- afs_freeVolList = tv->next;
- return tv;
-
-} /*afs_MemGetVolSlot */
-
-/* afs_ResetVolumes()
- * Reset volume inforamation for all volume structs that
- * point to a speicific server.
- */
-void
-afs_ResetVolumes(struct server *srvp)
-{
- int j, k;
- struct volume *vp;
-
- /* Find any volumes residing on this server and flush their state */
- for (j = 0; j < NVOLS; j++) {
- for (vp = afs_volumes[j]; vp; vp = vp->next) {
- for (k = 0; k < MAXHOSTS; k++) {
- if (!srvp || (vp->serverHost[k] == srvp)) {
- vp->serverHost[k] = 0;
- afs_ResetVolumeInfo(vp);
- break;
- }
- }
- }
- }
-}
-
-
-/* reset volume name to volume id mapping cache */
-void
-afs_CheckVolumeNames(int flags)
-{
- afs_int32 i, j;
- struct volume *tv;
- unsigned int now;
- struct vcache *tvc;
- afs_int32 *volumeID, *cellID, vsize, nvols;
- AFS_STATCNT(afs_CheckVolumeNames);
-
- nvols = 0;
- volumeID = cellID = NULL;
- vsize = 0;
- ObtainReadLock(&afs_xvolume);
- if (flags & AFS_VOLCHECK_EXPIRED) {
- /*
- * allocate space to hold the volumeIDs and cellIDs, only if
- * we will be invalidating the mountpoints later on
- */
- for (i = 0; i < NVOLS; i++)
- for (tv = afs_volumes[i]; tv; tv = tv->next)
- ++vsize;
-
- volumeID = (afs_int32 *) afs_osi_Alloc(2 * vsize * sizeof(*volumeID));
- cellID = (volumeID) ? volumeID + vsize : 0;
- }
-
- now = osi_Time();
- for (i = 0; i < NVOLS; i++) {
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (flags & AFS_VOLCHECK_EXPIRED) {
- if (((tv->expireTime < (now + 10)) && (tv->states & VRO))
- || (flags & AFS_VOLCHECK_FORCE)) {
- afs_ResetVolumeInfo(tv); /* also resets status */
- if (volumeID) {
- volumeID[nvols] = tv->volume;
- cellID[nvols] = tv->cell;
- }
- ++nvols;
- continue;
- }
- }
- if (flags & (AFS_VOLCHECK_BUSY | AFS_VOLCHECK_FORCE)) {
- for (j = 0; j < MAXHOSTS; j++)
- tv->status[j] = not_busy;
- }
-
- }
- }
- ReleaseReadLock(&afs_xvolume);
-
-
- /* next ensure all mt points are re-evaluated */
- if (nvols || (flags & (AFS_VOLCHECK_FORCE | AFS_VOLCHECK_MTPTS))) {
- ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-
- /* if the volume of "mvid" of the vcache entry is among the
- * ones we found earlier, then we re-evaluate it. Also, if the
- * force bit is set or we explicitly asked to reevaluate the
- * mt-pts, we clean the cmvalid bit */
-
- if ((flags & (AFS_VOLCHECK_FORCE | AFS_VOLCHECK_MTPTS))
- || (tvc->mvid
- && inVolList(tvc->mvid, nvols, volumeID, cellID)))
- tvc->states &= ~CMValid;
-
- /* If the volume that this file belongs to was reset earlier,
- * then we should remove its callback.
- * Again, if forced, always do it.
- */
- if ((tvc->states & CRO)
- && (inVolList(&tvc->fid, nvols, volumeID, cellID)
- || (flags & AFS_VOLCHECK_FORCE))) {
-
- AFS_FAST_HOLD(tvc);
- ReleaseReadLock(&afs_xvcache);
-
- ObtainWriteLock(&afs_xcbhash, 485);
- /* LOCKXXX: We aren't holding tvc write lock? */
- afs_DequeueCallback(tvc);
- tvc->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
-
- ObtainReadLock(&afs_xvcache);
-
- /* our tvc ptr is still good until now */
- AFS_FAST_RELE(tvc);
- }
- }
- }
- osi_dnlc_purge(); /* definitely overkill, but it's safer this way. */
- ReleaseReadLock(&afs_xvcache);
- }
-
- if (volumeID)
- afs_osi_Free(volumeID, 2 * vsize * sizeof(*volumeID));
-
-} /*afs_CheckVolumeNames */
-
-
-static int
-inVolList(struct VenusFid *fid, afs_int32 nvols, afs_int32 * vID,
- afs_int32 * cID)
-{
- afs_int32 i;
-
- /* if no arrays present, be conservative and return true */
- if (nvols && (!vID || !cID))
- return 1;
-
- for (i = 0; i < nvols; ++i) {
- if (fid->Fid.Volume == vID[i] && fid->Cell == cID[i])
- return 1;
- }
- return 0;
-}
-
-
-/* afs_PutVolume is now a macro in afs.h */
-
-
-/* afs_FindVolume()
- * return volume struct if we have it cached and it's up-to-date
- *
- * Environment: Must be called with afs_xvolume unlocked.
- */
-struct volume *
-afs_FindVolume(struct VenusFid *afid, afs_int32 locktype)
-{
- struct volume *tv;
- afs_int32 i;
-
- if (afid == NULL)
- return NULL;
-
- i = VHash(afid->Fid.Volume);
- ObtainWriteLock(&afs_xvolume, 106);
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->volume == afid->Fid.Volume && tv->cell == afid->Cell
- && (tv->states & VRecheck) == 0) {
- tv->refCount++;
- break;
- }
- }
- ReleaseWriteLock(&afs_xvolume);
- return tv; /* NULL if we didn't find it */
-} /*afs_FindVolume */
-
-
-
-/*
- * Note that areq may be null, in which case we don't bother to set any
- * request status information.
- */
-struct volume *
-afs_GetVolume(struct VenusFid *afid, struct vrequest *areq,
- afs_int32 locktype)
-{
- struct volume *tv;
- char *bp, tbuf[CVBS];
- AFS_STATCNT(afs_GetVolume);
-
- tv = afs_FindVolume(afid, locktype);
- if (!tv) {
- if (afs_IsDynrootFid(afid)) {
- tv = afs_NewDynrootVolume(afid);
- } else {
- bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
- tv = afs_NewVolumeByName(bp, afid->Cell, 0, areq, locktype);
- }
- }
- return tv;
-} /*afs_GetVolume */
-
-
-
-static struct volume *
-afs_SetupVolume(afs_int32 volid, char *aname, char *ve, struct cell *tcell,
- afs_int32 agood, afs_int32 type, struct vrequest *areq)
-{
- struct volume *tv;
- struct vldbentry *ove = (struct vldbentry *)ve;
- struct nvldbentry *nve = (struct nvldbentry *)ve;
- struct uvldbentry *uve = (struct uvldbentry *)ve;
-
- int whichType; /* which type of volume to look for */
- int i, j, err = 0;
-
- if (!volid) {
- int len;
- /* special hint from file server to use vlserver */
- len = strlen(aname);
- if (len >= 8 && strcmp(aname + len - 7, ".backup") == 0)
- whichType = BACKVOL;
- else if (len >= 10 && strcmp(aname + len - 9, ".readonly") == 0)
- whichType = ROVOL;
- else
- whichType = RWVOL;
-
- /* figure out which one we're really interested in (a set is returned) */
- volid = afs_vtoi(aname);
- if (volid == 0) {
- if (type == 2) {
- volid = uve->volumeId[whichType];
- } else if (type == 1) {
- volid = nve->volumeId[whichType];
- } else {
- volid = ove->volumeId[whichType];
- }
- }
- }
-
-
- ObtainWriteLock(&afs_xvolume, 108);
- i = VHash(volid);
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->volume == volid && tv->cell == tcell->cellNum) {
- break;
- }
- }
- if (!tv) {
- struct fvolume *tf = 0;
-
- tv = afs_GetVolSlot();
- memset((char *)tv, 0, sizeof(struct volume));
- tv->cell = tcell->cellNum;
- RWLOCK_INIT(&tv->lock, "volume lock");
- tv->next = afs_volumes[i]; /* thread into list */
- afs_volumes[i] = tv;
- tv->volume = volid;
- for (j = fvTable[FVHash(tv->cell, volid)]; j != 0; j = tf->next) {
- if (afs_FVIndex != j) {
- struct osi_file *tfile;
- tfile = osi_UFSOpen(volumeInode);
- err =
- afs_osi_Read(tfile, sizeof(struct fvolume) * j,
- &staticFVolume, sizeof(struct fvolume));
- if (err != sizeof(struct fvolume))
- osi_Panic("read volumeinfo2");
- osi_UFSClose(tfile);
- afs_FVIndex = j;
- }
- tf = &staticFVolume;
- if (tf->cell == tv->cell && tf->volume == volid)
- break;
- }
- if (tf && (j != 0)) {
- tv->vtix = afs_FVIndex;
- tv->mtpoint = tf->mtpoint;
- tv->dotdot = tf->dotdot;
- tv->rootVnode = tf->rootVnode;
- tv->rootUnique = tf->rootUnique;
- } else {
- tv->vtix = -1;
- tv->rootVnode = tv->rootUnique = 0;
- }
- }
- tv->refCount++;
- tv->states &= ~VRecheck; /* just checked it */
- tv->accessTime = osi_Time();
- ReleaseWriteLock(&afs_xvolume);
- ObtainWriteLock(&tv->lock, 111);
- if (type == 2) {
- InstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq);
- } else if (type == 1)
- InstallNVolumeEntry(tv, nve, tcell->cellNum);
- else
- InstallVolumeEntry(tv, ove, tcell->cellNum);
- if (agood) {
- if (!tv->name) {
- tv->name = afs_osi_Alloc(strlen(aname) + 1);
- strcpy(tv->name, aname);
- }
- }
- for (i = 0; i < NMAXNSERVERS; i++) {
- tv->status[i] = not_busy;
- }
- ReleaseWriteLock(&tv->lock);
- return tv;
-}
-
-
-struct volume *
-afs_GetVolumeByName(register char *aname, afs_int32 acell, int agood,
- struct vrequest *areq, afs_int32 locktype)
-{
- afs_int32 i;
- struct volume *tv;
-
- AFS_STATCNT(afs_GetVolumeByName);
- ObtainWriteLock(&afs_xvolume, 112);
- for (i = 0; i < NVOLS; i++) {
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->name && !strcmp(aname, tv->name) && tv->cell == acell
- && (tv->states & VRecheck) == 0) {
- tv->refCount++;
- ReleaseWriteLock(&afs_xvolume);
- return tv;
- }
- }
- }
-
- ReleaseWriteLock(&afs_xvolume);
-
- tv = afs_NewVolumeByName(aname, acell, agood, areq, locktype);
- return (tv);
-}
-
-static struct volume *
-afs_NewDynrootVolume(struct VenusFid *fid)
-{
- struct cell *tcell;
- struct volume *tv;
- struct vldbentry *tve;
- char *bp, tbuf[CVBS];
-
- tcell = afs_GetCell(fid->Cell, READ_LOCK);
- if (!tcell)
- return NULL;
- tve = afs_osi_Alloc(sizeof(*tve));
- if (!(tcell->states & CHasVolRef))
- tcell->states |= CHasVolRef;
-
- bp = afs_cv2string(&tbuf[CVBS], fid->Fid.Volume);
- memset(tve, 0, sizeof(*tve));
- strcpy(tve->name, "local-dynroot");
- tve->volumeId[ROVOL] = fid->Fid.Volume;
- tve->flags = VLF_ROEXISTS;
-
- tv = afs_SetupVolume(0, bp, tve, tcell, 0, 0, 0);
- afs_PutCell(tcell, READ_LOCK);
- afs_osi_Free(tve, sizeof(*tve));
- return tv;
-}
-
-int lastnvcode;
-static struct volume *
-afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
- struct vrequest *areq, afs_int32 locktype)
-{
- afs_int32 code, type = 0;
- struct volume *tv, *tv1;
- struct vldbentry *tve;
- struct nvldbentry *ntve;
- struct uvldbentry *utve;
- struct cell *tcell;
- char *tbuffer, *ve;
- struct conn *tconn;
- struct vrequest treq;
-
- if (strlen(aname) > VL_MAXNAMELEN) /* Invalid volume name */
- return NULL;
-
- tcell = afs_GetCell(acell, READ_LOCK);
- if (!tcell) {
- return NULL;
- }
-
- /* allow null request if we don't care about ENODEV/ETIMEDOUT distinction */
- if (!areq)
- areq = &treq;
-
-
- afs_Trace2(afs_iclSetp, CM_TRACE_GETVOL, ICL_TYPE_STRING, aname,
- ICL_TYPE_POINTER, aname);
- tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- tve = (struct vldbentry *)(tbuffer + 1024);
- ntve = (struct nvldbentry *)tve;
- utve = (struct uvldbentry *)tve;
- afs_InitReq(&treq, afs_osi_credp); /* *must* be unauth for vldb */
- do {
- tconn =
- afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
- &treq, SHARED_LOCK);
- if (tconn) {
- if (tconn->srvr->server->flags & SNO_LHOSTS) {
- type = 0;
- RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameO(tconn->id, aname, tve);
- RX_AFS_GLOCK();
- } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
- type = 1;
- RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameN(tconn->id, aname, ntve);
- RX_AFS_GLOCK();
- } else {
- type = 2;
- RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameU(tconn->id, aname, utve);
- RX_AFS_GLOCK();
- if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
- if (code == RXGEN_OPCODE) {
- type = 1;
- RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameN(tconn->id, aname, ntve);
- RX_AFS_GLOCK();
- if (code == RXGEN_OPCODE) {
- type = 0;
- tconn->srvr->server->flags |= SNO_LHOSTS;
- RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameO(tconn->id, aname, tve);
- RX_AFS_GLOCK();
- } else if (!code)
- tconn->srvr->server->flags |= SYES_LHOSTS;
- } else if (!code)
- tconn->srvr->server->flags |= SVLSRV_UUID;
- }
- lastnvcode = code;
- }
- } else
- code = -1;
- } while (afs_Analyze(tconn, code, NULL, &treq, -1, /* no op code for this */
- SHARED_LOCK, tcell));
-
- if (code) {
- /* If the client has yet to contact this cell and contact failed due
- * to network errors, mark the VLDB servers as back up.
- * That the client tried and failed can be determined from the
- * fact that there was a downtime incident, but CHasVolRef is not set.
- */
- if (areq->networkError && !(tcell->states & CHasVolRef)) {
- int i;
- struct server *sp;
- struct srvAddr *sap;
- for (i = 0; i < MAXCELLHOSTS; i++) {
- if ((sp = tcell->cellHosts[i]) == NULL)
- break;
- for (sap = sp->addr; sap; sap = sap->next_sa)
- afs_MarkServerUpOrDown(sap, 0);
- }
- }
- afs_CopyError(&treq, areq);
- osi_FreeLargeSpace(tbuffer);
- afs_PutCell(tcell, READ_LOCK);
- return NULL;
- }
- /*
- * Check to see if this cell has not yet referenced a volume. If
- * it hasn't, it's just about to change its status, and we need to mark
- * this fact down. Note that it is remotely possible that afs_SetupVolume
- * could fail and we would still not have a volume reference.
- */
- if (!(tcell->states & CHasVolRef)) {
- tcell->states |= CHasVolRef;
- afs_stats_cmperf.numCellsContacted++;
- }
- /*First time a volume in this cell has been referenced */
- if (type == 2)
- ve = (char *)utve;
- else if (type == 1)
- ve = (char *)ntve;
- else
- ve = (char *)tve;
- tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, areq);
- if ((agood == 3) && tv->backVol) {
- /*
- * This means that very soon we'll ask for the BK volume so
- * we'll prefetch it (well we did already.)
- */
- tv1 =
- afs_SetupVolume(tv->backVol, (char *)0, ve, tcell, 0, type, areq);
- tv1->refCount--;
- }
- if ((agood >= 2) && tv->roVol) {
- /*
- * This means that very soon we'll ask for the RO volume so
- * we'll prefetch it (well we did already.)
- */
- tv1 = afs_SetupVolume(tv->roVol, NULL, ve, tcell, 0, type, areq);
- tv1->refCount--;
- }
- osi_FreeLargeSpace(tbuffer);
- afs_PutCell(tcell, READ_LOCK);
- return tv;
-
-} /*afs_NewVolumeByName */
-
-
-
-/* call this with the volume structure locked; used for new-style vldb requests */
-void
-InstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
-{
- register struct server *ts;
- struct cell *cellp;
- register int i, j;
- afs_int32 mask;
- afs_uint32 temp;
-
- AFS_STATCNT(InstallVolumeEntry);
-
- /* Determine the type of volume we want */
- if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
- mask = VLSF_RWVOL;
- } else if ((ve->flags & VLF_ROEXISTS)
- && (av->volume == ve->volumeId[ROVOL])) {
- mask = VLSF_ROVOL;
- av->states |= VRO;
- } else if ((ve->flags & VLF_BACKEXISTS)
- && (av->volume == ve->volumeId[BACKVOL])) {
- /* backup always is on the same volume as parent */
- mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
- } else {
- mask = 0; /* Can't find volume in vldb entry */
- }
-
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
- cellp = afs_GetCell(acell, 0);
-
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
- /* Step through the VLDB entry making sure each server listed is there */
- for (i = 0, j = 0; i < ve->nServers; i++) {
- if (((ve->serverFlags[i] & mask) == 0)
- || (ve->serverFlags[i] & VLSF_DONTUSE)) {
- continue; /* wrong volume or don't use this volume */
- }
-
- temp = htonl(ve->serverNumber[i]);
- ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
- av->serverHost[j] = ts;
-
- /*
- * The cell field could be 0 if the server entry was created
- * first with the 'fs setserverprefs' call which doesn't set
- * the cell field. Thus if the afs_GetServer call above
- * follows later on it will find the server entry thus it will
- * simply return without setting any fields, so we set the
- * field ourselves below.
- */
- if (!ts->cell)
- ts->cell = cellp;
- afs_PutServer(ts, WRITE_LOCK);
- j++;
- }
- if (j < MAXHOSTS) {
- av->serverHost[j++] = 0;
- }
- afs_SortServers(av->serverHost, MAXHOSTS);
-} /*InstallVolumeEntry */
-
-
-void
-InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
-{
- register struct server *ts;
- struct cell *cellp;
- register int i, j;
- afs_int32 mask;
- afs_uint32 temp;
-
- AFS_STATCNT(InstallVolumeEntry);
-
- /* Determine type of volume we want */
- if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
- mask = VLSF_RWVOL;
- } else if ((ve->flags & VLF_ROEXISTS)
- && (av->volume == ve->volumeId[ROVOL])) {
- mask = VLSF_ROVOL;
- av->states |= VRO;
- } else if ((ve->flags & VLF_BACKEXISTS)
- && (av->volume == ve->volumeId[BACKVOL])) {
- /* backup always is on the same volume as parent */
- mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
- } else {
- mask = 0; /* Can't find volume in vldb entry */
- }
-
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
- cellp = afs_GetCell(acell, 0);
-
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
- /* Step through the VLDB entry making sure each server listed is there */
- for (i = 0, j = 0; i < ve->nServers; i++) {
- if (((ve->serverFlags[i] & mask) == 0)
- || (ve->serverFlags[i] & VLSF_DONTUSE)) {
- continue; /* wrong volume or don't use this volume */
- }
-
- temp = htonl(ve->serverNumber[i]);
- ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
- av->serverHost[j] = ts;
- /*
- * The cell field could be 0 if the server entry was created
- * first with the 'fs setserverprefs' call which doesn't set
- * the cell field. Thus if the afs_GetServer call above
- * follows later on it will find the server entry thus it will
- * simply return without setting any fields, so we set the
- * field ourselves below.
- */
- if (!ts->cell)
- ts->cell = cellp;
- afs_PutServer(ts, WRITE_LOCK);
- j++;
- }
- if (j < MAXHOSTS) {
- av->serverHost[j++] = 0;
- }
- afs_SortServers(av->serverHost, MAXHOSTS);
-} /*InstallNVolumeEntry */
-
-
-void
-InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
- struct cell *tcell, struct vrequest *areq)
-{
- register struct server *ts;
- struct conn *tconn;
- struct cell *cellp;
- register int i, j;
- afs_uint32 serverid;
- afs_int32 mask;
- int k;
-
- AFS_STATCNT(InstallVolumeEntry);
-
- /* Determine type of volume we want */
- if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
- mask = VLSF_RWVOL;
- } else if ((ve->flags & VLF_ROEXISTS)
- && av->volume == ve->volumeId[ROVOL]) {
- mask = VLSF_ROVOL;
- av->states |= VRO;
- } else if ((ve->flags & VLF_BACKEXISTS)
- && (av->volume == ve->volumeId[BACKVOL])) {
- /* backup always is on the same volume as parent */
- mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
- } else {
- mask = 0; /* Can't find volume in vldb entry */
- }
-
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
- cellp = afs_GetCell(acell, 0);
-
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
- /* Gather the list of servers the VLDB says the volume is on
- * and initialize the ve->serverHost[] array. If a server struct
- * is not found, then get the list of addresses for the
- * server, VL_GetAddrsU(), and create a server struct, afs_GetServer().
- */
- for (i = 0, j = 0; i < ve->nServers; i++) {
- if (((ve->serverFlags[i] & mask) == 0)
- || (ve->serverFlags[i] & VLSF_DONTUSE)) {
- continue; /* wrong volume don't use this volume */
- }
-
- if (!(ve->serverFlags[i] & VLSERVER_FLAG_UUID)) {
- /* The server has no uuid */
- serverid = htonl(ve->serverNumber[i].time_low);
- ts = afs_GetServer(&serverid, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
- } else {
- ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0);
- if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i])
- && ts->addr) {
- /* uuid, uniquifier, and portal are the same */
- } else {
- afs_uint32 *addrp, nentries, code, unique;
- bulkaddrs addrs;
- ListAddrByAttributes attrs;
- afsUUID uuid;
-
- memset((char *)&attrs, 0, sizeof(attrs));
- attrs.Mask = VLADDR_UUID;
- attrs.uuid = ve->serverNumber[i];
- memset((char *)&uuid, 0, sizeof(uuid));
- memset((char *)&addrs, 0, sizeof(addrs));
- do {
- tconn =
- afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
- tcell->cellNum, areq, SHARED_LOCK);
- if (tconn) {
- RX_AFS_GUNLOCK();
- code =
- VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique,
- &nentries, &addrs);
- RX_AFS_GLOCK();
- } else {
- code = -1;
- }
-
- /* Handle corrupt VLDB (defect 7393) */
- if (code == 0 && nentries == 0)
- code = VL_NOENT;
-
- } while (afs_Analyze
- (tconn, code, NULL, areq, -1, SHARED_LOCK, tcell));
- if (code) {
- /* Better handing of such failures; for now we'll simply retry this call */
- areq->volumeError = 1;
- return;
- }
-
- addrp = addrs.bulkaddrs_val;
- for (k = 0; k < nentries; k++) {
- addrp[k] = htonl(addrp[k]);
- }
- ts = afs_GetServer(addrp, nentries, acell, cellp->fsport,
- WRITE_LOCK, &ve->serverNumber[i],
- ve->serverUnique[i]);
- afs_osi_Free(addrs.bulkaddrs_val,
- addrs.bulkaddrs_len * sizeof(*addrp));
- }
- }
- av->serverHost[j] = ts;
-
- /* The cell field could be 0 if the server entry was created
- * first with the 'fs setserverprefs' call which doesn't set
- * the cell field. Thus if the afs_GetServer call above
- * follows later on it will find the server entry thus it will
- * simply return without setting any fields, so we set the
- * field ourselves below.
- */
- if (!ts->cell)
- ts->cell = cellp;
- afs_PutServer(ts, WRITE_LOCK);
- j++;
- }
-
- afs_SortServers(av->serverHost, MAXHOSTS);
-} /*InstallVolumeEntry */
-
-
-void
-afs_ResetVolumeInfo(struct volume *tv)
-{
- int i;
-
- AFS_STATCNT(afs_ResetVolumeInfo);
- ObtainWriteLock(&tv->lock, 117);
- tv->states |= VRecheck;
- for (i = 0; i < MAXHOSTS; i++)
- tv->status[i] = not_busy;
- if (tv->name) {
- afs_osi_Free(tv->name, strlen(tv->name) + 1);
- tv->name = NULL;
- }
- ReleaseWriteLock(&tv->lock);
-}
+++ /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
- */
-
-#ifdef UKERNEL
-#include <UKERNEL/afsincludes.h>
-#else
-
-#include <afsconfig.h>
-
-/* AFS based headers */
-#include "afs/stds.h"
-#ifdef AFS_AIX_ENV
-#include "osi_vfs.h"
-#else
-#ifdef AFS_DEC_ENV
-#include "afs/gfs_vfs.h"
-#include "afs/gfs_vnode.h"
-#else
-#ifdef AFS_HPUX_ENV
-#include "osi_vfs.h"
-#endif /* AFS_HPUX_ENV */
-#endif /* AFS_DEC_ENV */
-#endif /* AFS_AIX_ENV */
-#if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
-#include "osi_vfs.h"
-#endif
-#include "rx/rx.h"
-#include "afs/afs_osi.h"
-#include "afs/lock.h"
-#include "afs/volerrors.h"
-#include "afs/voldefs.h"
-#ifdef AFS_LINUX20_ENV
-#ifdef TRUE
-#undef TRUE
-#undef FALSE
-#endif
-#endif
-#ifdef AFS_LINUX20_ENV
-#undef __NFDBITS
-#undef __FDMASK
-#endif
-#include "afsint.h"
-#include "afs/exporter.h"
-#include "vldbint.h"
-#include "afs/afs.h"
-#include "afs/afs_chunkops.h"
-/*#include "afs/auxinode.h" -- used only in afs_istuff.c */
-#include "rx/rxkad.h"
-#include "afs/prs_fs.h"
-#include "afs/dir.h"
-#include "afs/afs_axscache.h"
-#include "afs/icl.h"
-#include "afs/afs_stats.h"
-#include "afs/afs_prototypes.h"
-#if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-#include "osi_machdep.h"
-#endif
-
-#endif
+++ /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
- */
-
-#ifndef __EXPORTER__
-#define __EXPORTER__
-
-#ifdef UID_NOBODY
-#define NFS_NOBODY UID_NOBODY
-#endif
-#ifndef NFS_NOBODY
-#define NFS_NOBODY -2 /* maps Nfs's "nobody" but since not declared by some systems (i.e. Ultrix) we use a constant */
-#endif
-#define RMTUSER_REQ 0xabc
-
-/**
- * There is a limitation on the number of bytes that can be passed into
- * the file handle that nfs passes into AFS. The limit is 10 bytes.
- * We pass in an array of long of size 2. On a 32 bit system this would be
- * 8 bytes. But on a 64 bit system this would be 16 bytes. The first
- * element of this array is a pointer so we cannot truncate that. But the
- * second element is the AFS_XLATOR_MAGIC, which we can truncate.
- * So on a 64 bit system the 10 bytes are used as below
- * Bytes 1-8 pointer to vnode
- * Bytes 9 and 10 AFS_XLATOR_MAGIC
- *
- * And hence for 64 bit environments AFS_XLATOR_MAGIC is 8765 which takes
- * up 2 bytes
- */
-
-#if defined(AFS_SUN57_64BIT_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZPTR==64)) || defined(AFS_LINUX_64BIT_KERNEL)
-#define AFS_XLATOR_MAGIC 0x8765 /* XXX */
-#else
-#define AFS_XLATOR_MAGIC 0x87654321
-#endif
-
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#define AFS_NFSXLATORREQ(cred) 0
-#else
-#ifdef AFS_OSF_ENV
-#define AFS_NFSXLATORREQ(cred) ((cred)->cr_ruid == NFSXLATOR_CRED)
-#else
-#define AFS_NFSXLATORREQ(cred) ((cred)->cr_rgid == NFSXLATOR_CRED)
-#endif
-#endif
-
-struct exporterops {
- int (*export_reqhandler) ();
- int (*export_hold) ();
- int (*export_rele) ();
- int (*export_sysname) ();
- int (*export_garbagecollect) ();
- int (*export_statistics) ();
-};
-
-struct exporterstats {
- afs_int32 calls; /* # of calls to the exporter */
- afs_int32 rejectedcalls; /* # of afs rejected calls */
- afs_int32 nopag; /* # of unpagged remote calls */
- afs_int32 invalidpag; /* # of invalid pag calls */
-};
-
-struct afs_exporter {
- struct afs_exporter *exp_next;
- struct exporterops *exp_op;
- afs_int32 exp_states;
- afs_int32 exp_type;
- struct exporterstats exp_stats;
- char *exp_data;
-};
-
-/* exp_type values */
-#define EXP_NULL 0 /* Undefined */
-#define EXP_NFS 1 /* Nfs/Afs translator */
-
-/* exp_states values */
-#define EXP_EXPORTED 1
-#define EXP_UNIXMODE 2
-#define EXP_PWSYNC 4
-#define EXP_SUBMOUNTS 8
-
-
-#define AFS_NFSFULLFID 1
-
-#define EXP_REQHANDLER(EXP, CRED, HOST, PAG, EXPP) \
- (*(EXP)->exp_op->export_reqhandler)(EXP, CRED, HOST, PAG, EXPP)
-#define EXP_HOLD(EXP) \
- (*(EXP)->exp_op->export_hold)(EXP)
-#define EXP_RELE(EXP) \
- (*(EXP)->exp_op->export_rele)(EXP)
-#define EXP_SYSNAME(EXP, INNAME, OUTNAME, NUM) \
- (*(EXP)->exp_op->export_sysname)(EXP, INNAME, OUTNAME, NUM)
-#define EXP_GC(EXP, param) \
- (*(EXP)->exp_op->export_garbagecollect)(EXP, param)
-#define EXP_STATISTICS(EXP) \
- (*(EXP)->exp_op->export_statistics)(EXP)
-
-struct afs3_fid {
- u_short len;
- u_short padding;
- afs_uint32 Cell;
- afs_uint32 Volume;
- afs_uint32 Vnode;
- afs_uint32 Unique;
-};
-
-struct Sfid {
- afs_uint32 padding;
- afs_uint32 Cell;
- afs_uint32 Volume;
- afs_uint32 Vnode;
- afs_uint32 Unique;
-#ifdef AFS_SUN5_ENV
- struct cred *credp;
-#endif
-};
-
-
-#endif /* __EXPORTER__ */
+++ /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
- */
-
-#ifndef __AFSLOCK_INCLUDE__
-#define __AFSLOCK_INCLUDE__ 1
-
-#if !defined(KERNEL) && !defined(KDUMP_KERNEL)
-#error Do not include afs/lock.h except for kernel code.
-#endif
-
-/*
- * (C) COPYRIGHT IBM CORPORATION 1987
- * LICENSED MATERIALS - PROPERTY OF IBM
- */
-
-#if (defined(AFS_SUN5_ENV)) || defined(AFS_OSF_ENV)
-#define AFS_NOBOZO_LOCK
-#endif
-
-#if !defined(AFS_OSF20_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_OSF32_ENV)
- /* We do not instrument locks on osf20 because the vcache structure
- ** exceeds the maximim possible limit for a vnode.
- */
-#define INSTRUMENT_LOCKS
-/* This is the max lock number in use. Please update it if you add any new
- * lock numbers.
- */
-#define MAX_LOCK_NUMBER 700
-#endif
-
-struct afs_bozoLock {
- short count; /* count of excl locks */
- char flags; /* bit 1: is anyone waiting? */
- char spare; /* for later */
- char *proc; /* process holding the lock, really a struct proc * */
-};
-#ifndef AFS_NOBOZO_LOCK
-typedef struct afs_bozoLock afs_bozoLock_t;
-#else
-#ifdef AFS_SUN5_ENV
-typedef kmutex_t afs_bozoLock_t;
-#else
-typedef struct afs_bozoLock afs_bozoLock_t;
-#endif
-#define afs_BozonLock(lock, avc)
-#define afs_BozonUnlock(lock, avc)
-#define afs_BozonInit(lock, nm)
-#define afs_CheckBozonLock(lock) 0
-#define afs_CheckBozonLockBlocking(lock) 0
-#endif
-
-#define AFS_BOZONWAITING 1 /* someone is waiting for this lock */
-
-#undef MObtainWriteLock /* Defined also in ../rx/rx_machdep.h" */
-#undef MReleaseWriteLock
-#ifndef RXObtainWriteLock
-#define RXObtainWriteLock(lock) ObtainWriteLock(lock)
-#define RXReleaseWriteLock(lock) ReleaseWriteLock(lock)
-#endif
-#define MObtainReadLock(lock) ObtainReadLock(lock)
-#define MObtainWriteLock(lock,src) ObtainWriteLock(lock,src)
-#define MObtainSharedLock(lock,src) ObtainSharedLock(lock,src)
-#define MUpgradeSToWLock(lock,src) UpgradeSToWLock(lock,src)
-#define MConvertWToSLock(lock) ConvertWToSLock(lock)
-#define MReleaseReadLock(lock) ReleaseReadLock(lock)
-#define MReleaseWriteLock(lock) ReleaseWriteLock(lock)
-#define MReleaseSharedLock(lock) ReleaseSharedLock(lock)
-
-#define RWLOCK_INIT(lock, nm) Lock_Init(lock)
-#undef LOCK_INIT
-#define LOCK_INIT(lock, nm) Lock_Init(lock)
-
-/* The following macros allow multi statement macros to be defined safely, i.e.
- - the multi statement macro can be the object of an if statement;
- - the call to the multi statement macro may be legally followed by a semi-colon.
- BEGINMAC and ENDMAC have been tested with both the portable C compiler and
- Hi-C. Both compilers were from the Palo Alto 4.2BSD software releases, and
- both optimized out the constant loop code. For an example of the use
- of BEGINMAC and ENDMAC, see the definition for ReleaseWriteLock, below.
- An alternative to this, using "if(1)" for BEGINMAC is not used because it
- may generate worse code with pcc, and may generate warning messages with hi-C.
-*/
-
-#define BEGINMAC do {
-#define ENDMAC } while (0)
-
-#if defined(AFS_SUN5_ENV) || defined(AFS_OBSD_ENV)
-#define MyPidxx (curproc->p_pid)
-#else
-#if defined(AFS_AIX41_ENV)
-extern tid_t thread_self();
-#define MyPidxx thread_self()
-#else /* AFS_AIX41_ENV */
-#if defined(AFS_HPUX101_ENV)
-#define MyPidxx ((int)p_pid(u.u_procp))
-#else
-#if defined(AFS_SGI64_ENV)
-#if defined(AFS_SGI65_ENV)
-#define MyPidxx proc_pid(curproc())
-#else
-#define MyPidxx current_pid()
-#endif
-#else /* AFS_SGI64_ENV */
-#ifdef AFS_LINUX20_ENV
-#define MyPidxx current->pid
-#else
-#if defined(AFS_DARWIN_ENV)
-#define MyPidxx (current_proc()->p_pid )
-#else
-#if defined(AFS_FBSD_ENV)
-#define MyPidxx (curproc->p_pid )
-#else
-#define MyPidxx (u.u_procp->p_pid )
-#endif /* AFS_FBSD_ENV */
-#endif /* AFS_DARWIN_ENV */
-#endif /* AFS_LINUX20_ENV */
-#endif /* AFS_SGI64_ENV */
-#endif /* AFS_HPUX101_ENV */
-#endif /* AFS_AIX41_ENV */
-#endif
-
-/* all locks wait on excl_locked except for READ_LOCK, which waits on readers_reading */
-struct afs_lock {
- unsigned char wait_states; /* type of lockers waiting */
- unsigned char excl_locked; /* anyone have boosted, shared or write lock? */
- unsigned short readers_reading; /* # readers actually with read locks */
- unsigned short num_waiting; /* probably need this soon */
- unsigned short spare; /* not used now */
- osi_timeval_t time_waiting; /* for statistics gathering */
-#if defined(INSTRUMENT_LOCKS)
- /* the following are useful for debugging
- ** the field 'src_indicator' is updated only by ObtainLock() and
- ** only for writes/shared locks. Hence, it indictes where in the
- ** source code the shared/write lock was set.
- */
- unsigned int pid_last_reader; /* proceess id of last reader */
- unsigned int pid_writer; /* process id of writer, else 0 */
- unsigned int src_indicator; /* third param to ObtainLock() */
-#endif /* INSTRUMENT_LOCKS */
-};
-typedef struct afs_lock afs_lock_t;
-typedef struct afs_lock afs_rwlock_t;
-
-#define READ_LOCK 1
-#define WRITE_LOCK 2
-#define SHARED_LOCK 4
-/* this next is not a flag, but rather a parameter to Afs_Lock_Obtain */
-#define BOOSTED_LOCK 6
-
-/* next defines wait_states for which we wait on excl_locked */
-#define EXCL_LOCKS (WRITE_LOCK|SHARED_LOCK)
-
-#ifdef KERNEL
-#include "icl.h"
-
-extern int afs_trclock;
-
-#define AFS_LOCK_TRACE_ENABLE 0
-#if AFS_LOCK_TRACE_ENABLE
-#define AFS_LOCK_TRACE(op, lock, type) \
- if (afs_trclock) Afs_Lock_Trace(op, lock, type, __FILE__, __LINE__);
-#else
-#define AFS_LOCK_TRACE(op, lock, type)
-#endif
-
-#if defined(INSTRUMENT_LOCKS)
-
-#define ObtainReadLock(lock)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, READ_LOCK);\
- if (!((lock)->excl_locked & WRITE_LOCK)) \
- ((lock)->readers_reading)++; \
- else \
- Afs_Lock_Obtain(lock, READ_LOCK); \
- (lock)->pid_last_reader = MyPidxx; \
- ENDMAC
-
-#define ObtainWriteLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, WRITE_LOCK);\
- if (!(lock)->excl_locked && !(lock)->readers_reading)\
- (lock) -> excl_locked = WRITE_LOCK;\
- else\
- Afs_Lock_Obtain(lock, WRITE_LOCK); \
- (lock)->pid_writer = MyPidxx; \
- (lock)->src_indicator = src;\
- ENDMAC
-
-#define NBObtainWriteLock(lock, src) (((lock)->excl_locked || (lock)->readers_reading) ? EWOULDBLOCK : (((lock) -> excl_locked = WRITE_LOCK), ((lock)->pid_writer = MyPidxx), ((lock)->src_indicator = src), 0))
-
-#define ObtainSharedLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, SHARED_LOCK);\
- if (!(lock)->excl_locked)\
- (lock) -> excl_locked = SHARED_LOCK;\
- else\
- Afs_Lock_Obtain(lock, SHARED_LOCK); \
- (lock)->pid_writer = MyPidxx; \
- (lock)->src_indicator = src;\
- ENDMAC
-
-#define NBObtainSharedLock(lock, src) (((lock)->excl_locked) ? EWOULDBLOCK : (((lock) -> excl_locked = SHARED_LOCK), ((lock)->pid_writer = MyPidxx), ((lock)->src_indicator = src), 0))
-
-#define UpgradeSToWLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, BOOSTED_LOCK);\
- if (!(lock)->readers_reading)\
- (lock)->excl_locked = WRITE_LOCK;\
- else\
- Afs_Lock_Obtain(lock, BOOSTED_LOCK); \
- (lock)->pid_writer = MyPidxx; \
- (lock)->src_indicator = src;\
- ENDMAC
-
-/* this must only be called with a WRITE or boosted SHARED lock! */
-#define ConvertWToSLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, SHARED_LOCK);\
- (lock)->excl_locked = SHARED_LOCK; \
- if((lock)->wait_states) \
- Afs_Lock_ReleaseR(lock); \
- ENDMAC
-
-#define ConvertWToRLock(lock) \
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, READ_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- ((lock)->readers_reading)++;\
- (lock)->pid_last_reader = MyPidxx ; \
- (lock)->pid_writer = 0;\
- Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-#define ConvertSToRLock(lock) \
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, READ_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- ((lock)->readers_reading)++;\
- (lock)->pid_last_reader = MyPidxx ; \
- (lock)->pid_writer = 0;\
- Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-#define ReleaseReadLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, READ_LOCK);\
- if (!(--((lock)->readers_reading)) && (lock)->wait_states)\
- Afs_Lock_ReleaseW(lock) ; \
- if ( (lock)->pid_last_reader == MyPidxx ) \
- (lock)->pid_last_reader =0;\
- ENDMAC
-
-#define ReleaseWriteLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, WRITE_LOCK);\
- (lock)->excl_locked &= ~WRITE_LOCK;\
- if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
- (lock)->pid_writer=0; \
- ENDMAC
-
-/* can be used on shared or boosted (write) locks */
-#define ReleaseSharedLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, SHARED_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
- (lock)->pid_writer=0; \
- ENDMAC
-
-#else /* INSTRUMENT_LOCKS */
-
-#define ObtainReadLock(lock)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, READ_LOCK);\
- if (!((lock)->excl_locked & WRITE_LOCK)) \
- ((lock)->readers_reading)++; \
- else \
- Afs_Lock_Obtain(lock, READ_LOCK); \
- ENDMAC
-
-#define ObtainWriteLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, WRITE_LOCK);\
- if (!(lock)->excl_locked && !(lock)->readers_reading)\
- (lock) -> excl_locked = WRITE_LOCK;\
- else\
- Afs_Lock_Obtain(lock, WRITE_LOCK); \
- ENDMAC
-
-#define NBObtainWriteLock(lock, src) (((lock)->excl_locked || (lock)->readers_reading) ? EWOULDBLOCK : (((lock) -> excl_locked = WRITE_LOCK), 0))
-
-#define ObtainSharedLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, SHARED_LOCK);\
- if (!(lock)->excl_locked)\
- (lock) -> excl_locked = SHARED_LOCK;\
- else\
- Afs_Lock_Obtain(lock, SHARED_LOCK); \
- ENDMAC
-
-#define NBObtainSharedLock(lock, src) (((lock)->excl_locked) ? EWOULDBLOCK : (((lock) -> excl_locked = SHARED_LOCK), 0))
-
-#define UpgradeSToWLock(lock, src)\
- BEGINMAC \
- AFS_LOCK_TRACE(CM_TRACE_LOCKOBTAIN, lock, BOOSTED_LOCK);\
- if (!(lock)->readers_reading)\
- (lock)->excl_locked = WRITE_LOCK;\
- else\
- Afs_Lock_Obtain(lock, BOOSTED_LOCK); \
- ENDMAC
-
-/* this must only be called with a WRITE or boosted SHARED lock! */
-#define ConvertWToSLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, SHARED_LOCK);\
- (lock)->excl_locked = SHARED_LOCK; \
- if((lock)->wait_states) \
- Afs_Lock_ReleaseR(lock); \
- ENDMAC
-
-#define ConvertWToRLock(lock) \
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, READ_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- ((lock)->readers_reading)++;\
- Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-#define ConvertSToRLock(lock) \
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDOWN, lock, READ_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- ((lock)->readers_reading)++;\
- Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-#define ReleaseReadLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, READ_LOCK);\
- if (!(--((lock)->readers_reading)) && (lock)->wait_states)\
- Afs_Lock_ReleaseW(lock) ; \
- ENDMAC
-
-#define ReleaseWriteLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, WRITE_LOCK);\
- (lock)->excl_locked &= ~WRITE_LOCK;\
- if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-/* can be used on shared or boosted (write) locks */
-#define ReleaseSharedLock(lock)\
- BEGINMAC\
- AFS_LOCK_TRACE(CM_TRACE_LOCKDONE, lock, SHARED_LOCK);\
- (lock)->excl_locked &= ~(SHARED_LOCK | WRITE_LOCK);\
- if ((lock)->wait_states) Afs_Lock_ReleaseR(lock);\
- ENDMAC
-
-#endif /* INSTRUMENT_LOCKS */
-
-/* I added this next macro to make sure it is safe to nuke a lock -- Mike K. */
-#define LockWaiters(lock)\
- ((int) ((lock)->num_waiting))
-
-#define CheckLock(lock)\
- ((lock)->excl_locked? (int) -1 : (int) (lock)->readers_reading)
-
-#define WriteLocked(lock)\
- ((lock)->excl_locked & WRITE_LOCK)
-#endif
-
-/*
-
-You can also use the lock package for handling parent locks for independently-lockable sets of
-small objects. The concept here is that the parent lock is at the same level in the
-locking hierarchy as the little locks, but certain restrictions apply.
-
-The general usage pattern is as follows. You have a set of entries to search. When searching it, you
-have a "scan" lock on the table. If you find what you're looking for, you drop the lock down
-to a "hold" lock, lock the entry, and release the parent lock. If you don't find what
-you're looking for, you create the entry, downgrade the "scan" lock to a "hold" lock,
-lock the entry and unlock the parent.
-
-To delete an item from the table, you initially obtain a "purge" lock on the parent. Unlike all
-of the other parent lock modes described herein, in order to obtain a "purge" lock mode, you
-must have released all locks on any items in the table. Once you have obtained the parent
-lock in "purge" mode, you should check to see if the entry is locked. If its not locked, you
-are free to delete the entry, knowing that no one else can attempt to obtain a lock
-on the entry while you have the purge lock held on the parent. Unfortunately, if it *is* locked,
-you can not lock it yourself and wait for the other dude to release it, since the entry's locker
-may need to lock another entry before unlocking the entry you want (which would result in
-deadlock). Instead, then, you must release the parent lock, and try again "later" (see Lock_Wait
-for assistance in waiting until later). Unfortunately, this is the best locking paradigm I've yet
-come up with.
-
-What are the advantages to this scheme? First, the use of the parent lock ensures that
-two people don't try to add the same entry at the same time or delete an entry while someone
-else is adding it. It also ensures that when one process is deleting an entry, no one else is
-preparing to lock the entry. Furthermore, when obtaining a lock on a little entry, you
-are only holding a "hold" lock on the parent lock, so that others may come in and search
-the table during this time. Thus it will not hold up the system if a little entry takes
-a great deal of time to free up.
-
-Here's how to compute the compatibility matrix:
-
-The invariants are:
-
-add no deletions, additions allowed, additions will be performed, will obtain little locks
-hold no deletions, additions allowed, no additions will be performed, will obtain little locks
-purge no deletions or additions allowed, deletions will be performed, don't obtain little locks
-
-When we compute the locking matrix, we note that hold is compatible with hold and add.
-Add is compatible only with hold. purge is not compatible with anything. This is the same
-matrix as obtained by mapping add->S, hold->read and purge->write locks. Thus we
-can use the locks above to solve this problem, and we do.
-
-*/
-
-#endif /* __AFSLOCK_INCLUDE__ */
+++ /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
- */
-
-#ifndef _longc_procs_h_
-#define _longc_procs_h_ 1
-
-#if !defined(LONGCALL_DEFS) && defined(KERNEL) && defined(DYNEL) && (defined(AFS_DEC_ENV) || defined(AFS_DECOSF_ENV))
-
-#define LONGCALL_DEFS
-
-struct afs_longcall_procs {
- int (*LC_xdr_u_short) ();
- int (*LC_xdr_short) ();
- int (*LC_xdr_opaque) ();
- int (*LC_xdr_array) ();
- int (*LC_xdr_bytes) ();
- int (*LC_xdr_u_long) ();
- int (*LC_xdr_string) ();
- int (*LC_xdr_long) ();
- int (*LC_xdr_int) ();
- int (*LC_xdr_u_int) ();
- int (*LC_ioctl) ();
- int (*LC_copyout) ();
- int (*LC_biodone) ();
- int (*LC_ureadc) ();
- int (*LC_strcmp) ();
- int (*LC_uiomove) ();
- int (*LC_uprintf) ();
- int (*LC_strncpy) ();
- int (*LC_flock) ();
- int (*LC_setgroups) ();
- struct ucred *(*LC_crcopy) ();
- struct ucred *(*LC_crget) ();
- int (*LC_crhold) ();
- int (*LC_ip_stripoptions) ();
- int (*LC_in_cksum) ();
- struct mbuf *(*LC_m_pullup) ();
- int (*LC_resettodr) ();
- int (*LC_untimeout) ();
- int (*LC_timeout) ();
- int (*LC_mpurge) ();
- int (*LC_xrele) ();
- int (*LC_m_free) ();
- int (*LC_m_clalloc) ();
- int (*LC_splimp) ();
- int (*LC_m_freem) ();
- int (*LC_soclose) ();
- int (*LC_sobind) ();
- struct mbuf *(*LC_m_get) ();
- int (*LC_socreate) ();
- int (*LC_soreserve) ();
-#if defined(AFS_DECOSF_ENV)
- int (*LC_getf) ();
-#else /* AFS_DECOSF_ENV */
- struct file *(*LC_getf) ();
-#endif
- int (*LC_splx) ();
- int (*LC_microtime) ();
- int (*LC_splnet) ();
- int (*LC_bcmp) ();
-#ifdef XDR_CHAR_IN_KERNEL
- int (*LC_xdr_char) ();
-#endif
-#ifdef AFS_DEC_ENV
-
- int (*LC_gfs_unlock) ();
- int (*LC_gfs_lock) ();
- int (*LC_gput) ();
- struct inode *(*LC_ufs_galloc) ();
- int (*LC_gno_close) ();
- int (*LC_km_alloc) ();
- int (*LC_km_free) ();
-
- int (*LC_nuxi_l) ();
- int (*LC_nuxi_s) ();
-
- struct inode *(*LC_gfs_gget) ();
- int (*LC_binval) ();
- int (*LC_splclock) ();
- int (*LC_xumount) ();
- int (*LC_bflush) ();
- int (*LC_blkclr) ();
- int (*LC_vmaccess) ();
- struct gnode *(*LC_gfs_namei) ();
- int (*LC_getpdev) ();
- int (*LC_check_mountp) ();
- int (*LC_access) ();
- int (*LC_ovbcopy) ();
- int (*LC_groupmember) ();
- int (*LC_imin) ();
- int (*LC_setjmp) ();
-
- struct gnode *(*LC_gget) ();
- void (*LC_grele) ();
- void (*LC_gref) ();
- int (*LC_xdr_char) ();
- int (*LC_smp_lock_once) ();
- int (*LC_smp_lock_long) ();
- int (*LC_smp_lock_retry) ();
- int (*LC_smp_unlock_long) ();
- int (*LC_smp_owner) ();
- int (*LC_xinval) ();
- int (*LC_cacheinvalall) ();
- int (*LC_psignal) ();
- int (*LC_ufs_rwgp_lock) ();
-#else
- int (*LC_iunlock) ();
- int (*LC_ilock) ();
- int (*LC_iput) ();
- struct inode *(*LC_ialloc) ();
- int (*LC_vno_close) ();
- int (*LC_kmem_alloc) ();
- int (*LC_kmem_free) ();
-
- int (*LC_m_cpytoc) ();
-
- int (*LC_ufs_brelse) ();
- int (*LC_lookupname) ();
- int (*LC_vn_rele) ();
- int (*LC_vn_rdwr) ();
- int (*LC_mapout) ();
- struct mount *(*LC_getmp) ();
- struct inode *(*LC_iget) ();
- struct mbuf *(*LC_m_more) ();
- int (*LC__spl1) ();
-#endif
- int (*LC_rdwri) ();
- struct file *(*LC_falloc) ();
- int (*LC_rmfree) ();
- int (*LC_mapin) ();
- long (*LC_rmalloc) ();
- struct pte *(*LC_vtopte) ();
- int (*LC_vattr_null) ();
- int (*LC_strlen) ();
- int (*LC_bcopy) ();
- int (*LC_brelse) ();
- struct buf *(*LC_geteblk) ();
- int (*LC_panic) ();
- int (*LC_strcpy) ();
- int (*LC_printf) ();
- int (*LC_copyinstr) ();
- int (*LC_copyin) ();
- int (*LC_sleep) ();
- int (*LC_wakeup) ();
- int (*LC_bzero) ();
- int (*LC_suser) ();
- int (*LC_crfree) ();
-#if 0
- int (*LC_igetinode) ();
-#endif
-#if defined(AFS_DECOSF_ENV)
- void (*LC_assert_wait) ();
- int (*LC_closef) ();
- int (*LC_fake_inode_init) ();
- int (*LC_getnewvnode) ();
- struct mount *(*LC_getvfs) ();
- int (*LC_idrop) ();
- int (*LC_insmntque) ();
- int (*LC_ioctl_base) ();
- caddr_t(*LC_kalloc) ();
- void (*LC_kfree) ();
- void (*LC_lock_done) ();
- struct mbuf *(*LC_m_getclr) ();
- struct mbuf *(*LC_m_retry) ();
- struct mbuf *(*LC_m_retryhdr) ();
- int (*LC_mpsleep) ();
- int (*LC_namei) ();
- unsigned int (*LC_nuxi_32) ();
- unsigned short (*LC_nuxi_16) ();
- int (*LC_setgroups_base) ();
- int (*LC_substitute_real_creds) ();
- int (*LC_swap_ipl) ();
- void (*LC_thread_block) ();
- /* XXX - should be kern_return_t */
- int (*LC_u_vp_create) ();
- int (*LC_ubc_bufalloc) ();
- int (*LC_ubc_flush_sync) ();
- int (*LC_ubc_invalidate) ();
- int (*LC_ubc_lookup) ();
- int (*LC_ubc_page_dirty) ();
- int (*LC_ubc_page_release) ();
- int (*LC_ubc_sync_iodone) ();
- int (*LC_vgetm) ();
- int (*LC_vgone) ();
- int (*LC_vn_close) ();
-/*
- int (*LC_vn_ioctl) ();
- int (*LC_vn_read) ();
- int (*LC_vn_select) ();
- int (*LC_vn_write) ();
-*/
- void (*LC_vrele) ();
- int (*LC_xdr_char) ();
-#endif /* AFS_DECOSF_ENV */
-};
-extern struct afs_longcall_procs afs_longcall_procs;
-
-#ifndef LONGCALL_NO_MACROS
-
-#if defined(AFS_DECOSF_ENV)
-#undef kmem_alloc
-#undef kmem_free
-#endif /* AFS_DECOSF_ENV */
-
-#define crfree (*afs_longcall_procs.LC_crfree)
-#define suser (*afs_longcall_procs.LC_suser)
-#define bzero (*afs_longcall_procs.LC_bzero)
-#define wakeup (*afs_longcall_procs.LC_wakeup)
-#if !defined(AFS_DECOSF_ENV)
-#define sleep (*afs_longcall_procs.LC_sleep)
-#endif
-#define copyin (*afs_longcall_procs.LC_copyin)
-#define copyinstr (*afs_longcall_procs.LC_copyinstr)
-#define printf (*afs_longcall_procs.LC_printf)
-#define panic (*afs_longcall_procs.LC_panic)
-#define geteblk (*afs_longcall_procs.LC_geteblk)
-#define brelse (*afs_longcall_procs.LC_brelse)
-#define bcopy (*afs_longcall_procs.LC_bcopy)
-#define strlen (*afs_longcall_procs.LC_strlen)
-#define vtopte (*afs_longcall_procs.LC_vtopte)
-#define rmalloc (*afs_longcall_procs.LC_rmalloc)
-
-#define mapin (*afs_longcall_procs.LC_mapin)
-#define strcpy (*afs_longcall_procs.LC_strcpy)
-#define strncpy (*afs_longcall_procs.LC_strncpy)
-
-#define rmfree (*afs_longcall_procs.LC_rmfree)
-#define falloc (*afs_longcall_procs.LC_falloc)
-#define rdwri (*afs_longcall_procs.LC_rdwri)
-
-#ifdef XDR_CHAR_IN_KERNEL
-#define xdr_char (*afs_longcall_procs.LC_xdr_char)
-#endif
-
-#ifdef AFS_DEC_ENV
-#define psignal (*afs_longcall_procs.LC_psignal)
-#define ufs_rwgp_lock (*afs_longcall_procs.LC_ufs_rwgp_lock)
-#define gput (*afs_longcall_procs.LC_gput)
-#define ufs_galloc (*afs_longcall_procs.LC_ufs_galloc)
-#define gno_close (*afs_longcall_procs.LC_gno_close)
-
-#define km_alloc (*afs_longcall_procs.LC_km_alloc)
-#define km_free (*afs_longcall_procs.LC_km_free)
-
-#define nuxi_l (*afs_longcall_procs.LC_nuxi_l)
-#define nuxi_s (*afs_longcall_procs.LC_nuxi_s)
-
-#define gfs_gget (*afs_longcall_procs.LC_gfs_gget)
-#define binval (*afs_longcall_procs.LC_binval)
-#define splclock (*afs_longcall_procs.LC_splclock)
-#define xumount (*afs_longcall_procs.LC_xumount)
-#define bflush (*afs_longcall_procs.LC_bflush)
-#define blkclr (*afs_longcall_procs.LC_blkclr)
-#define vmaccess (*afs_longcall_procs.LC_vmaccess)
-#define gfs_namei (*afs_longcall_procs.LC_gfs_namei)
-#define getpdev (*afs_longcall_procs.LC_getpdev)
-#define check_mountp (*afs_longcall_procs.LC_check_mountp)
-#define access (*afs_longcall_procs.LC_access)
-#define ovbcopy (*afs_longcall_procs.LC_ovbcopy)
-#define groupmember (*afs_longcall_procs.LC_groupmember)
-#define imin (*afs_longcall_procs.LC_imin)
-#define setjmp (*afs_longcall_procs.LC_setjmp)
-#define gget (*afs_longcall_procs.LC_gget)
-#define grele (*afs_longcall_procs.LC_grele)
-#define gref (*afs_longcall_procs.LC_gref)
-#define xdr_char (*afs_longcall_procs.LC_xdr_char)
-#define smp_lock_once (*afs_longcall_procs.LC_smp_lock_once)
-#define smp_lock_long (*afs_longcall_procs.LC_smp_lock_long)
-#define smp_lock_retry (*afs_longcall_procs.LC_smp_lock_retry)
-#define smp_unlock_long (*afs_longcall_procs.LC_smp_unlock_long)
-#define smp_owner (*afs_longcall_procs.LC_smp_owner)
-#define xinval (*afs_longcall_procs.LC_xinval)
-#define cacheinvalall (*afs_longcall_procs.LC_cacheinvalall)
-#else
-#define iunlock (*afs_longcall_procs.LC_iunlock)
-#define ilock (*afs_longcall_procs.LC_ilock)
-#define iput (*afs_longcall_procs.LC_iput)
-#define ialloc (*afs_longcall_procs.LC_ialloc)
-#if !defined(AFS_DECOSF_ENV)
-#define vno_close (*afs_longcall_procs.LC_vno_close)
-#endif
-#define kmem_alloc (*afs_longcall_procs.LC_kmem_alloc)
-#define kmem_free (*afs_longcall_procs.LC_kmem_free)
-
-#define m_cpytoc (*afs_longcall_procs.LC_m_cpytoc)
-
-#define ufs_brelse (*afs_longcall_procs.LC_ufs_brelse)
-#if !defined(AFS_DECOSF_ENV)
-#define lookupname (*afs_longcall_procs.LC_lookupname)
-#endif
-/* #define vn_rele (*afs_longcall_procs.LC_vn_rele) */
-#define mapout (*afs_longcall_procs.LC_mapout)
-#define getmp (*afs_longcall_procs.LC_getmp)
-#define iget (*afs_longcall_procs.LC_iget)
-#define m_more (*afs_longcall_procs.LC_m_more)
-#define _spl1 (*afs_longcall_procs.LC__spl1)
-#endif
-
-#define bcmp (*afs_longcall_procs.LC_bcmp)
-#if !defined(AFS_DECOSF_ENV)
-#define splnet (*afs_longcall_procs.LC_splnet)
-#define splx (*afs_longcall_procs.LC_splx)
-#endif
-#define microtime (*afs_longcall_procs.LC_microtime)
-/* #define ldiv$$ (*afs_longcall_procs[34]) */
-#define getf (*afs_longcall_procs.LC_getf)
-#define soreserve (*afs_longcall_procs.LC_soreserve)
-#define socreate (*afs_longcall_procs.LC_socreate)
-#define m_get (*afs_longcall_procs.LC_m_get)
-#define sobind (*afs_longcall_procs.LC_sobind)
-#define soclose (*afs_longcall_procs.LC_soclose)
-#define m_freem (*afs_longcall_procs.LC_m_freem)
-#if !defined(AFS_DECOSF_ENV)
-#define splimp (*afs_longcall_procs.LC_splimp)
-#endif
-#define m_clalloc (*afs_longcall_procs.LC_m_clalloc)
-#define m_free (*afs_longcall_procs.LC_m_free)
-#define xrele (*afs_longcall_procs.LC_xrele)
-#define mpurge (*afs_longcall_procs.LC_mpurge)
-/* #define lmul$$ (*afs_longcall_procs[48]) */
-/* #define timeout (*afs_longcall_procs.LC_timeout) */
-#define untimeout (*afs_longcall_procs.LC_untimeout)
-#define resettodr (*afs_longcall_procs.LC_resettodr)
-#define m_pullup (*afs_longcall_procs.LC_m_pullup)
-#define ip_stripoptions (*afs_longcall_procs.LC_ip_stripoptions)
-#define in_cksum (*afs_longcall_procs.LC_in_cksum)
-#define crcopy (*afs_longcall_procs.LC_crcopy)
-#if !defined(AFS_DECOSF_ENV)
-#define crhold (*afs_longcall_procs.LC_crhold)
-#endif
-#define crget (*afs_longcall_procs.LC_crget)
-#define setgroups (*afs_longcall_procs.LC_setgroups)
-/* #define flock (*afs_longcall_procs.LC_flock) */
-#define uprintf (*afs_longcall_procs.LC_uprintf)
-#define uiomove (*afs_longcall_procs.LC_uiomove)
-#define strcmp (*afs_longcall_procs.LC_strcmp)
-#define ureadc (*afs_longcall_procs.LC_ureadc)
-#define biodone (*afs_longcall_procs.LC_biodone)
-/* #define uldiv$$ (*afs_longcall_procs[68]) */
-#define copyout (*afs_longcall_procs.LC_copyout)
-#define ioctl (*afs_longcall_procs.LC_ioctl)
-#define xdr_int (*afs_longcall_procs.LC_xdr_int)
-#define xdr_long (*afs_longcall_procs.LC_xdr_long)
-#define xdr_string (*afs_longcall_procs.LC_xdr_string)
-#define xdr_u_long (*afs_longcall_procs.LC_xdr_u_long)
-#define xdr_u_int (*afs_longcall_procs.LC_xdr_u_int)
-#define xdr_bytes (*afs_longcall_procs.LC_xdr_bytes)
-#define xdr_array (*afs_longcall_procs.LC_xdr_array)
-#define xdr_opaque (*afs_longcall_procs.LC_xdr_opaque)
-#define xdr_short (*afs_longcall_procs.LC_xdr_short)
-#define xdr_u_short (*afs_longcall_procs.LC_xdr_u_short)
-
-#if defined(AFS_DECOSF_ENV)
-#define assert_wait (*afs_longcall_procs.LC_assert_wait)
-#define closef (*afs_longcall_procs.LC_closef)
-#define fake_inode_init (*afs_longcall_procs.LC_fake_inode_init)
-#define getnewvnode (*afs_longcall_procs.LC_getnewvnode)
-#define getvfs (*afs_longcall_procs.LC_getvfs)
-#define idrop (*afs_longcall_procs.LC_idrop)
-#define insmntque (*afs_longcall_procs.LC_insmntque)
-#define ioctl_base (*afs_longcall_procs.LC_ioctl_base)
-#define kalloc (*afs_longcall_procs.LC_kalloc)
-#define kfree (*afs_longcall_procs.LC_kfree)
-#define lock_done (*afs_longcall_procs.LC_lock_done)
-#define m_getclr (*afs_longcall_procs.LC_m_getclr)
-#define m_retry (*afs_longcall_procs.LC_m_retry)
-#define m_retryhdr (*afs_longcall_procs.LC_m_retryhdr)
-#define mpsleep (*afs_longcall_procs.LC_mpsleep)
-#define namei (*afs_longcall_procs.LC_namei)
-#define nuxi_32 (*afs_longcall_procs.LC_nuxi_32)
-#define nuxi_16 (*afs_longcall_procs.LC_nuxi_16)
-#define setgroups_base (*afs_longcall_procs.LC_setgroups_base)
-#define substitute_real_creds (*afs_longcall_procs.LC_substitute_real_creds)
-#define swap_ipl (*afs_longcall_procs.LC_swap_ipl)
-#define thread_block (*afs_longcall_procs.LC_thread_block)
-#define u_vp_create (*afs_longcall_procs.LC_u_vp_create)
-#define ubc_bufalloc (*afs_longcall_procs.LC_ubc_bufalloc)
-#define ubc_flush_sync (*afs_longcall_procs.LC_ubc_flush_sync)
-#define ubc_invalidate (*afs_longcall_procs.LC_ubc_invalidate)
-#define ubc_lookup (*afs_longcall_procs.LC_ubc_lookup)
-#define ubc_page_dirty (*afs_longcall_procs.LC_ubc_page_dirty)
-#define ubc_page_release (*afs_longcall_procs.LC_ubc_page_release)
-#define ubc_sync_iodone (*afs_longcall_procs.LC_ubc_sync_iodone)
-#define vgetm (*afs_longcall_procs.LC_vgetm)
-#define vgone (*afs_longcall_procs.LC_vgone)
-#define vn_close (*afs_longcall_procs.LC_vn_close)
-/*
-#define vn_ioctl (*afs_longcall_procs.LC_vn_ioctl)
-#define vn_read (*afs_longcall_procs.LC_vn_read)
-#define vn_select (*afs_longcall_procs.LC_vn_select)
-#define vn_write (*afs_longcall_procs.LC_vn_write)
-*/
-#define vrele (*afs_longcall_procs.LC_vrele)
-#define xdr_char (*afs_longcall_procs.LC_xdr_char)
-#endif /* AFS_DECOSF_ENV */
-
-#endif /* LONGCALL_NO_MACROS */
-
-#endif
-#endif
+++ /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
- */
-
-#ifndef __NFSCLIENT__
-#define __NFSCLIENT__
-
-#define NNFSCLIENTS 32 /* Hash table size for afs_nfspags table */
-#define NHash(host) ((host) & (NNFSCLIENTS-1))
-#define NFSCLIENTGC (24*3600) /* time after which to GC nfsclientpag structs */
-#define NFSXLATOR_CRED 0xaaaa
-
-struct nfsclientpag {
- /* From here to .... */
- struct nfsclientpag *next; /* Next hash pointer */
- struct exporterops *nfs_ops;
- afs_int32 states;
- afs_int32 type;
- struct exporterstats nfs_stats;
- /* .... here is also an overlay to the afs_exporter structure */
-
- afs_int32 refCount; /* Ref count for packages using this */
- afs_int32 uid; /* search based on uid and ... */
- afs_int32 host; /* ... nfs client's host ip address */
- afs_int32 pag; /* active pag for all (uid, host) "unpaged" conns */
- char *sysname[MAXNUMSYSNAMES];/* user's "@sys" value; also kept in unixuser */
- int sysnamecount; /* number of sysnames */
- afs_int32 lastcall; /* Used for timing out nfsclientpag structs */
-};
-
-
-#endif /* __NFSCLIENT__ */
+++ /dev/null
-/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef AFS_SYSCTL_H
-#define AFS_SYSCTL_H
-
-/* top level AFS names */
-#define AFS_SC_ALL 0
-#define AFS_SC_DARWIN 1
-
-/* AFS_SC_ALL: platform-independent sysctls */
- /* nothing defined */
-
-/* AFS_SC_DARWIN: darwin-specific sysctls */
-#define AFS_SC_DARWIN_ALL 0
-#define AFS_SC_DARWIN_12 1
-#define AFS_SC_DARWIN_13 2
-#define AFS_SC_DARWIN_14 3
-#define AFS_SC_DARWIN_60 4
-#define AFS_SC_DARWIN_70 5
-
-/* AFS_SC_DARWIN_ALL: darwin version-independent sysctls */
-#define AFS_SC_DARWIN_ALL_REALMODES 1
-
-/* AFS_SC_DARWIN_12: darwin 1.2 sysctls */
- /* nothing defined */
-
-/* AFS_SC_DARWIN_13: darwin 1.3 sysctls */
- /* nothing defined */
-
-/* AFS_SC_DARWIN_14: darwin 1.4 sysctls */
- /* nothing defined */
-
-/* AFS_SC_DARWIN_60: darwin 6.x sysctls */
- /* nothing defined */
-
-/* AFS_SC_DARWIN_70: darwin 7.x sysctls */
- /* nothing defined */
-
-#endif /* AFS_SYSCTL_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
- */
-
-#ifdef UKERNEL
-#include <UKERNEL/sysincludes.h>
-#else
-
-#ifndef __AFS_SYSINCLUDESH__
-#define __AFS_SYSINCLUDESH__ 1
-
-#ifdef AFS_OBSD_ENV
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/lock.h>
-#include <sys/queue.h>
-#include <sys/resourcevar.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/time.h>
-#include <sys/filedesc.h>
-#include <sys/file.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/dirent.h>
-#include <sys/user.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/stat.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <ufs/ffs/fs.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/extattr.h>
-#include <ufs/ufs/ufsmount.h>
-#ifndef MLEN
-#include <sys/mbuf.h>
-#include <net/if.h>
-#endif
-#include <sys/protosw.h>
-#include <sys/ioctl.h>
-#include <sys/timeout.h>
-#else /* AFS_OBSD_ENV */
-#ifdef AFS_LINUX22_ENV
-#include <linux/version.h>
-#include <linux/config.h>
-#include <linux/linkage.h>
-#include <linux/limits.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/vfs.h>
-#include <linux/net.h>
-#include <linux/kdev_t.h>
-#include <linux/ioctl.h>
-#if defined(AFS_LINUX26_ENV)
-#include <linux/backing-dev.h>
-#include <linux/pagemap.h>
-#include <linux/namei.h>
-#endif
-/* Avoid conflicts with coda overloading AFS type namespace. Must precede
- * inclusion of uaccess.h.
- */
-#define _LINUX_CODA_FS_I
-#define _CFS_HEADER_
-struct coda_inode_info {
-};
-#define _LINUX_XFS_FS_I
-struct xfs_inode_info {
-};
-#include <asm/uaccess.h>
-#include <linux/list.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/quota.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <asm/semaphore.h>
-#include <linux/errno.h>
-#ifdef COMPLETION_H_EXISTS
-#include <linux/completion.h>
-#endif
-
-#else /* AFS_LINUX22_ENV */
-#if defined(AFS_DARWIN_ENV)
-#ifndef _MACH_ETAP_H_
-#define _MACH_ETAP_H_
-typedef unsigned short etap_event_t;
-#endif
-#endif
-#if !defined(AFS_OSF_ENV)
-#include "h/errno.h"
-#include "h/types.h"
-#include "h/param.h"
-
-#ifdef AFS_AUX_ENV
-#ifdef PAGING
-#include "h/mmu.h"
-#include "h/seg.h"
-#include "h/page.h"
-#include "h/region.h"
-#endif /* PAGING */
-#include "h/sysmacros.h"
-#include "h/signal.h"
-#include "h/var.h"
-#endif /* AFS_AUX_ENV */
-
-#include "h/systm.h"
-#include "h/time.h"
-
-#ifdef AFS_AIX_ENV
-#ifdef AFS_AIX41_ENV
-#include "sys/statfs.h"
-#endif
-#ifdef AFS_AIX51_ENV
-#include "sys/acl.h"
-#endif
-#include "../h/file.h"
-#include "../h/fullstat.h"
-#include "../h/vattr.h"
-#include "../h/var.h"
-#include "../h/access.h"
-#endif /* AFS_AIX_ENV */
-
-#if defined(AFS_SGI_ENV)
-#include "values.h"
-#include "sys/sema.h"
-#include "sys/cmn_err.h"
-#ifdef AFS_SGI64_ENV
-#include <ksys/behavior.h>
-#endif /* AFS_SGI64_ENV */
-#include "fs/efs_inode.h"
-#ifdef AFS_SGI_EFS_IOPS_ENV
-#include "sgiefs/efs.h"
-#endif
-#include "sys/kmem.h"
-#include "sys/cred.h"
-#include "sys/resource.h"
-
-/*
- * ../sys/debug.h defines ASSERT(), but it is nontrivial only if DEBUG
- * is on (see afs_osi.h).
- * In IRIX 6.5 we cannot have DEBUG turned on since certain
- * system-defined structures have different members with DEBUG on, and
- * this breaks our ability to interact with the rest of the kernel.
- *
- * Instead of using ASSERT(), we use our own osi_Assert().
- */
-#if defined(AFS_SGI65_ENV) && !defined(DEBUG)
-#define DEBUG
-#include "sys/debug.h"
-#undef DEBUG
-#else
-#include "sys/debug.h"
-#endif
-
-#include "sys/statvfs.h"
-#include "sys/sysmacros.h"
-#include "sys/fs_subr.h"
-#include "sys/siginfo.h"
-#endif /* AFS_SGI_ENV */
-
-#if !defined(AFS_AIX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV)
-# include "h/kernel.h"
-#endif /* !SUN5 && !SGI */
-
-#ifdef AFS_SUN5_ENV
-#include <sys/cmn_err.h> /* for kernel printf() prototype */
-#endif
-
-#if defined(AFS_SUN56_ENV)
-#include "h/vfs.h" /* stops SUN56 socketvar.h warnings */
-#include "h/stropts.h" /* stops SUN56 socketvar.h warnings */
-#include "h/stream.h" /* stops SUN56 socketvar.h errors */
-#endif
-
-#include "h/socket.h"
-#include "h/socketvar.h"
-#include "h/protosw.h"
-
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_FBSD_ENV)
-# include "h/dirent.h"
-# ifdef AFS_SUN5_ENV
-# include "h/sysmacros.h"
-# include "h/fs/ufs_fsdir.h"
-# endif /* AFS_SUN5_ENV */
-#else
-# include "h/dir.h"
-#endif /* SGI || SUN || HPUX */
-
-#ifdef AFS_DEC_ENV
-# include "h/smp_lock.h"
-#endif /* AFS_DEC_ENV */
-
-
-#if !defined(AFS_SGI64_ENV) && !defined(AFS_FBSD_ENV)
-#include "h/user.h"
-#endif /* AFS_SGI64_ENV */
-#define MACH_USER_API 1
-#if defined(AFS_FBSD50_ENV)
-#include "h/bio.h"
-#include "h/filedesc.h"
-#endif
-#include "h/file.h"
-#include "h/uio.h"
-#include "h/buf.h"
-#include "h/stat.h"
-
-
-/* ----- The following mainly deal with vnodes/inodes stuff ------ */
-#ifdef AFS_DEC_ENV
-# include "h/mount.h"
-# include "machine/psl.h"
-# include "afs/gfs_vnode.h"
-#endif
-
-#ifdef AFS_MACH_ENV
-# include <vfs/vfs.h>
-# include <vfs/vnode.h>
-# include <sys/inode.h>
-# include <sys/mount.h>
-# include <vm/vm_pager.h>
-# include <kern/mfs.h>
-# include <mach/vm_param.h>
-# include <kern/parallel.h>
-#endif /* AFS_MACH_ENV */
-
-#ifndef AFS_DEC_ENV
-# ifdef AFS_SUN5_ENV
-# include "h/statvfs.h"
-# endif /* AFS_SUN5_ENV */
-# ifdef AFS_HPUX_ENV
-struct vfspage; /* for vnode.h compiler warnings */
-# include "h/swap.h" /* for struct swpdbd, for vnode.h compiler warnings */
-# include "h/dbd.h" /* for union idbd, for vnode.h compiler warnings */
-#ifdef AFS_HPUX110_ENV
-# include "h/resource.h"
-#endif
-#ifdef AFS_HPUX1123_ENV
-# include <sys/user.h>
-# include <sys/cred.h>
-#endif
-# endif /* AFS_HPUX_ENV */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-# if defined(AFS_FBSD50_ENV)
-struct vop_getwritemount_args;
-# endif
-# include <sys/uio.h>
-# include <sys/mount.h>
-# include <sys/namei.h>
-# include <sys/vnode.h>
-# include <sys/queue.h>
-# include <sys/malloc.h>
-#ifndef AFS_FBSD_ENV
-# include <sys/ubc.h>
-#define timeout_fcn_t mach_timeout_fcn_t
-# include <kern/sched_prim.h>
-#else
-MALLOC_DECLARE(M_AFS);
-# include <ufs/ufs/dinode.h>
-# include <vm/vm.h>
-# include <vm/vm_extern.h>
-# include <vm/pmap.h>
-# include <vm/vm_map.h>
-# include <sys/lock.h>
-# include <sys/user.h>
-#endif
-#undef timeout_fcn_t
-#define _DIR_H_
-#define doff_t int32_t
-# include <ufs/ufs/quota.h>
-# include <ufs/ufs/inode.h>
-# include <ufs/ffs/fs.h>
-#else
-# include "h/vfs.h"
-# include "h/vnode.h"
-# ifdef AFS_SUN5_ENV
-# include "h/fs/ufs_inode.h"
-# include "h/fs/ufs_mount.h"
-# else
-# if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
-# include "ufs/inode.h"
-# if !defined(AFS_SGI_ENV) && !defined(AFS_HPUX_ENV)
-# include "ufs/mount.h"
-# endif /* !AFS_HPUX_ENV */
-# endif /* !AFS_AIX32_ENV */
-# endif /* AFS_SUN5_ENV */
-#endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
-#endif /* AFS_DEC_ENV */
-
-/* These mainly deal with networking and rpc headers */
-#include "netinet/in.h"
-#undef MFREE /* defined at mount.h for AIX */
-#ifdef AFS_SUN5_ENV
-# include "h/time.h"
-#else
-#if !defined(AFS_HPUX_ENV)
-# include "h/mbuf.h"
-#endif
-#endif /* AFS_SUN5_ENV */
-
-#include "rpc/types.h"
-#include "rx/xdr.h"
-
-#ifdef AFS_AIX32_ENV
-# include "net/spl.h"
-#endif
-
-/* Miscellaneous headers */
-#include "h/proc.h"
-#if !defined(AFS_FBSD_ENV)
-#include "h/ioctl.h"
-#endif /* AFS_FBSD_ENV */
-
-#if defined(AFS_HPUX101_ENV) && !defined(AFS_HPUX1123_ENV)
-#include "h/proc_iface.h"
-#include "h/vas.h"
-#endif
-
-#if defined(AFS_HPUX102_ENV)
-#include "h/unistd.h"
-#include "h/tty.h"
-#endif
-
-#if !defined(AFS_SGI_ENV) && !defined(AFS_SUN_ENV) && !defined(AFS_MACH_ENV) && !defined(AFS_AIX32_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
-
-# include "h/text.h"
-#endif
-
-
-#if defined(AFS_AIX_ENV) || defined(AFS_DEC_ENV)
-# include "h/flock.h" /* fcntl.h is a user-level include in aix */
-#else
-# include "h/fcntl.h"
-#endif /* AIX || DEC */
-
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
-# include "h/unistd.h"
-#endif /* SGI || SUN */
-
-#ifdef AFS_AIX32_ENV
-# include "h/vmuser.h"
-#endif /* AFS_AIX32_ENV */
-
-#if defined(AFS_SUN5_ENV)
-#include <sys/tiuser.h>
-#include <sys/t_lock.h>
-#include <sys/mutex.h>
-#include <sys/vtrace.h>
-#include <sys/pathname.h>
-#include <sys/debug.h>
-#endif
-
-#else /* ! AFS_OSF_ENV */
-/* All of the OSF/1 stuff is here */
-#include <net/net_globals.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/protosw.h>
-#include <ufs/dir.h>
-#include <sys/user.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-#include <ufs/inode.h>
-#include <sys/mount.h>
-#include <vm/vm_page.h>
-#include <mach/vm_param.h>
-#include <kern/parallel.h>
-#include <mach/mach_types.h>
-#ifndef AFS_OSF30_ENV
-#include <kern/mfs.h>
-#endif
-#include <mach/vm_param.h>
-#include <kern/parallel.h>
-
-/* These mainly deal with networking and rpc headers */
-#include <netinet/in.h>
-#include <sys/mbuf.h>
-#include <rpc/types.h>
-
-#ifdef AFS_ALPHA_ENV
-#undef kmem_alloc
-#undef kmem_free
-#undef mem_alloc
-#undef mem_free
-#undef register
-#endif /* AFS_ALPHA_ENV */
-
-#include <rx/xdr.h>
-#include <sys/proc.h>
-#include <sys/ioctl.h>
-
-#endif /* AFS_OSF_ENV */
-#endif /* AFS_LINUX22_ENV */
-#endif /* AFS_OBSD_ENV */
-
-#endif /* __AFS_SYSINCLUDESH__ so idempotent */
-
-#endif
+++ /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
- */
-
-/*
- System: VICE-TWO
- Module: voldefs.h
- Institution: The Information Technology Center, Carnegie-Mellon University
-
- */
-
-/* If you add volume types here, be sure to check the definition of
- volumeWriteable in volume.h */
-
-#define readwriteVolume RWVOL
-#define readonlyVolume ROVOL
-#define backupVolume BACKVOL
-
-#define RWVOL 0
-#define ROVOL 1
-#define BACKVOL 2
-
-/* All volumes will have a volume header name in this format */
-#define VFORMAT "V%010lu.vol"
-#define VMAXPATHLEN 64 /* Maximum length (including null) of a volume
- * external path name */
-
-/* Values for connect parameter to VInitVolumePackage */
-#define CONNECT_FS 1
-#define DONT_CONNECT_FS 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
- */
-
-/*
- System: VICE-TWO
- Module: errors.h
-
- */
-
-/*
- * Vice2 error codes
- * 3/20/85
- * Note: all of the errors listed here are currently generated by the volume
- * package. Other vice error codes, should they be needed, could be included
- * here also.
- */
-
-#define VREADONLY EROFS /* Attempt to write a read-only volume */
-
-/* Special error codes, which may require special handling (other than just
- passing them through directly to the end user) are listed below */
-
-#define VICE_SPECIAL_ERRORS 101 /* Lowest special error code */
-
-#define VSALVAGE 101 /* Volume needs salvage */
-#define VNOVNODE 102 /* Bad vnode number quoted */
-#define VNOVOL 103 /* Volume not attached, doesn't exist,
- * not created or not online */
-#define VVOLEXISTS 104 /* Volume already exists */
-#define VNOSERVICE 105 /* Volume is not in service (i.e. it's
- * is out of funds, is obsolete, or somesuch) */
-#define VOFFLINE 106 /* Volume is off line, for the reason
- * given in the offline message */
-#define VONLINE 107 /* Volume is already on line */
-#define VDISKFULL 108 /* ENOSPC - Partition is "full", i.e. rougly within
- * n% of full */
-#define VOVERQUOTA 109 /* EDQUOT - Volume max quota exceeded */
-#define VBUSY 110 /* Volume temporarily unavailable; try again.
- * The volume should be available again shortly; if
- * it isn't something is wrong. Not normally to be
- * propagated to the application level */
-#define VMOVED 111 /* Volume has moved to another server; do a VGetVolumeInfo
- * to THIS server to find out where */
-
-#define VRESTARTING -100 /* server is restarting, otherwise similar to
- * VBUSY above. This is negative so that old
- * cache managers treat it as "server is down" */