These files are no longer used.
Change-Id: I4a7e0cc8c308399004c999b3769c77388794cfdd
Reviewed-on: http://gerrit.openafs.org/11802
Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
Reviewed-by: Chas Williams <3chas3@gmail.com>
Reviewed-by: Daria Brashear <shadow@your-file-system.com>
Tested-by: Daria Brashear <shadow@your-file-system.com>
+++ /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"
-
-
-#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 */
-
-/* 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 */
-
-#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 */
- new = (void *)(KM_TYPE | (unsigned long)new);
- } else {
- osi_Assert(drop_glock || !haveGlock);
- if (drop_glock && haveGlock)
- AFS_GUNLOCK();
- new = (void *)vmalloc(asize);
- if (drop_glock && haveGlock)
- AFS_GLOCK();
- if (new) /* piggy back alloc type */
- new = (void *)(VM_TYPE | (unsigned long)new);
- }
-
- 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%lx\n",
- (int)MEMTYPE(p), (unsigned long)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%lx, index=%lu\n",
- (int)memtype, (unsigned long)lmp->chunk, (unsigned long)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(void)
-{
- /* 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;
-
-}
-
-/************** 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 */
- error:
- up(&afs_linux_alloc_sem);
- return MEMADDR(new);
-
- free_error:
- if (new) {
- linux_free(new);
- }
- 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");
- BUG();
- }
-
- 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"
-
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-
-cred_t *
-crget(void)
-{
- cred_t *tmp;
-
-#if !defined(GFP_NOFS)
-#define GFP_NOFS GFP_KERNEL
-#endif
- tmp = kmalloc(sizeof(cred_t), GFP_NOFS);
- if (!tmp)
- osi_Panic("crget: No more memory for creds!\n");
-
- tmp->cr_ref = 1;
- return tmp;
-}
-
-void
-crfree(cred_t * cr)
-{
- if (cr->cr_ref > 1) {
- cr->cr_ref--;
- return;
- }
-
- kfree(cr);
-}
-
-
-/* Return a duplicate of the cred. */
-cred_t *
-crdup(cred_t * cr)
-{
- cred_t *tmp = crget();
-
- afs_set_cr_uid(tmp, afs_cr_uid(cr));
- afs_set_cr_ruid(tmp, afs_cr_ruid(cr));
- afs_set_cr_gid(tmp, afs_cr_gid(cr));
- afs_set_cr_rgid(tmp, afs_cr_rgid(cr));
-
- memcpy(tmp->cr_groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- tmp->cr_ngroups = cr->cr_ngroups;
-
- return tmp;
-}
-
-cred_t *
-crref(void)
-{
- cred_t *cr = crget();
-
- afs_set_cr_uid(cr, current_fsuid());
- afs_set_cr_ruid(cr, current_uid());
- afs_set_cr_gid(cr, current_fsgid());
- afs_set_cr_rgid(cr, current_gid());
-
- memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
- cr->cr_ngroups = current->ngroups;
-
- return cr;
-}
-
-
-/* Set the cred info into the current task */
-void
-crset(cred_t * cr)
-{
-#if defined(STRUCT_TASK_STRUCT_HAS_CRED)
- struct cred *new_creds;
-
- /* If our current task doesn't have identical real and effective
- * credentials, commit_cred won't let us change them, so we just
- * bail here.
- */
- if (current->cred != current->real_cred)
- return;
- new_creds = prepare_creds();
- new_creds->fsuid = afs_cr_uid(cr);
- new_creds->uid = afs_cr_ruid(cr);
- new_creds->fsgid = afs_cr_gid(cr);
- new_creds->gid = afs_cr_rgid(cr);
-#else
- current->fsuid = afs_cr_uid(cr);
- current->uid = afs_cr_ruid(cr);
- current->fsgid = afs_cr_gid(cr);
- current->gid = afs_cr_rgid(cr);
-#endif
- memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- current->ngroups = cr->cr_ngroups;
-}
+++ /dev/null
-/*
- * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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.
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include <linux/random.h>
-
-int
-osi_readRandom(void *data, afs_size_t len) {
- get_random_bytes(data, len);
- 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"
-
-
-#ifdef AFS_LINUX24_ENV
-#include "h/module.h" /* early to avoid printf->printk mapping */
-#endif
-#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"
-
-afs_lock_t afs_xosi; /* lock is for tvattr */
-extern struct osi_dev cacheDev;
-#if defined(AFS_LINUX24_ENV)
-extern struct vfsmount *afs_cacheMnt;
-#endif
-extern struct super_block *afs_cacheSBp;
-
-void *
-osi_UFSOpen(afs_dcache_id_t *ainode)
-{
- struct osi_file *afile = NULL;
- extern int cacheDiskType;
- afs_int32 code = 0;
- 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(&afs_osi_cred, 0, sizeof(afs_ucred_t));
- crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
- afs_osicred_initialized = 1;
- }
- afile = 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, ainode->ufs);
- if (!tip)
- osi_Panic("Can't get inode %d\n", ainode->ufs);
- FILE_INODE(filp) = tip;
- tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
- filp->f_flags = O_RDWR;
-#if defined(AFS_LINUX24_ENV)
- filp->f_mode = FMODE_READ|FMODE_WRITE;
- 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->ufs);
- afile->size = i_size_read(tip);
- AFS_GLOCK();
- afile->offset = 0;
- afile->proc = (int (*)())0;
- return (void *)afile;
-}
-
-void osi_get_fh(struct dentry *dp, afs_ufs_dcache_id_t *ainode) {
- *ainode = dp->d_inode->i_ino;
-}
-
-int
-afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
-{
- afs_int32 code;
- AFS_STATCNT(osi_Stat);
- ObtainWriteLock(&afs_xosi, 320);
- astat->size = i_size_read(OSIFILE_INODE(afile));
- astat->mtime = OSIFILE_INODE(afile)->i_mtime;
- astat->atime = OSIFILE_INODE(afile)->i_atime;
- code = 0;
- ReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-int
-osi_UFSClose(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(struct osi_file *afile, afs_int32 asize)
-{
- afs_int32 code;
- struct osi_stat tstat;
- struct iattr newattrs;
- struct inode *inode = OSIFILE_INODE(afile);
- AFS_STATCNT(osi_Truncate);
-
- /* This routine only shrinks files, and most systems
- * have very slow truncates, even when the file is already
- * small enough. Check now and save some time.
- */
- code = afs_osi_Stat(afile, &tstat);
- if (code || tstat.size <= asize)
- return code;
- ObtainWriteLock(&afs_xosi, 321);
- AFS_GUNLOCK();
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- down_write(&inode->i_alloc_sem);
-#endif
-#ifdef STRUCT_INODE_HAS_I_MUTEX
- mutex_lock(&inode->i_mutex);
-#else
- down(&inode->i_sem);
-#endif
- 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
- i_size_write(inode, asize);
- 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;
-#ifdef STRUCT_INODE_HAS_I_MUTEX
- mutex_unlock(&inode->i_mutex);
-#else
- up(&inode->i_sem);
-#endif
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
- up_write(&inode->i_alloc_sem);
-#endif
- AFS_GLOCK();
- ReleaseWriteLock(&afs_xosi);
- return code;
-}
-
-
-/* Generic read interface */
-int
-afs_osi_Read(struct osi_file *afile, int offset, void *aptr,
- afs_int32 asize)
-{
- struct uio auio;
- struct iovec iov;
- afs_int32 code;
-
- memset(&auio, 0, sizeof(auio));
- memset(&iov, 0, sizeof(iov));
-
- 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;
- setup_uio(&auio, &iov, aptr, afile->offset, asize, UIO_READ, AFS_UIOSYS);
- AFS_GUNLOCK();
- code = osi_rdwr(afile, &auio, UIO_READ);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - auio.uio_resid;
- afile->offset += code;
- } else {
- afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, auio.uio_resid,
- ICL_TYPE_INT32, code);
- if (code > 0) {
- code = -code;
- }
- }
- return code;
-}
-
-/* Generic write interface */
-int
-afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
- afs_int32 asize)
-{
- struct uio auio;
- struct iovec iov;
- afs_int32 code;
-
- memset(&auio, 0, sizeof(auio));
- memset(&iov, 0, sizeof(iov));
-
- 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;
- setup_uio(&auio, &iov, aptr, afile->offset, asize, UIO_WRITE, AFS_UIOSYS);
- AFS_GUNLOCK();
- code = osi_rdwr(afile, &auio, UIO_WRITE);
- AFS_GLOCK();
- if (code == 0) {
- code = asize - auio.uio_resid;
- afile->offset += code;
- } else {
- if (code == ENOSPC)
- afs_warnuser
- ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
- if (code > 0) {
- code = -code;
- }
- }
-
- 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), struct buf *bp)
-{
- afs_int32 returnCode;
-
- AFS_STATCNT(osi_MapStrategy);
- returnCode = (*aproc) (bp);
-
- return returnCode;
-}
-
-void
-shutdown_osifile(void)
-{
- AFS_STATCNT(shutdown_osifile);
- if (afs_cold_shutdown) {
- afs_osicred_initialized = 0;
- }
-}
-
-/* Intialize cache device info and fragment size for disk cache partition. */
-int
-osi_InitCacheInfo(char *aname)
-{
- int code;
- extern afs_dcache_id_t cacheInode;
- struct dentry *dp;
- extern struct osi_dev cacheDev;
- extern afs_int32 afs_fsfragsize;
- extern struct super_block *afs_cacheSBp;
- extern struct vfsmount *afs_cacheMnt;
- code = osi_lookupname_internal(aname, 1, &afs_cacheMnt, &dp);
- if (code)
- return ENOENT;
-
- osi_get_fh(dp, &cacheInode.ufs);
- 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(struct osi_file *osifile, struct uio *uiop, int rw)
-{
- struct file *filp = &osifile->file;
- KERNEL_SPACE_DECL;
- int code = 0;
- struct iovec *iov;
- afs_size_t count;
- unsigned long savelim;
-
- savelim = current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur;
- current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
-
- if (uiop->uio_seg == AFS_UIOSYS)
- TO_USER_SPACE();
-
- /* seek to the desired position. Return -1 on error. */
- if (filp->f_op->llseek) {
- if (filp->f_op->llseek(filp, (loff_t) uiop->uio_offset, 0) != uiop->uio_offset)
- return -1;
- } else
- 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->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = savelim;
-
- return code;
-}
-
-/* setup_uio
- * Setup a uio struct.
- */
-void
-setup_uio(struct uio *uiop, struct iovec *iovecp, const char *buf, afs_offs_t pos,
- int count, uio_flag_t flag, uio_seg_t seg)
-{
- iovecp->iov_base = (char *)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, struct uio *uiop)
-{
- int count;
- 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;
-}
-
+++ /dev/null
-/* Taken from linux-2.6/arch/ppc64/boot/string.S
- *
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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
- *
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
- .section ".text"
- .align 2
- .globl flush_cache
- .section ".opd","aw"
- .align 3
-flush_cache:
- .quad .flush_cache,.TOC.@tocbase,0
- .previous
- .size flush_cache,24
- .globl .flush_cache
-.flush_cache:
- addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
- rlwinm. 4,4,27,5,31
- mtctr 4
- beqlr
-1: dcbf 0,3
- icbi 0,3
- addi 3,3,0x20
- bdnz 1b
- sync
- isync
- blr
- .long 0
- .byte 0,12,0,0,0,0,0,0
- .type .flush_cache,@function
- .size .flush_cache,.-.flush_cache
+++ /dev/null
-/*
- * Copyright 2000, International Business Machines Corporation and others.
- * All Rights Reserved.
- *
- * This software has been released under the terms of the IBM Public
- * License. For details, see the LICENSE file in the top-level source
- * directory or online at http://www.openafs.org/dl/license10.html
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if AFS_GCPAGS
-
-/* afs_osi_TraverseProcTable() - Walk through the systems process
- * table, calling afs_GCPAGs_perproc_func() for each process.
- */
-
-#ifdef EXPORTED_TASKLIST_LOCK
-extern rwlock_t tasklist_lock __attribute__((weak));
-#endif
-void
-afs_osi_TraverseProcTable(void)
-{
-#if !defined(LINUX_KEYRING_SUPPORT) && (!defined(STRUCT_TASK_STRUCT_HAS_CRED) || defined(HAVE_LINUX_RCU_READ_LOCK))
- struct task_struct *p;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && defined(EXPORTED_TASKLIST_LOCK)
- if (&tasklist_lock)
- read_lock(&tasklist_lock);
-#endif /* EXPORTED_TASKLIST_LOCK */
-
-#if defined(for_each_process)
- for_each_process(p) if (p->pid) {
-#ifdef STRUCT_TASK_STRUCT_HAS_EXIT_STATE
- if (p->exit_state)
- continue;
-#else
- if (p->state & TASK_ZOMBIE)
- continue;
-#endif
- afs_GCPAGs_perproc_func(p);
- }
-#else
- for_each_task(p) if (p->pid) {
-#ifdef STRUCT_TASK_STRUCT_HAS_EXIT_STATE
- if (p->exit_state)
- continue;
-#else
- if (p->state & TASK_ZOMBIE)
- continue;
-#endif
- afs_GCPAGs_perproc_func(p);
- }
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && defined(EXPORTED_TASKLIST_LOCK)
- if (&tasklist_lock)
- read_unlock(&tasklist_lock);
-#endif /* EXPORTED_TASKLIST_LOCK */
-#endif
-}
-
-/* return a pointer (sometimes a static copy ) to the cred for a
- * given afs_proc_t.
- * subsequent calls may overwrite the previously returned value.
- */
-
-const afs_ucred_t *
-afs_osi_proc2cred(afs_proc_t * pr)
-{
- afs_ucred_t *rv = NULL;
- static afs_ucred_t cr;
-
- if (pr == NULL) {
- return NULL;
- }
-
- if ((pr->state == TASK_RUNNING) || (pr->state == TASK_INTERRUPTIBLE)
- || (pr->state == TASK_UNINTERRUPTIBLE)
- || (pr->state == TASK_STOPPED)) {
-
- /* This is dangerous. If anyone ever crfree's the cred that's
- * returned from here, we'll go boom, because it's statically
- * allocated. */
-
- cr.cr_ref = 1;
- afs_set_cr_uid(&cr, task_uid(pr));
-
- cr.cr_ngroups = pr->ngroups;
- memcpy(cr.cr_groups, pr->groups, NGROUPS * sizeof(gid_t));
-
- rv = &cr;
- }
-
- return rv;
-}
-
-#endif /* AFS_GCPAGS */
+++ /dev/null
-/*
- * Copyright 2000, International Business Machines Corporation and others.
- * All Rights Reserved.
- *
- * This software has been released under the terms of the IBM Public
- * License. For details, see the LICENSE file in the top-level source
- * directory or online at http://www.openafs.org/dl/license10.html
- */
-
-/*
- * Implements:
- * setgroups (syscall)
- * setpag
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-#ifdef LINUX_KEYRING_SUPPORT
-#include <linux/seq_file.h>
-#endif
-
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h" /* statistics */
-#include "afs/nfsclient.h"
-#ifdef AFS_LINUX22_ENV
-#include "h/smp_lock.h"
-#endif
-
-#define NUMPAGGROUPS 2
-
-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);
-}
-
-/* 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;
- int n;
- gid_t *gp;
-
- AFS_STATCNT(afs_getgroups);
-
- gp = cr->cr_groups;
- n = cr->cr_ngroups;
-
- for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++)
- *groups++ = *gp++;
- return i;
-}
-
-/* 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;
-}
-
-int
-__setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
- int change_parent)
-{
- gid_t *gidset;
- afs_int32 ngroups, code = 0;
- int j;
-
- gidset = 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;
-}
-
-int
-setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
- int change_parent)
-{
- int code;
-
- AFS_STATCNT(setpag);
-
- code = __setpag(cr, pagvalue, newpag, change_parent);
-
- return code;
-}
-
-
-/* Intercept the standard system call. */
-extern asmlinkage 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 asmlinkage int (*sys_setgroups32p) (int gidsetsize,
- __kernel_gid32_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 asmlinkage 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. */
-#ifdef AFS_AMD64_LINUX20_ENV
-extern asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
-#endif /* AFS_AMD64_LINUX20_ENV */
-#ifdef AFS_SPARC64_LINUX26_ENV
-extern asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
- __kernel_gid32_t * grouplist);
-#endif /* AFS_SPARC64_LINUX26_ENV */
-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. */
-#ifdef AFS_AMD64_LINUX20_ENV
-extern asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
-#endif /* AFS_AMD64_LINUX20_ENV */
-#ifdef AFS_SPARC64_LINUX26_ENV
-extern asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
- __kernel_gid_t32 * grouplist);
-#endif /* AFS_SPARC64_LINUX26_ENV */
-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"
-
-
-#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(long a, long b, long c, long d, long e, long f)
-{
- return 0;
-}
-
-int
-afs_syscall_iopen(int a, int b, int c)
-{
- return 0;
-}
-
-int
-afs_syscall_iincdec(int a, int v, int c, int d)
-{
- 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 module support routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#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/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-extern struct proc_dir_entry *openafs_procfs;
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
-static int ioctl32_done;
-#endif
-
-extern asmlinkage long
-afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
-
-static int
-afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
-
- struct afsprocdata sysargs;
-#ifdef NEED_IOCTL32
- struct afsprocdata32 sysargs32;
-#endif
-
- if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL;
-
-#ifdef NEED_IOCTL32
-#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)
-#elif defined(AFS_S390X_LINUX20_ENV)
- if (current->thread.flags & S390_FLAG_31BIT)
-#else
-#error Not done for this linux type
-#endif
- {
- if (copy_from_user(&sysargs32, (void *)arg,
- sizeof(struct afsprocdata32)))
- return -EFAULT;
-
- return afs_syscall((unsigned long)sysargs32.syscall,
- (unsigned long)sysargs32.param1,
- (unsigned long)sysargs32.param2,
- (unsigned long)sysargs32.param3,
- (unsigned long)sysargs32.param4);
- } else
-#endif /* NEED_IOCTL32 */
- {
- 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);
- }
-}
-
-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
-static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg) {
- return afs_ioctl(FILE_INODE(file), file, cmd, arg);
-}
-#endif
-
-static struct file_operations afs_syscall_fops = {
-#ifdef HAVE_UNLOCKED_IOCTL
- .unlocked_ioctl = afs_unlocked_ioctl,
-#else
- .ioctl = afs_ioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
- .compat_ioctl = afs_unlocked_ioctl,
-#endif
-};
-
-void
-osi_ioctl_init(void)
-{
- struct proc_dir_entry *entry;
-
- entry = create_proc_entry(PROC_SYSCALL_NAME, 0666, openafs_procfs);
- entry->proc_fops = &afs_syscall_fops;
-#if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
- entry->owner = THIS_MODULE;
-#endif
-
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
- if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0)
- ioctl32_done = 1;
-#endif
-}
-
-void
-osi_ioctl_clean(void)
-{
- remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
- if (ioctl32_done)
- unregister_ioctl32_conversion(VIOC_SYSCALL32);
-#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 implementation.
- *
- */
-
-#ifndef OSI_MACHDEP_H_
-#define OSI_MACHDEP_H_
-
-#include <linux/version.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
-
-#ifdef STRUCT_TASK_STRUCT_HAS_TGID
-#define getpid() current->tgid
-#ifdef STRUCT_TASK_STRUCT_HAS_REAL_PARENT
-#define getppid() current->real_parent->tgid
-#elif defined(STRUCT_TASK_STRUCT_HAS_PARENT)
-#define getppid() current->parent->tgid
-#else
-#define getppid() current->p_opptr->tgid
-#endif
-#else /* !STRUCT_TASK_STRUCT_HAS_TGID */
-#define getpid() current->pid
-#ifdef STRUCT_TASK_STRUCT_HAS_REAL_PARENT
-#define getppid() current->real_parent->pid
-#elif defined(STRUCT_TASK_STRUCT_HAS_PARENT)
-#define getppid() current->parent->pid
-#else
-#define getppid() current->p_opptr->pid
-#endif
-#endif /* STRUCT_TASK_STRUCT_HAS_TGID */
-
-#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
-
-#if defined (STRUCT_TASK_STRUCT_HAS_RLIM)
-#define TASK_STRUCT_RLIM rlim
-#elif defined (STRUCT_TASK_STRUCT_HAS_SIGNAL_RLIM)
-#define TASK_STRUCT_RLIM signal->rlim
-#else
-#error Not sure what to do about rlim (should be in the Linux task struct somewhere....)
-#endif
-
-
-#define afs_hz HZ
-#include "h/sched.h"
-#if defined(HAVE_LINUX_CURRENT_KERNEL_TIME)
-static inline time_t osi_Time(void) {
- struct timespec xtime;
- xtime = current_kernel_time();
- return xtime.tv_sec;
-}
-#else
-#define osi_Time() (xtime.tv_sec)
-#endif
-
-
-
-#ifdef AFS_LINUX_64BIT_KERNEL
-#define osi_GetTime(V) \
- do { \
- struct timeval __afs_tv; \
- do_gettimeofday(&__afs_tv); \
- (V)->tv_sec = (afs_int32)__afs_tv.tv_sec; \
- (V)->tv_usec = (afs_int32)__afs_tv.tv_usec; \
- } while (0)
-#else
-#define osi_GetTime(V) do_gettimeofday((V))
-#endif
-
-#undef gop_lookupname
-#define gop_lookupname osi_lookupname
-
-#undef gop_lookupname_user
-#define gop_lookupname_user osi_lookupname
-
-#define osi_vnhold(V, N) do { VN_HOLD(AFSTOV(V)); } while (0)
-#define VN_HOLD(V) osi_Assert(igrab((V)) == (V))
-#define VN_RELE(V) iput((V))
-
-#define afs_suser(x) capable(CAP_SYS_ADMIN)
-#define wakeup afs_osi_Wakeup
-
-#undef vType
-#define vType(V) ((AFSTOV((V)))->i_mode & S_IFMT)
-#undef vSetType
-#define vSetType(V, type) AFSTOV((V))->i_mode = ((type) | (AFSTOV((V))->i_mode & ~S_IFMT)) /* preserve mode */
-
-#undef IsAfsVnode
-#define IsAfsVnode(V) ((V)->i_sb == afs_globalVFS) /* test superblock instead */
-#undef SetAfsVnode
-#define SetAfsVnode(V) /* unnecessary */
-
-/* We often need to pretend we're in user space to get memory transfers
- * right for the kernel calls we use.
- */
-#include <asm/uaccess.h>
-
-#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={0}
-#define TO_USER_SPACE() { _fs_space_decl = get_fs(); set_fs(get_ds()); }
-#define TO_KERNEL_SPACE() set_fs(_fs_space_decl)
-
-#define copyin(F, T, C) (copy_from_user ((char*)(T), (char*)(F), (C)) > 0 ? EFAULT : 0)
-static inline long copyinstr(char *from, char *to, int count, int *length) {
- long tmp;
- tmp = strncpy_from_user(to, from, count);
- if (tmp < 0)
- return EFAULT;
- *length = tmp;
- return 0;
-}
-#define copyout(F, T, C) (copy_to_user ((char*)(T), (char*)(F), (C)) > 0 ? EFAULT : 0)
-
-/* kernel print statements */
-#define printf printk
-#define uprintf printk
-
-
-#ifndef NGROUPS
-#define NGROUPS NGROUPS_SMALL
-#endif
-
-/* cred struct */
-typedef struct afs_cred { /* maps to task field: */
- int cr_ref;
- uid_t cr_uid; /* euid */
- uid_t cr_ruid; /* uid */
- gid_t cr_gid; /* egid */
- gid_t cr_rgid; /* gid */
- gid_t cr_groups[NGROUPS]; /* 32 groups - empty set to NOGROUP */
- int cr_ngroups;
-} cred_t;
-
-typedef struct afs_cred afs_ucred_t;
-typedef struct task_struct afs_proc_t;
-
-#if !defined(current_cred)
-#define current_gid() (current->gid)
-#define current_uid() (current->uid)
-#define current_fsgid() (current->fsgid)
-#define current_fsuid() (current->fsuid)
-#endif
-#if defined(STRUCT_TASK_STRUCT_HAS_CRED)
-#define current_group_info() (current->cred->group_info)
-#define task_gid(task) (task->cred->gid)
-#define task_user(task) (task->cred->user)
-#define task_session_keyring(task) (task->cred->tgcred->session_keyring)
-#define current_session_keyring() (current->cred->tgcred->session_keyring)
-#else
-#define current_group_info() (current->group_info)
-#if !defined(task_gid)
-#define task_gid(task) (task->gid)
-#endif
-#if !defined(task_uid)
-#define task_uid(task) (task->uid)
-#endif
-#define task_user(task) (task->user)
-#define task_session_keyring(task) (task->signal->session_keyring)
-#define current_session_keyring() (current->signal->session_keyring)
-#endif
-#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;
-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;
-};
-#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
-
-#define OSIFILE_INODE(a) FILE_INODE(&(a)->file)
-
-#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
-#define NEED_IOCTL32
-#endif
-
-/* 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__)
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-extern struct mutex afs_global_lock;
-#else
-extern struct semaphore afs_global_lock;
-#define mutex_lock(lock) down(lock)
-#define mutex_unlock(lock) up(lock)
-#endif
-extern int afs_global_owner;
-
-#define AFS_GLOCK() \
-do { \
- mutex_lock(&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; \
- mutex_unlock(&afs_global_lock); \
-} while (0)
-
-#define osi_InitGlock()
-
-#else
-#define AFS_GLOCK()
-#define AFS_GUNLOCK()
-#define ISAFS_GLOCK() 1
-#define AFS_ASSERT_GLOCK()
-#endif
-
-#ifdef AFS_AMD64_LINUX20_ENV
-/* RHEL5 beta's kernel doesn't define these. They aren't gonna change, so... */
-
-#ifndef __NR_ia32_afs_syscall
-#define __NR_ia32_afs_syscall 137
-#endif
-#ifndef __NR_ia32_setgroups
-#define __NR_ia32_setgroups 81
-#endif
-#ifndef __NR_ia32_setgroups32
-#define __NR_ia32_setgroups32 206
-#endif
-#ifndef __NR_ia32_close
-#define __NR_ia32_close 6
-#endif
-#ifndef __NR_ia32_chdir
-#define __NR_ia32_chdir 12
-#endif
-#ifndef __NR_ia32_break
-#define __NR_ia32_break 17
-#endif
-#ifndef __NR_ia32_stty
-#define __NR_ia32_stty 31
-#endif
-#ifndef __NR_ia32_gtty
-#define __NR_ia32_gtty 32
-#endif
-#ifndef __NR_ia32_ftime
-#define __NR_ia32_ftime 35
-#endif
-#ifndef __NR_ia32_prof
-#define __NR_ia32_prof 44
-#endif
-#ifndef __NR_ia32_lock
-#define __NR_ia32_lock 53
-#endif
-#ifndef __NR_ia32_mpx
-#define __NR_ia32_mpx 56
-#endif
-#ifndef __NR_ia32_exit
-#define __NR_ia32_exit 1
-#endif
-#ifndef __NR_ia32_mount
-#define __NR_ia32_mount 21
-#endif
-#ifndef __NR_ia32_read
-#define __NR_ia32_read 3
-#endif
-#ifndef __NR_ia32_write
-#define __NR_ia32_write 4
-#endif
-#ifndef __NR_ia32_open
-#define __NR_ia32_open 5
-#endif
-#ifndef __NR_ia32_close
-#define __NR_ia32_close 6
-#endif
-#ifndef __NR_ia32_unlink
-#define __NR_ia32_unlink 10
-#endif
-#endif
-
-#define osi_procname(procname, size) strncpy(procname, current->comm, size)
-
-#endif /* OSI_MACHDEP_H_ */
+++ /dev/null
-/*
- * Copyright 2000, International Business Machines Corporation and others.
- * All Rights Reserved.
- *
- * This software has been released under the terms of the IBM Public
- * License. For details, see the LICENSE file in the top-level source
- * directory or online at http://www.openafs.org/dl/license10.html
- */
-
-/*
- * Linux support routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-
-int afs_osicred_initialized = 0;
-afs_ucred_t afs_osi_cred;
-
-void
-afs_osi_SetTime(osi_timeval_t * tvp)
-{
-#if defined(AFS_LINUX24_ENV)
- struct timeval tv;
- tv.tv_sec = tvp->tv_sec;
- tv.tv_usec = tvp->tv_usec;
-
- 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();
- if (sys_settimeofdayp)
- (void)(*sys_settimeofdayp) (tvp, NULL);
- TO_KERNEL_SPACE();
-#endif
-}
-
-void
-osi_linux_mask(void)
-{
- SIG_LOCK(current);
- sigfillset(¤t->blocked);
- RECALC_SIGPENDING(current);
- SIG_UNLOCK(current);
-}
-
-#if defined(AFS_LINUX24_ENV)
-/* LOOKUP_POSITIVE is becoming the default */
-#ifndef LOOKUP_POSITIVE
-#define LOOKUP_POSITIVE 0
-#endif
-/* Lookup name and return vnode for same. */
-int
-osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
- struct dentry **dpp)
-{
- int code;
- struct nameidata nd;
- int flags = LOOKUP_POSITIVE;
- code = ENOENT;
-
- if (followlink)
- flags |= LOOKUP_FOLLOW;
- if (path_init(aname, flags, &nd))
- code = path_walk(aname, &nd);
-
- if (!code) {
-#if defined(STRUCT_NAMEIDATA_HAS_PATH)
- *dpp = dget(nd.path.dentry);
- if (mnt)
- *mnt = mntget(nd.path.mnt);
- path_put(&nd.path);
-#else
- *dpp = dget(nd.dentry);
- if (mnt)
- *mnt = mntget(nd.mnt);
- path_release(&nd);
-#endif
- }
- return code;
-}
-
-int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- struct dentry **dpp)
-{
- int code;
- char *tname;
- code = ENOENT;
- if (seg == AFS_UIOUSER) {
- tname = getname(aname);
- if (IS_ERR(tname))
- return PTR_ERR(tname);
- } else {
- tname = aname;
- }
- code = osi_lookupname_internal(tname, followlink, NULL, dpp);
- if (seg == AFS_UIOUSER) {
- putname(tname);
- }
- return code;
-}
-#else
-int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink, 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
+++ /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"
-
-
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#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
-#ifdef AFS_SPARC64_LINUX20_ENV
-#include <linux/ioctl32.h>
-#endif
-
-#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>
-#include <linux/kernel.h>
-#endif
-
-extern struct file_system_type afs_fs_type;
-
-#if !defined(AFS_LINUX24_ENV)
-static long get_page_offset(void);
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-DEFINE_MUTEX(afs_global_lock);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-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
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-int __init
-afs_init(void)
-#else
-int
-init_module(void)
-#endif
-{
- int err;
- AFS_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) */
-
- osi_Init();
-
-#ifndef LINUX_KEYRING_SUPPORT
- err = osi_syscall_init();
- if (err)
- return err;
-#endif
- err = afs_init_inodecache();
- if (err) {
-#ifndef LINUX_KEYRING_SUPPORT
- osi_syscall_clean();
-#endif
- return err;
- }
- err = register_filesystem(&afs_fs_type);
- if (err) {
- afs_destroy_inodecache();
-#ifndef LINUX_KEYRING_SUPPORT
- osi_syscall_clean();
-#endif
- return err;
- }
-
- osi_sysctl_init();
-#ifdef LINUX_KEYRING_SUPPORT
- osi_keyring_init();
-#endif
-#ifdef AFS_LINUX24_ENV
- osi_proc_init();
- osi_ioctl_init();
-#endif
-
- return 0;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-void __exit
-afs_cleanup(void)
-#else
-void
-cleanup_module(void)
-#endif
-{
-#ifdef LINUX_KEYRING_SUPPORT
- osi_keyring_shutdown();
-#endif
- osi_sysctl_clean();
-#ifndef LINUX_KEYRING_SUPPORT
- osi_syscall_clean();
-#endif
- unregister_filesystem(&afs_fs_type);
-
- afs_destroy_inodecache();
- osi_linux_free_afs_memory();
-
-#ifdef AFS_LINUX24_ENV
- osi_ioctl_clean();
- osi_proc_clean();
-#endif
-
- return;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
-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 defined(EXPORTED_TASKLIST_LOCK)
- read_lock(&tasklist_lock);
-#endif
- /* search backward thru the circular list */
-#if 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 defined(EXPORTED_TASKLIST_LOCK)
- read_unlock(&tasklist_lock);
-#endif
- return p->addr_limit.seg;
- }
- }
-
-#if defined(EXPORTED_TASKLIST_LOCK)
- 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
- */
-
-/*
- * Linux module support routines.
- *
- */
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#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/proc_fs.h>
-#include <linux/slab.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#endif
-
-static unsigned long nfs_server_addr = 0;
-#if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(nfs_server_addr, long, 0);
-#else
-MODULE_PARM(nfs_server_addr, "l");
-#endif
-MODULE_PARM_DESC(nfs_server_addr, "IP Address of NFS Server");
-
-static char *this_cell = 0;
-#if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(this_cell, charp, 0);
-#else
-MODULE_PARM(this_cell, "s");
-#endif
-MODULE_PARM_DESC(this_cell, "Local cell name");
-
-#if defined(AFS_LINUX24_ENV)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-DEFINE_MUTEX(afs_global_lock);
-#else
-DECLARE_MUTEX(afs_global_lock);
-#endif
-struct proc_dir_entry *openafs_procfs;
-#else
-struct semaphore afs_global_lock = MUTEX;
-#endif
-int afs_global_owner = 0;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-int __init
-afspag_init(void)
-#else
-int
-init_module(void)
-#endif
-{
-#if !defined(EXPORTED_PROC_ROOT_FS) && defined(AFS_LINUX24_ENV)
- char path[64];
-#endif
- int err;
-
- osi_Init();
-
- err = osi_syscall_init();
- if (err)
- return err;
-#ifdef AFS_LINUX24_ENV
-#if defined(EXPORTED_PROC_ROOT_FS)
- openafs_procfs = proc_mkdir(PROC_FSDIRNAME, proc_root_fs);
-#else
- sprintf(path, "fs/%s", PROC_FSDIRNAME);
- openafs_procfs = proc_mkdir(path, NULL);
-#endif
- osi_ioctl_init();
-#endif
-
- afspag_Init(htonl(nfs_server_addr));
- if (this_cell)
- afspag_SetPrimaryCell(this_cell);
-
- return 0;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-void __exit
-afspag_cleanup(void)
-#else
-void
-cleanup_module(void)
-#endif
-{
-#if !defined(EXPORTED_PROC_ROOT_FS) && defined(AFS_LINUX24_ENV)
- char path[64];
-#endif
- osi_syscall_clean();
-
- osi_linux_free_afs_memory();
-
-#ifdef AFS_LINUX24_ENV
- osi_ioctl_clean();
-#if defined(EXPORTED_PROC_ROOT_FS)
- remove_proc_entry(PROC_FSDIRNAME, proc_root_fs);
-#else
- sprintf(path, "fs/%s", PROC_FSDIRNAME);
- remove_proc_entry(path, NULL);
-#endif
-#endif
- return;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
-module_init(afspag_init);
-module_exit(afspag_cleanup);
-#endif
+++ /dev/null
-/*
- * vi:set cin noet sw=4 tw=70:
- * Copyright 2004, 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 of this code borrowed from arla under the following terms:
- * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * 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. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL").
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
- */
-
-/* Code to find the Linux syscall table */
-
-#ifdef OSI_PROBE_STANDALONE
-#define OSI_PROBE_DEBUG
-#endif
-#ifndef OSI_PROBE_STANDALONE
-#include <afsconfig.h>
-#include "afs/param.h"
-#endif
-#if defined(ENABLE_LINUX_SYSCALL_PROBING)
-#ifdef AFS_LINUX24_ENV
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#ifndef OSI_PROBE_STANDALONE
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#endif
-#include <linux/version.h>
-#include <linux/sched.h>
-#ifdef HAVE_LINUX_CONFIG_H
-#include <linux/config.h>
-#endif
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/unistd.h>
-#include <linux/mm.h>
-
-#ifdef AFS_AMD64_LINUX20_ENV
-#include <asm/ia32_unistd.h>
-#endif
-
-/* number of syscalls */
-/* NB: on MIPS we care about the 4xxx range */
-#ifndef NR_syscalls
-#define NR_syscalls 222
-#endif
-
-/* lower bound of valid kernel text pointers */
-#ifdef AFS_IA64_LINUX20_ENV
-#define ktxt_lower_bound (((unsigned long)&kernel_thread ) & 0xfff00000L)
-#elif defined(AFS_PPC64_LINUX20_ENV)
-#define ktxt_lower_bound (KERNELBASE)
-#else
-#define ktxt_lower_bound (((unsigned long)&kernel_thread ) & ~0xfffffL)
-#endif
-
-/* On SPARC64 and S390X, sys_call_table contains 32-bit entries
- * even though pointers are 64 bit quantities.
- */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-#define SYSCALLTYPE unsigned int
-#define PROBETYPE int
-#else
-#define SYSCALLTYPE void *
-#define PROBETYPE long
-#endif
-
-#if defined(AFS_S390X_LINUX20_ENV)
-#define _SS(x) ((x) << 1)
-#define _SX(x) ((x) &~ 1)
-#else
-#define _SS(x) (x)
-#define _SX(x) (x)
-#endif
-
-/* Older Linux doesn't have __user. The sys_read prototype needs it. */
-#ifndef __user
-#define __user
-#endif
-
-/* Allow the user to specify sys_call_table addresses */
-static unsigned long sys_call_table_addr[4] = { 0,0,0,0 };
-#if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param_array(sys_call_table_addr, long, NULL, 0);
-#else
-MODULE_PARM(sys_call_table_addr, "1-4l");
-#endif
-MODULE_PARM_DESC(sys_call_table_addr, "Location of system call tables");
-
-/* If this is set, we are more careful about avoiding duplicate matches */
-static int probe_carefully = 1;
-#if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(probe_carefully, int, 0);
-#else
-MODULE_PARM(probe_carefully, "i");
-#endif
-MODULE_PARM_DESC(probe_carefully, "Probe for system call tables carefully");
-
-static int probe_ignore_syscalls[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-#if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param_array(probe_ignore_syscalls, int, NULL, 0);
-#else
-MODULE_PARM(probe_ignore_syscalls, "1-8i");
-#endif
-MODULE_PARM_DESC(probe_ignore_syscalls, "Syscalls to ignore in table checks");
-
-#ifdef OSI_PROBE_DEBUG
-/*
- * Debugging flags:
- * 0x0001 - General debugging
- * 0x0002 - detail - try
- * 0x0004 - detail - try_harder
- * 0x0008 - detail - check_table
- * 0x0010 - detail - check_harder
- * 0x0020 - detail - check_harder/zapped
- * 0x0040 - automatically ignore setgroups and afs_syscall
- * 0x0080 - detail - check_table_readable
- */
-static int probe_debug = 0x41;
-#if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(probe_debug, int, 0);
-#else
-MODULE_PARM(probe_debug, "i");
-#endif
-MODULE_PARM_DESC(probe_debug, "Debugging level");
-
-static unsigned long probe_debug_addr[4] = { 0,0,0,0 };
-#if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param_array(probe_debug_addr, long, NULL, 0);
-#else
-MODULE_PARM(probe_debug_addr, "1-4l");
-#endif
-MODULE_PARM_DESC(probe_debug_addr, "Debug range starting locations");
-
-static unsigned long probe_debug_range = 0;
-#if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(probe_debug_range, long, 0);
-#else
-MODULE_PARM(probe_debug_range, "l");
-#endif
-MODULE_PARM_DESC(probe_debug_range, "Debug range length");
-
-static unsigned long probe_debug_tag = 0;
-#if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
-module_param(probe_debug_tag, long, 0);
-#else
-MODULE_PARM(probe_debug_tag, "l");
-#endif
-MODULE_PARM_DESC(probe_debug_tag, "Debugging output start tag");
-#endif
-
-
-/* Weak references are our friends. They are supported by the in-kernel
- * linker in Linux 2.6 and by all versions of modutils back to 2.2pre1.
- * A weak reference not satisified by the kernel will have value zero.
- *
- * Unfortunately, weak references to functions don't work right on
- * IA64; specifically, if you actually try to make a call through
- * such a reference, and the symbol doesn't exist in the kernel, then
- * the module relocation code will oops. A workaround for this is
- * probably possible, but the use of kallsyms_* is of limited value,
- * so I'm not bothing with the effort for now.
- * -- jhutz, 10-Feb-2005
- */
-#ifdef OSI_PROBE_KALLSYMS
-extern int kallsyms_symbol_to_address(char *name, unsigned long *token,
- char **mod_name,
- unsigned long *mod_start,
- unsigned long *mod_end,
- char **sec_name,
- unsigned long *sec_start,
- unsigned long *sec_end,
- char **sym_name,
- unsigned long *sym_start,
- unsigned long *sym_end
- ) __attribute__((weak));
-
-extern int kallsyms_address_to_symbol(unsigned long address,
- char **mod_name,
- unsigned long *mod_start,
- unsigned long *mod_end,
- char **sec_name,
- unsigned long *sec_start,
- unsigned long *sec_end,
- char **sym_name,
- unsigned long *sym_start,
- unsigned long *sym_end
- ) __attribute__((weak));
-#endif
-
-extern SYSCALLTYPE sys_call_table[] __attribute__((weak));
-extern SYSCALLTYPE ia32_sys_call_table[] __attribute__((weak));
-extern SYSCALLTYPE sys_call_table32[] __attribute__((weak));
-extern SYSCALLTYPE sys_call_table_emu[] __attribute__((weak));
-
-extern asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) __attribute__((weak));
-extern asmlinkage long sys_close(unsigned int) __attribute__((weak));
-#if defined(EXPORTED_SYS_CHDIR)
-extern asmlinkage long sys_chdir(const char *) __attribute__((weak));
-#endif
-extern asmlinkage ssize_t sys_write(unsigned int, const char *, size_t) __attribute__((weak));
-extern asmlinkage long sys_wait4(pid_t, unsigned int *, int, struct rusage *) __attribute__((weak));
-extern asmlinkage long sys_exit (int) __attribute__((weak));
-#if defined(EXPORTED_SYS_OPEN)
-extern asmlinkage long sys_open (const char *, int, int) __attribute__((weak));
-#endif
-extern asmlinkage long sys_ioctl(unsigned int, unsigned int, unsigned long) __attribute__((weak));
-
-
-/* Structures used to control probing. We put all the details of which
- * symbols we're interested in, what syscall functions to look for, etc
- * into tables, so we can then have a single copy of the functions that
- * actually do the work.
- */
-typedef struct {
- char *name;
- int NR1;
- void *fn1;
- int NR2;
- void *fn2;
- int NR3;
- void *fn3;
-} tryctl;
-
-typedef struct {
- char *symbol; /* symbol name */
- char *desc; /* description for messages */
- int offset; /* first syscall number in table */
-
- void *weak_answer; /* weak symbol ref */
- void *parm_answer; /* module parameter answer */
- void *debug_answer; /* module parameter answer */
- unsigned long given_answer; /* compiled-in answer, if any */
-
- tryctl *trylist; /* array of combinations to try */
-
- unsigned long try_sect_sym; /* symbol in section to try scanning */
- unsigned long try_base; /* default base address for scan */
- unsigned long try_base_mask; /* base address bits to force to zero */
- unsigned long try_length; /* default length for scan */
-
- unsigned long alt_try_sect_sym; /* symbol in section to try scanning */
- unsigned long alt_try_base; /* default base address for scan */
- unsigned long alt_try_base_mask; /* base address bits to force to zero */
- unsigned long alt_try_length; /* default length for scan */
-
- int n_zapped_syscalls; /* number of unimplemented system calls */
- int *zapped_syscalls; /* list of unimplemented system calls */
-
- int n_unique_syscalls; /* number of unique system calls */
- int *unique_syscalls; /* list of unimplemented system calls */
-
- int verifyNR; /* syscall number to verify match */
- void *verify_fn; /* syscall pointer to verify match */
-
- int debug_ignore_NR[4]; /* syscalls to ignore for debugging */
-} probectl;
-
-/********** Probing Configuration: sys_call_table **********/
-
-/* syscall pairs/triplets to probe */
-/* On PPC64 and SPARC64, we need to omit the ones that might match both tables */
-static tryctl main_try[] = {
-#if !defined(AFS_PPC64_LINUX20_ENV) && !defined(AFS_SPARC64_LINUX20_ENV)
-#if defined(EXPORTED_SYS_CHDIR)
- { "scan: close+chdir+write", __NR_close, &sys_close, __NR_chdir, &sys_chdir, __NR_write, &sys_write },
-#endif
-#endif
- { "scan: close+wait4", __NR_close, &sys_close, __NR_wait4, &sys_wait4, -1, 0 },
-#if !defined(AFS_PPC64_LINUX20_ENV) && !defined(AFS_SPARC64_LINUX20_ENV)
-#if defined(EXPORTED_SYS_CHDIR)
- { "scan: close+chdir", __NR_close, &sys_close, __NR_chdir, &sys_chdir, -1, 0 },
-#endif
-#endif
- { "scan: close+ioctl", __NR_close, &sys_close, __NR_ioctl, &sys_ioctl, -1, 0 },
-#if defined(EXPORTED_SYS_OPEN)
- { "scan: exit+open", __NR_exit, &sys_exit, __NR_open, &sys_open, -1, 0 },
-#endif
- { 0 }
-};
-
-/* zapped syscalls for try_harder */
-/* this list is based on the table in 'zapped_syscalls' */
-
-static int main_zapped_syscalls[] = {
-/*
- * SPARC-Linux uses syscall number mappings chosen to be compatible
- * with SunOS. So, it doesn't have any of the traditional calls or
- * the new STREAMS ones. However, there are a number of syscalls
- * which are SunOS-specific (not implemented on Linux), i386-specific
- * (not implemented on SPARC-Linux), or implemented only on one of
- * sparc32 or sparc64. Of course, there are no __NR macros for most
- * of these.
- *
- * Note that the calls we list here are implemented by sys_nis_syscall,
- * not by sys_ni_syscall. That means we have to exclude all of the
- * other entries, or we might get a sys_ni_syscall into the list and
- * the test would no longer work.
- */
-#if defined(AFS_SPARC64_LINUX20_ENV)
- /* mmap2, fstat64, getmsg, putmsg, modify_ldt */
- 56, 63, 151, 152, 218,
-#elif defined(AFS_SPARC_LINUX20_ENV)
- /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
- 52, 151, 152, 164, 218,
-#else /* !AFS_SPARC_LINUX20_ENV */
-
-/*
- * These 7 syscalls are present in the syscall table on most "older"
- * platforms that use the traditional syscall number mappings. They
- * are not implemented on any platform.
- */
-#ifdef __NR_break
- __NR_break,
-#endif
-#ifdef __NR_stty
- __NR_stty,
-#endif
-#ifdef __NR_gtty
- __NR_gtty,
-#endif
-#ifdef __NR_ftime
- __NR_ftime,
-#endif
-#ifdef __NR_prof
- __NR_prof,
-#endif
-#ifdef __NR_lock
- __NR_lock,
-#endif
-#ifdef __NR_mpx
- __NR_mpx,
-#endif
-/*
- * On s390 and arm (but not arm26), the seven traditional unimplemented
- * system calls are indeed present and unimplemented. However, the
- * corresponding __NR macros are not defined, so the tests above fail.
- * Instead, we just have to know the numbers for these.
- */
-#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- /* break, stty, gtty, ftime, prof, lock, mpx */
- 17, 31, 32, 35, 44, 53, 56,
-#endif
-
-/*
- * Sadly, some newer platforms like IA64, amd64, and PA-RISC don't have
- * the traditional numbers, so the list above are not helpful. They
- * do have entries for getpmsg/putpmsg, which are always unimplemented.
- */
-#ifdef __NR_getpmsg
- __NR_getpmsg,
-#endif
-#ifdef __NR_putpmsg
- __NR_putpmsg,
-#endif
-
-/*
- * Alpha-Linux uses syscall number mappings chosen to be compatible
- * with OSF/1. So, it doesn't have any of the traditional calls or
- * the new STREAMS ones, but it does have several OSF/1-specific
- * syscalls which are not implemented on Linux. These don't exist on
- * any other platform.
- */
-#ifdef __NR_osf_syscall
- __NR_osf_syscall,
-#endif
-#ifdef __NR_osf_profil
- __NR_osf_profil,
-#endif
-#ifdef __NR_osf_reboot
- __NR_osf_reboot,
-#endif
-#ifdef __NR_osf_kmodcall
- __NR_osf_kmodcall,
-#endif
-#ifdef __NR_osf_old_vtrace
- __NR_osf_old_vtrace,
-#endif
-
-/*
- * On PPC64, we need a couple more entries to distinguish the two
- * tables, since the system call numbers are the same and the sets of
- * unimplemented calls are very similar.
- * mmap2 and fstat64 are implemented only for 32-bit calls
- */
-#ifdef AFS_PPC64_LINUX20_ENV
- /* _mmap2, _fstat64 */
- 192, 197,
-#endif /* AFS_PPC64_LINUX20_ENV */
-
-/* Similarly for S390X, with lcown16 and fstat64 */
-#ifdef AFS_S390X_LINUX20_ENV
- /* lchown16, fstat64 */
- 16, 197,
-#endif
-#endif /* !AFS_SPARC_LINUX20_ENV */
- 0
-};
-
-/* unique syscalls for try_harder */
-static int main_unique_syscalls[] = {
-#if defined(AFS_SPARC64_LINUX24_ENV) || defined(AFS_SPARC_LINUX24_ENV)
- /*
- * On SPARC, we need some additional unique calls to make sure
- * we don't match the SunOS-compatibility table.
- */
- __NR_sgetmask, __NR_ssetmask,
-#endif
- __NR_exit, __NR_mount, __NR_read, __NR_write,
- __NR_open, __NR_close, __NR_unlink
-};
-
-/* probe control structure */
-static probectl main_probe = {
- /* symbol name and description */
- "sys_call_table",
- "system call table",
-
- /* syscall number of first entry in table */
-#ifdef AFS_IA64_LINUX20_ENV
- 1024,
-#else
- 0,
-#endif
-
- sys_call_table, /* weak symbol ref */
- 0, 0, /* module parameter answers */
-#ifdef AFS_LINUX_sys_call_table
- AFS_LINUX_sys_call_table, /* compiled-in answer, if any */
-#else
- 0,
-#endif
-
- main_try, /* array of combinations to try */
-
- /* symbol in section to try scanning */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- (unsigned long)&sys_close,
-#elif defined(AFS_AMD64_LINUX20_ENV)
- /* On this platform, it's in a different section! */
- (unsigned long)&tasklist_lock,
-#else
- (unsigned long)&init_mm,
-#endif
-
- /* default base address for scan */
- /* base address bits to force to zero */
- /* default length for scan */
-#if defined(AFS_SPARC64_LINUX20_ENV)
- (unsigned long)(&sys_close),
- 0xfffff,
- 0x10000,
-#elif defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- /* bleah; this is so suboptimal */
- (unsigned long)(&sys_close),
- 0xfffff,
- 0x20000,
-#elif defined(AFS_IA64_LINUX20_ENV)
- (unsigned long)(&init_mm),
- 0x1fffff,
- 0x30000,
-#elif defined(AFS_AMD64_LINUX20_ENV)
- (unsigned long)(&tasklist_lock) - 0x30000,
- 0,
- 0x6000,
-#elif defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC_LINUX20_ENV)
- (unsigned long)&init_mm,
- 0xffff,
- 16384,
-#else
- (unsigned long)&init_mm,
- 0,
- 16384,
-#endif
-
- 0, 0, 0, 0,
-
- /* number and list of unimplemented system calls */
- ((sizeof(main_zapped_syscalls)/sizeof(main_zapped_syscalls[0])) - 1),
- main_zapped_syscalls,
-
- /* number and list of unique system calls */
- (sizeof(main_unique_syscalls)/sizeof(main_unique_syscalls[0])),
- main_unique_syscalls,
-
- /* syscall number and pointer to verify match */
- __NR_close, &sys_close,
-
- /* syscalls to ignore for debugging */
- {
-#if defined(AFS_ALPHA_LINUX20_ENV)
- 338,
-#elif defined(AFS_AMD64_LINUX20_ENV)
- 183,
-#elif defined(AFS_IA64_LINUX20_ENV)
- 1141,
-#elif defined(AFS_SPARC_LINUX20_ENV) || defined(AFS_SPARC64_LINUX20_ENV)
- 227,
-#else
- 137,
-#endif
- __NR_setgroups,
-#ifdef __NR_setgroups32
- __NR_setgroups32,
-#else
- -1,
-#endif
- -1,
- }
-};
-
-
-/********** Probing Configuration: amd64 ia32_sys_call_table **********/
-#if defined(AFS_AMD64_LINUX20_ENV)
-
-/* syscall pairs/triplets to probe */
-static tryctl ia32_try[] = {
-#if defined(EXPORTED_SYS_CHDIR)
- { "scan: close+chdir+write", __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir, __NR_ia32_write, &sys_write },
- { "scan: close+chdir", __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir, -1, 0 },
-#endif
- { 0 }
-};
-
-/* zapped syscalls for try_harder */
-static int ia32_zapped_syscalls[] = {
- __NR_ia32_break, __NR_ia32_stty, __NR_ia32_gtty, __NR_ia32_ftime,
- __NR_ia32_prof, __NR_ia32_lock, __NR_ia32_mpx,
- 0
-};
-
-/* unique syscalls for try_harder */
-static int ia32_unique_syscalls[] = {
- __NR_ia32_exit, __NR_ia32_mount, __NR_ia32_read, __NR_ia32_write,
- __NR_ia32_open, __NR_ia32_close, __NR_ia32_unlink
-};
-
-/* probe control structure */
-static probectl ia32_probe = {
- /* symbol name and description */
- "ia32_sys_call_table",
- "32-bit system call table",
-
- /* syscall number of first entry in table */
- 0,
-
- ia32_sys_call_table, /* weak symbol ref */
- 0, 0, /* module parameter answers */
-#ifdef AFS_LINUX_ia32_sys_call_table
- AFS_LINUX_ia32_sys_call_table,/* compiled-in answer, if any */
-#else
- 0,
-#endif
-
- ia32_try, /* array of combinations to try */
-
- /* symbol in section to try scanning */
- (unsigned long)&init_mm,
-
- /* default base address for scan */
- /* base address bits to force to zero */
- /* default length for scan */
- (unsigned long)&init_mm,
- 0,
- (0x180000 / sizeof(unsigned long *)),
-
- 0, 0, 0, 0,
-
-
- /* number and list of unimplemented system calls */
- ((sizeof(ia32_zapped_syscalls)/sizeof(ia32_zapped_syscalls[0])) - 1),
- ia32_zapped_syscalls,
-
- /* number and list of unique system calls */
- (sizeof(ia32_unique_syscalls)/sizeof(ia32_unique_syscalls[0])),
- ia32_unique_syscalls,
-
- /* syscall number and pointer to verify match */
- __NR_ia32_close, &sys_close,
-
- /* syscalls to ignore for debugging */
- {
- 137,
- __NR_ia32_setgroups,
- __NR_ia32_setgroups32,
- -1,
- }
-};
-
-static probectl *probe_list[] = {
- &main_probe, &ia32_probe
-};
-
-
-/********** Probing Configuration: IA64 **********/
-#elif defined(AFS_IA64_LINUX20_ENV)
-struct fptr {
- void *ip;
- unsigned long gp;
-};
-
-/* no 32-bit support on IA64 for now */
-static probectl *probe_list[] = {
- &main_probe
-};
-
-
-/********** Probing Configuration: ppc64, sparc64 sys_call_table32 **********/
-#elif defined(AFS_PPC64_LINUX20_ENV) || defined(AFS_SPARC64_LINUX20_ENV)
-struct fptr {
- void *ip;
- unsigned long gp;
-};
-
-/*
- * syscall pairs/triplets to probe
- * This has to be empty, because anything that would work will
- * also match the main table, and that's no good.
- */
-static tryctl sct32_try[] = {
- { 0 }
-};
-
-/* zapped syscalls for try_harder */
-static int sct32_zapped_syscalls[] = {
-#ifdef AFS_PPC64_LINUX20_ENV
- /* These should be sufficient */
- __NR_break, __NR_stty, __NR_gtty, __NR_ftime,
- __NR_prof, __NR_lock, __NR_mpx,
-#endif
-#ifdef AFS_SPARC64_LINUX20_ENV
- /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
- 52, 151, 152, 164, 218,
-#endif
- 0
-};
-
-/* unique syscalls for try_harder */
-/* mmap2 and fstat64 are implemented only for 32-bit calls */
-static int sct32_unique_syscalls[] = {
-#ifdef AFS_PPC64_LINUX20_ENV
- /* _mmap2, _fstat64 */
- 192, 197,
-#endif
-#ifdef AFS_SPARC64_LINUX24_ENV
- /*
- * On SPARC, we need some additional unique calls to make sure
- * we don't match the SunOS-compatibility table.
- */
- __NR_sgetmask, __NR_ssetmask,
-#endif
- __NR_exit, __NR_mount, __NR_read, __NR_write,
- __NR_open, __NR_close, __NR_unlink
-};
-
-/* probe control structure */
-static probectl sct32_probe = {
- /* symbol name and description */
- "sys_call_table32",
- "32-bit system call table",
-
- /* syscall number of first entry in table */
- 0,
-
- sys_call_table32, /* weak symbol ref */
- 0, 0, /* module parameter answers */
-#ifdef AFS_LINUX_sys_call_table32
- AFS_LINUX_sys_call_table32, /* compiled-in answer, if any */
-#else
- 0,
-#endif
-
- sct32_try, /* array of combinations to try */
-
- /* symbol in section to try scanning */
-#if defined(AFS_SPARC64_LINUX20_ENV)
- (unsigned long)&sys_close,
-#else
- (unsigned long)&init_mm,
-#endif
-
- /* default base address for scan */
- /* base address bits to force to zero */
- /* default length for scan */
-#if defined(AFS_SPARC64_LINUX20_ENV)
- (unsigned long)(&sys_close),
- 0xfffff,
- 0x10000,
-#else
- (unsigned long)&init_mm,
- 0,
- 16384,
-#endif
-
- 0, 0, 0, 0,
-
- /* number and list of unimplemented system calls */
- ((sizeof(sct32_zapped_syscalls)/sizeof(sct32_zapped_syscalls[0])) - 1),
- sct32_zapped_syscalls,
-
- /* number and list of unique system calls */
- (sizeof(sct32_unique_syscalls)/sizeof(sct32_unique_syscalls[0])),
- sct32_unique_syscalls,
-
- /* syscall number and pointer to verify match */
- __NR_close, &sys_close,
-
- /* syscalls to ignore for debugging */
- {
-#if defined(AFS_SPARC64_LINUX20_ENV)
- 227,
-#else
- 137,
-#endif
- __NR_setgroups,
- -1,
- -1,
- }
-};
-
-static probectl *probe_list[] = {
- &main_probe, &sct32_probe
-};
-
-
-/********** End of Probing Configuration **********/
-
-#else /* no per-platform probe control, so use the default list */
-static probectl *probe_list[] = {
- &main_probe
-};
-#endif
-
-#define N_PROBE_LIST (sizeof(probe_list) / sizeof(*probe_list))
-#define DEBUG_IN_RANGE(P,x) (!probe_debug_range || \
- (P->debug_answer && \
- (unsigned long)(x) >= (unsigned long)P->debug_answer && \
- (unsigned long)(x) < (unsigned long)P->debug_answer + probe_debug_range))
-
-
-
-static int check_table(probectl *P, PROBETYPE *ptr)
-{
- PROBETYPE *x;
- int i, j;
-
- for (x = ptr, i = 0; i < _SS(NR_syscalls); i++, x++) {
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0040) {
- for (j = 0; j < 4; j++) {
- if (_SS(P->debug_ignore_NR[j]) == _SX(i + P->offset)) break;
- }
- if (j < 4) continue;
- }
-#endif
- for (j = 0; j < 8; j++) {
- if (_SS(probe_ignore_syscalls[j]) == _SX(i) + P->offset) break;
- }
- if (j < 8) continue;
- if (*x <= ktxt_lower_bound) {
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
- printk("<7>check 0x%lx -> %d [0x%lx]\n",
- (unsigned long)ptr, i, (unsigned long)*x);
-#endif
- return i;
- }
- }
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
- printk("<7>check 0x%lx -> ok\n", (unsigned long)ptr);
-#endif
- return -1;
-}
-
-static void *try(probectl *P, tryctl *T, PROBETYPE *aptr,
- unsigned long datalen)
-{
-#ifdef OSI_PROBE_KALLSYMS
- char *mod_name, *sec_name, *sym_name;
- unsigned long mod_start, mod_end;
- unsigned long sec_start, sec_end;
- unsigned long sym_start, sym_end;
-#endif
- unsigned long offset, ip1, ip2, ip3;
- int ret;
- PROBETYPE *ptr;
-
-#if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
- ip1 = T->fn1 ? (unsigned long)((struct fptr *)T->fn1)->ip : 0;
- ip2 = T->fn2 ? (unsigned long)((struct fptr *)T->fn2)->ip : 0;
- ip3 = T->fn3 ? (unsigned long)((struct fptr *)T->fn3)->ip : 0;
-#else
- ip1 = (unsigned long)T->fn1;
- ip2 = (unsigned long)T->fn2;
- ip3 = (unsigned long)T->fn3;
-#endif
-
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0001)
- printk("<7>osi_probe: %s %s (%d->0x%lx, %d->0x%lx, %d->0x%lx)\n",
- P->symbol, T->name, T->NR1, ip1, T->NR2, ip2, T->NR3, ip3);
-#endif
-
- if (!ip1 || !ip2 || (T->NR3 >= 0 && !ip3))
- return 0;
-
- for (offset = 0; offset < datalen; offset++, aptr++) {
-#if defined(AFS_PPC64_LINUX20_ENV)
- ptr = (PROBETYPE*)(*aptr);
- if ((unsigned long)ptr <= KERNELBASE) {
- continue;
- }
-#else
- ptr = aptr;
-#endif
- if ((unsigned long)ptr < init_mm.start_code ||
-#if defined(AFS_AMD64_LINUX20_ENV)
- (unsigned long)ptr > init_mm.brk)
-#else
- (unsigned long)ptr > init_mm.end_data)
-#endif
- {
-/* printk("address 0x%lx (from 0x%lx %d) is out of range in check_table. wtf?\n", (unsigned long)x, (unsigned long)ptr, i);*/
- continue;
- }
-
- ret = check_table(P, ptr);
- if (ret >= 0) {
- /* return value is number of entries to skip */
- aptr += ret;
- offset += ret;
- continue;
- }
-
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0002) && DEBUG_IN_RANGE(P,ptr))
- printk("<7>try 0x%lx\n", (unsigned long)ptr);
-#endif
- if (ptr[_SS(T->NR1 - P->offset)] != ip1) continue;
- if (ptr[_SS(T->NR2 - P->offset)] != ip2) continue;
- if (ip3 && ptr[_SS(T->NR3 - P->offset)] != ip3) continue;
-
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0002)
- printk("<7>try found 0x%lx\n", (unsigned long)ptr);
-#endif
-#ifdef OSI_PROBE_KALLSYMS
- if (kallsyms_address_to_symbol) {
- ret = kallsyms_address_to_symbol((unsigned long)ptr,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (!ret || strcmp(sym_name, P->symbol)) continue;
- }
-#endif
- /* XXX should we make sure there is only one match? */
- return (void *)ptr;
- }
- return 0;
-}
-
-
-static int check_harder(probectl *P, PROBETYPE *p)
-{
- unsigned long ip1;
- int i, s;
-
- /* Check zapped syscalls */
- for (i = 1; i < P->n_zapped_syscalls; i++) {
- if (p[_SS(P->zapped_syscalls[i])] != p[_SS(P->zapped_syscalls[0])]) {
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0020) && DEBUG_IN_RANGE(P,p))
- printk("<7>check_harder 0x%lx zapped failed i=%d\n", (unsigned long)p, i);
-#endif
- return 0;
- }
- }
-
- /* Check unique syscalls */
- for (i = 0; i < P->n_unique_syscalls; i++) {
- for (s = 0; s < NR_syscalls; s++) {
- if (p[_SS(s)] == p[_SS(P->unique_syscalls[i])]
- && s != P->unique_syscalls[i]) {
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
- printk("<7>check_harder 0x%lx unique failed i=%d s=%d\n", (unsigned long)p, i, s);
-#endif
- return 0;
- }
- }
- }
-
-#if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
- ip1 = P->verify_fn ? (unsigned long)((struct fptr *)(P->verify_fn))->ip : 0;
-#else
- ip1 = (unsigned long)(P->verify_fn);
-#endif
-
- if (ip1 && p[_SS(P->verifyNR - P->offset)] != ip1) {
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
- printk("<7>check_harder 0x%lx verify failed\n", (unsigned long)p);
-#endif
- return 0;
- }
-
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
- printk("<7>check_harder 0x%lx success!\n", (unsigned long)p);
-#endif
- return 1;
-}
-
-static void *try_harder(probectl *P, PROBETYPE *ptr, unsigned long datalen)
-{
-#ifdef OSI_PROBE_KALLSYMS
- char *mod_name, *sec_name, *sym_name;
- unsigned long mod_start, mod_end;
- unsigned long sec_start, sec_end;
- unsigned long sym_start, sym_end;
-#endif
- unsigned long offset;
- void *match = 0;
- int ret;
-
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0001)
- printk("<7>osi_probe: %s try_harder\n", P->symbol);
-#endif
- for (offset = 0; offset < datalen; offset++, ptr++) {
- if ((unsigned long)ptr < init_mm.start_code ||
-#if defined(AFS_AMD64_LINUX20_ENV)
- (unsigned long)ptr > init_mm.brk)
-#else
- (unsigned long)ptr > init_mm.end_data)
-#endif
- {
-/* printk("address 0x%lx (from 0x%lx %d) is out of range in check_table. wtf?\n", (unsigned long)x, (unsigned long)ptr, i);*/
- continue;
- }
- ret = check_table(P, ptr);
- if (ret >= 0) {
- /* return value is number of entries to skip */
- ptr += ret;
- offset += ret;
- continue;
- }
-
-#ifdef OSI_PROBE_DEBUG
- if ((probe_debug & 0x0004) && DEBUG_IN_RANGE(P,ptr))
- printk("<7>try_harder 0x%lx\n", (unsigned long)ptr);
-#endif
- if (!check_harder(P, ptr))
- continue;
-
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0004)
- printk("<7>try_harder found 0x%lx\n", (unsigned long)ptr);
-#endif
-
-#ifdef OSI_PROBE_KALLSYMS
- if (kallsyms_address_to_symbol) {
- ret = kallsyms_address_to_symbol((unsigned long)ptr,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (!ret || strcmp(sym_name, P->symbol)) continue;
- }
-#endif
-
- if (match) {
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0005)
- printk("<7>%s: try_harder found multiple matches!\n", P->symbol);
-#endif
- return 0;
- }
-
- match = (void *)ptr;
- if (!probe_carefully)
- break;
- }
- return match;
-}
-
-
-#ifdef OSI_PROBE_DEBUG
-#define check_result(x,m) do { \
- if (probe_debug & 0x0001) { \
- printk("<7>osi_probe: %s = 0x%016lx %s\n", P->symbol, (unsigned long)(x), (m)); \
- } \
- if ((x) && ((int)(x)) != -ENOENT) { \
- *method = (m); \
- final_answer = (void *)(x); \
- } \
-} while (0)
-#else
-#define check_result(x,m) do { \
- if ((x) && ((int)(x)) != -ENOENT) { \
- *method = (m); \
- return (void *)(x); \
- } \
-} while (0)
-#endif
-static void *scan_for_syscall_table(probectl *P, PROBETYPE *B, unsigned long L)
-{
- tryctl *T;
- void *answer;
-#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- void *answer2;
-#endif
-#ifdef OSI_PROBE_DEBUG
- void *final_answer = 0;
-#endif
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0007)
- printk("<7>osi_probe: %s base=0x%lx, len=0x%lx\n",
- P->symbol, (unsigned long)B, L);
- if (probe_debug & 0x0009) {
- printk("<7>osi_probe: %s ktxt_lower_bound=0x%lx\n",
- P->symbol, ktxt_lower_bound);
- printk("<7>osi_probe: %s NR_syscalls=%d\n",
- P->symbol, NR_syscalls);
- }
-#endif
-
- for (T = P->trylist; T->name; T++) {
- answer = try(P, T, B, L);
-#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- answer2 = try(P, T, (PROBETYPE *)(2 + (void *)B), L);
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0003) {
- printk("<7>osi_probe: %s = 0x%016lx %s (even)\n",
- P->symbol, (unsigned long)(answer), T->name);
- printk("<7>osi_probe: %s = 0x%016lx %s (odd)\n",
- P->symbol, (unsigned long)(answer2), T->name);
- }
-#endif
- if (answer && answer2) answer = 0;
- else if (answer2) answer = answer2;
-#endif
- if (answer)
- return answer;
- }
-
- /* XXX more checks here */
-
- answer = try_harder(P, B, L);
-#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
- answer2 = try_harder(P, (PROBETYPE *)(2 + (void *)B), L);
-#ifdef OSI_PROBE_DEBUG
- if (probe_debug & 0x0005) {
- printk("<7>osi_probe: %s = 0x%016lx pattern scan (even)\n",
- P->symbol, (unsigned long)(answer));
- printk("<7>osi_probe: %s = 0x%016lx pattern scan (odd)\n",
- P->symbol, (unsigned long)(answer2));
- }
-#endif
- if (answer && answer2) answer = 0;
- else if (answer2) answer = answer2;
-#endif
- return answer;
-}
-
-static void *do_find_syscall_table(probectl *P, char **method)
-{
-#ifdef OSI_PROBE_KALLSYMS
- char *mod_name, *sec_name, *sym_name;
- unsigned long mod_start, mod_end;
- unsigned long sec_start, sec_end;
- unsigned long sym_start, sym_end;
- unsigned long token;
- int ret;
-#endif
- PROBETYPE *B;
- unsigned long L;
- void *answer;
-#ifdef OSI_PROBE_DEBUG
- void *final_answer = 0;
-#endif
-
- *method = "not found";
-
- /* if it's exported, there's nothing to do */
- check_result(P->weak_answer, "exported");
-
- /* ask the kernel to do the name lookup, if it's willing */
-#ifdef OSI_PROBE_KALLSYMS
- if (kallsyms_symbol_to_address) {
- token = 0;
- sym_start = 0;
- do {
- ret = kallsyms_symbol_to_address(P->symbol, &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") && sym_start)
- break;
- sym_start = 0;
- } while (ret);
- check_result(sym_start, "kallsyms_symbol_to_address");
- }
-#endif
-
- /* Maybe a little birdie told us */
- check_result(P->parm_answer, "module parameter");
- check_result(P->given_answer, "compiled-in");
-
- /* OK, so we have to scan. */
- B = (PROBETYPE *)((P->try_base) & ~(P->try_base_mask));
- L = P->try_length;
- /* Now, see if the kernel will tell us something better than the default */
-#ifdef OSI_PROBE_KALLSYMS
- if (kallsyms_address_to_symbol) {
- ret = kallsyms_address_to_symbol(P->try_sect_sym,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (ret) {
- B = (PROBETYPE *)sec_start;
- L = (sec_end - sec_start) / sizeof(unsigned long);
- }
- }
-#endif
-
- answer = scan_for_syscall_table(P, B, L);
- check_result(answer, "pattern scan");
- B = (PROBETYPE *)((P->alt_try_base) & ~(P->alt_try_base_mask));
- L = P->alt_try_length;
- /* Now, see if the kernel will tell us something better than the default */
-#ifdef OSI_PROBE_KALLSYMS
- if (kallsyms_address_to_symbol && P->alt_try_sect_sym) {
- ret = kallsyms_address_to_symbol(P->alt_try_sect_sym,
- &mod_name, &mod_start, &mod_end,
- &sec_name, &sec_start, &sec_end,
- &sym_name, &sym_start, &sym_end);
- if (ret) {
- B = (PROBETYPE *)sec_start;
- L = (sec_end - sec_start) / sizeof(unsigned long);
- }
- }
-#endif
- if (B && L) {
- answer = scan_for_syscall_table(P, B, L);
- check_result(answer, "pattern scan");
- }
-#ifdef OSI_PROBE_DEBUG
- return final_answer;
-#else
- return 0;
-#endif
-}
-
-void *osi_find_syscall_table(int which)
-{
- probectl *P;
- void *answer;
- char *method;
-
- if (which < 0 || which >= N_PROBE_LIST) {
- printk("error - afs_find_syscall_table called with invalid index!\n");
- return 0;
- }
- P = probe_list[which];
- if (which < 4) {
- P->parm_answer = (void *)sys_call_table_addr[which];
-#ifdef OSI_PROBE_DEBUG
- P->debug_answer = (void *)probe_debug_addr[which];
-#endif
- }
- answer = do_find_syscall_table(P, &method);
- if (!answer) {
- printk("Warning: failed to find address of %s\n", P->desc);
- printk("System call hooks will not be installed; proceeding anyway\n");
- return 0;
- }
- printk("Found %s at 0x%lx (%s)\n", P->desc, (unsigned long)answer, method);
- return answer;
-}
-
-
-#ifdef OSI_PROBE_STANDALONE
-int __init osi_probe_init(void)
-{
- int i;
-
- if (!probe_debug_tag) probe_debug_tag = jiffies;
- printk("*** osi_probe %ld debug = 0x%04x ***\n",
- probe_debug_tag, probe_debug);
- for (i = 0; i < N_PROBE_LIST; i++)
- (void)osi_find_syscall_table(i);
- return 0;
-}
-
-void osi_probe_exit(void) { }
-
-module_init(osi_probe_init);
-module_exit(osi_probe_exit);
-#endif
-#endif
-#else
-void *osi_find_syscall_table(int which)
-{
- return 0;
-}
-#endif /* EXPORTED_INIT_MM */
+++ /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"
-
-
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#ifdef HAVE_LINUX_SEQ_FILE_H
-#include <linux/seq_file.h>
-#endif
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/nfsclient.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/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-struct proc_dir_entry *openafs_procfs;
-
-#ifdef HAVE_LINUX_SEQ_FILE_H
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
- struct afs_q *cq, *tq;
- loff_t n = 0;
-
- AFS_GLOCK();
- ObtainReadLock(&afs_xcell);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tq = QNext(cq);
-
- if (n++ == *pos)
- break;
- }
- if (cq == &CellLRU)
- cq = NULL;
-
- AFS_GUNLOCK();
- return cq;
-}
-
-static void *c_next(struct seq_file *m, void *p, loff_t *pos)
-{
- struct afs_q *cq = p, *tq;
-
- AFS_GLOCK();
- (*pos)++;
- tq = QNext(cq);
-
- if (tq == &CellLRU)
- return NULL;
-
- AFS_GUNLOCK();
- return tq;
-}
-
-static void c_stop(struct seq_file *m, void *p)
-{
- AFS_GLOCK();
- ReleaseReadLock(&afs_xcell);
- AFS_GUNLOCK();
-}
-
-static int c_show(struct seq_file *m, void *p)
-{
- struct afs_q *cq = p;
- struct cell *tc = QTOC(cq);
- int j;
-
- seq_printf(m, ">%s #(%d/%d)\n", tc->cellName,
- tc->cellNum, tc->cellIndex);
-
- for (j = 0; j < AFS_MAXCELLHOSTS; j++) {
- afs_uint32 addr;
-
- if (!tc->cellHosts[j]) break;
-
- addr = tc->cellHosts[j]->addr->sa_ip;
- seq_printf(m, "%u.%u.%u.%u #%u.%u.%u.%u\n",
- NIPQUAD(addr), NIPQUAD(addr));
- }
-
- return 0;
-}
-
-static struct seq_operations afs_csdb_op = {
- .start = c_start,
- .next = c_next,
- .stop = c_stop,
- .show = c_show,
-};
-
-static int afs_csdb_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &afs_csdb_op);
-}
-
-static struct file_operations afs_csdb_operations = {
- .open = afs_csdb_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-
-static void *uu_start(struct seq_file *m, loff_t *pos)
-{
- struct unixuser *tu;
- loff_t n = 0;
- afs_int32 i;
-
- ObtainReadLock(&afs_xuser);
- if (!*pos)
- return (void *)(1);
-
- for (i = 0; i < NUSERS; i++) {
- for (tu = afs_users[i]; tu; tu = tu->next) {
- if (++n == *pos)
- return tu;
- }
- }
-
- return NULL;
-}
-
-static void *uu_next(struct seq_file *m, void *p, loff_t *pos)
-{
- struct unixuser *tu = p;
- afs_int32 i = 0;
-
- (*pos)++;
- if (!p) return NULL;
-
- if (p != (void *)1) {
- if (tu->next) return tu->next;
- i = UHash(tu->uid) + 1;
- }
-
- for (; i < NUSERS; i++)
- if (afs_users[i]) return afs_users[i];
- return NULL;
-}
-
-static void uu_stop(struct seq_file *m, void *p)
-{
- ReleaseReadLock(&afs_xuser);
-}
-
-static int uu_show(struct seq_file *m, void *p)
-{
- struct cell *tc = 0;
- struct unixuser *tu = p;
- union tokenUnion *token;
- char *cellname;
-
- if (p == (void *)1) {
- seq_printf(m, "%10s %4s %-6s %-25s %10s",
- "UID/PAG", "Refs", "States", "Cell", "ViceID");
- seq_printf(m, " %10s %10s %10s %3s",
- "Tok Set", "Tok Begin", "Tok Expire", "vno");
- seq_printf(m, " %-15s %10s %10s %s\n",
- "NFS Client", "UID/PAG", "Client UID", "Sysname(s)");
-
- return 0;
- }
-
- tu->refCount++;
- ReleaseReadLock(&afs_xuser);
-
- afs_LockUser(tu, READ_LOCK, 0);
-
- if (tu->cell == -1) {
- cellname = "<default>";
- } else {
- tc = afs_GetCellStale(tu->cell, READ_LOCK);
- if (tc) cellname = tc->cellName;
- else cellname = "<unknown>";
- }
-
- seq_printf(m, "%10d %4d %04x %-25s %10d",
- tu->uid, tu->refCount, tu->states, cellname, tu->viceId);
-
- if (tc) afs_PutCell(tc, READ_LOCK);
-
- if (tu->states & UHasTokens) {
- token = afs_FindToken(tu->tokens, RX_SECIDX_KAD);
- seq_printf(m, " %10d %10d %10d %3d",
- tu->tokenTime,
- (token != NULL)?token->rxkad.clearToken.BeginTimestamp:0,
- (token != NULL)?token->rxkad.clearToken.EndTimestamp:0,
- (token != NULL)?token->rxkad.clearToken.AuthHandle:0);
- } else {
- seq_printf(m, " %-36s", "Tokens Not Set");
- }
-
- if (tu->exporter && tu->exporter->exp_type == EXP_NFS) {
- struct nfsclientpag *np = (struct nfsclientpag *)(tu->exporter);
- char ipaddr[16];
- int i;
-
- sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(np->host));
- seq_printf(m, " %-15s %10d %10d", ipaddr, np->uid, np->client_uid);
- if (np->sysnamecount) {
- for (i = 0; i < np->sysnamecount; i++)
- seq_printf(m, " %s", np->sysname[i]);
- } else {
- seq_printf(m, " <no sysname list>");
- }
-
- } else if (tu->exporter) {
- seq_printf(m, " Unknown exporter type %d", tu->exporter->exp_type);
- }
- seq_printf(m, "\n");
-
- afs_PutUser(tu, READ_LOCK);
- ObtainReadLock(&afs_xuser);
-
- return 0;
-}
-
-static struct seq_operations afs_unixuser_seqop = {
- .start = uu_start,
- .next = uu_next,
- .stop = uu_stop,
- .show = uu_show,
-};
-
-static int afs_unixuser_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &afs_unixuser_seqop);
-}
-
-static struct file_operations afs_unixuser_fops = {
- .open = afs_unixuser_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-
-#else /* HAVE_LINUX_SEQ_FILE_H */
-
-static int
-csdbproc_info(char *buffer, char **start, off_t offset, int
-length)
-{
- int len = 0;
- off_t pos = 0;
- int cnt;
- struct afs_q *cq, *tq;
- struct cell *tc;
- char tbuffer[16];
- /* 90 - 64 cellname, 10 for 32 bit num and index, plus
- decor */
- char temp[91];
- afs_uint32 addr;
-
- ObtainReadLock(&afs_xcell);
-
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
-
- pos += 90;
-
- if (pos <= offset) {
- len = 0;
- } else {
- sprintf(temp, ">%s #(%d/%d)\n", tc->cellName,
- tc->cellNum, tc->cellIndex);
- sprintf(buffer + len, "%-89s\n", temp);
- len += 90;
- if (pos >= offset+length) {
- ReleaseReadLock(&afs_xcell);
- goto done;
- }
- }
-
- for (cnt = 0; cnt < AFS_MAXCELLHOSTS; cnt++) {
- if (!tc->cellHosts[cnt]) break;
- pos += 90;
- if (pos <= offset) {
- len = 0;
- } else {
- addr = ntohl(tc->cellHosts[cnt]->addr->sa_ip);
- sprintf(tbuffer, "%d.%d.%d.%d",
- (int)((addr>>24) & 0xff),
-(int)((addr>>16) & 0xff),
- (int)((addr>>8) & 0xff), (int)( addr & 0xff));
- sprintf(temp, "%s #%s\n", tbuffer, tbuffer);
- sprintf(buffer + len, "%-89s\n", temp);
- len += 90;
- if (pos >= offset+length) {
- ReleaseReadLock(&afs_xcell);
- goto done;
- }
- }
- }
- }
-
- ReleaseReadLock(&afs_xcell);
-
-done:
- *start = buffer + len - (pos - offset);
- len = pos - offset;
- if (len > length)
- len = length;
- return len;
-}
-
-#endif /* HAVE_LINUX_SEQ_FILE_H */
-
-void
-osi_proc_init(void)
-{
- struct proc_dir_entry *entry;
-#if !defined(EXPORTED_PROC_ROOT_FS)
- char path[64];
-#endif
-
-#if defined(EXPORTED_PROC_ROOT_FS)
- openafs_procfs = proc_mkdir(PROC_FSDIRNAME, proc_root_fs);
-#else
- sprintf(path, "fs/%s", PROC_FSDIRNAME);
- openafs_procfs = proc_mkdir(path, NULL);
-#endif
-#ifdef HAVE_LINUX_SEQ_FILE_H
- entry = create_proc_entry("unixusers", 0, openafs_procfs);
- if (entry) {
- entry->proc_fops = &afs_unixuser_fops;
-#if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
- entry->owner = THIS_MODULE;
-#endif
- }
- entry = create_proc_entry(PROC_CELLSERVDB_NAME, 0, openafs_procfs);
- if (entry)
- entry->proc_fops = &afs_csdb_operations;
-#else
- entry = create_proc_info_entry(PROC_CELLSERVDB_NAME, (S_IFREG|S_IRUGO), openafs_procfs, csdbproc_info);
-#endif
-#if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
- entry->owner = THIS_MODULE;
-#endif
-}
-
-void
-osi_proc_clean(void)
-{
-#if !defined(EXPORTED_PROC_ROOT_FS)
- char path[64];
-#endif
-
- remove_proc_entry(PROC_CELLSERVDB_NAME, openafs_procfs);
-#ifdef HAVE_LINUX_SEQ_FILE_H
- remove_proc_entry("unixusers", openafs_procfs);
-#endif
-#if defined(EXPORTED_PROC_ROOT_FS)
- remove_proc_entry(PROC_FSDIRNAME, proc_root_fs);
-#else
- sprintf(path, "fs/%s", PROC_FSDIRNAME);
- remove_proc_entry(path, 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
- */
-
-/*
- * 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_nfssrv.c */
-extern int osi_linux_nfs_initreq(struct vrequest *av, afs_ucred_t *cr,
- int *code);
-extern void osi_linux_nfssrv_init(void);
-extern void osi_linux_nfssrv_shutdown(void);
-extern afs_rwlock_t afs_xnfssrv;
-
-/* osi_file.c */
-extern afs_rwlock_t afs_xosi;
-extern int osi_InitCacheInfo(char *aname);
-extern int osi_rdwr(struct osi_file *osifile, struct uio *uiop, int rw);
-extern struct file *afs_linux_raw_open(afs_dcache_id_t *ainode, ino_t *hint);
-
-/* osi_ioctl.c */
-extern void osi_ioctl_init(void);
-extern void osi_ioctl_clean(void);
-
-/* osi_misc.c */
-extern void afs_osi_SetTime(osi_timeval_t * tvp);
-extern int osi_lookupname_internal(char *aname, int followlink,
- struct vfsmount **mnt, struct dentry **dpp);
-extern int osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- struct dentry **dpp);
-extern int osi_abspath(char *aname, char *buf, int buflen,
- int followlink, char **pathp);
-extern void afs_start_thread(void (*proc)(void), char *name);
-
-/* osi_probe.c */
-extern void *osi_find_syscall_table(int which);
-
-/* osi_proc.c */
-extern void osi_proc_init(void);
-extern void osi_proc_clean(void);
-
-/* osi_syscall.c */
-extern int osi_syscall_init(void);
-extern void osi_syscall_clean(void);
-
-/* osi_sysctl.c */
-extern int osi_sysctl_init(void);
-extern void osi_sysctl_clean(void);
-
-/* osi_vcache.c */
-extern void osi_ResetRootVCache(afs_uint32 volid);
-
-/* osi_vm.c */
-extern int osi_VM_FlushVCache(struct vcache *avc);
-extern void osi_VM_TryToSmush(struct vcache *avc, afs_ucred_t *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, afs_ucred_t *credp);
-extern void osi_VM_Truncate(struct vcache *avc, int alen,
- afs_ucred_t *acred);
-
-/* osi_vfsops.c */
-extern void vattr2inode(struct inode *ip, struct vattr *vp);
-extern int afs_init_inodecache(void);
-extern void afs_destroy_inodecache(void);
-
-/* osi_vnodeops.c */
-extern void afs_fill_inode(struct inode *ip, struct vattr *vattr);
-
-/* osi_groups.c */
-extern void osi_keyring_init(void);
-extern void osi_keyring_shutdown(void);
-extern int __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
- int change_parent);
-#ifdef LINUX_KEYRING_SUPPORT
-extern struct key_type key_type_afs_pag;
-#endif /* LINUX_KEYRING_SUPPORT */
-
-
-#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"
-
-
-#include "afs/sysincludes.h" /* Standard vendor system headers */
-#include "afsincludes.h" /* Afs-based standard headers */
-#include "afs/afs_stats.h" /* afs statistics */
-
-#if defined(HAVE_LINUX_FREEZER_H)
-#include <linux/freezer.h>
-#endif
-
-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;
- int code;
-
- AFS_STATCNT(osi_Wait);
- endTime = osi_Time() + (ams / 1000);
- if (ahandle)
- ahandle->proc = (caddr_t) current;
-
- do {
- AFS_ASSERT_GLOCK();
- code = afs_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;
-}
-
-
-
-
-afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
-#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-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);
-}
-
-/* afs_osi_TimedSleep
- *
- * Arguments:
- * event - event to sleep on
- * ams --- max sleep time in milliseconds
- * aintok - 1 if should sleep interruptibly
- *
- * Returns 0 if timeout, EINTR if signalled, and EGAIN if it might
- * have raced.
- */
-int
-afs_osi_TimedSleep(void *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
-/*
- * 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"
-
-
-#ifdef AFS_LINUX24_ENV
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#endif
-#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/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
-
-#ifndef NR_syscalls
-#define NR_syscalls 222
-#endif
-
-/* On SPARC64 and S390X, sys_call_table contains 32-bit entries
- * even though pointers are 64 bit quantities.
- * XXX unify this with osi_probe.c
- */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-#define SYSCALLTYPE unsigned int
-#define POINTER2SYSCALL (unsigned int)(unsigned long)
-#define SYSCALL2POINTER (void *)(long)
-#else
-#define SYSCALLTYPE void *
-#define POINTER2SYSCALL (void *)
-#define SYSCALL2POINTER (void *)
-#endif
-
-#if defined(AFS_S390X_LINUX24_ENV)
-#define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
- if (SYSCALL2POINTER FUNC > 0x7fffffff) { \
- TMPPAGE = kmalloc ( PAGE_SIZE, GFP_DMA|GFP_KERNEL ); \
- if (SYSCALL2POINTER TMPPAGE > 0x7fffffff) { \
- printf("Cannot allocate page for FUNC syscall jump vector\n"); \
- return EINVAL; \
- } \
- memcpy(TMPPAGE, syscall_jump_code, sizeof(syscall_jump_code)); \
- *(void **)(TMPPAGE + 0x0c) = &FUNC; \
- afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL TMPPAGE; \
- } else \
- afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
-#else
-#define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
- afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
-#endif
-
-#if defined(AFS_S390X_LINUX24_ENV)
-#define _S(x) ((x)<<1)
-#elif defined(AFS_IA64_LINUX20_ENV)
-#define _S(x) ((x)-1024)
-#else
-#define _S(x) x
-#endif
-
-
-/***** ALL PLATFORMS *****/
-extern asmlinkage long
-afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
-
-static SYSCALLTYPE *afs_sys_call_table;
-static SYSCALLTYPE afs_ni_syscall = 0;
-
-#ifdef AFS_S390X_LINUX24_ENV
-static void *afs_sys_setgroups_page = 0;
-static void *afs_sys_setgroups32_page = 0;
-static void *afs_syscall_page = 0;
-
-/* Because of how the syscall table is handled, we need to ensure our
- syscalls are within the first 2gb of address space. This means we need
- self-modifying code we can inject to call our handlers if the module
- is loaded high. If keyrings had advanced as fast as false protection
- this would be unnecessary. */
-
-uint32_t syscall_jump_code[] = {
- 0xe3d0f030, 0x00240dd0, 0xa7f40006, 0xffffffff, 0xffffffff, 0xe310d004,
- 0x0004e3d0, 0xf0300004, 0x07f10000,
-};
-#endif
-
-extern asmlinkage long afs_xsetgroups(int gidsetsize, gid_t * grouplist);
-asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
-
-#ifdef AFS_LINUX24_ENV
-extern asmlinkage long afs_xsetgroups32(int gidsetsize, gid_t * grouplist);
-asmlinkage int (*sys_setgroups32p) (int gidsetsize,
- __kernel_gid32_t * grouplist);
-#endif
-
-#if !defined(AFS_LINUX24_ENV)
-asmlinkage int (*sys_settimeofdayp) (struct timeval * tv, struct timezone * tz);
-#endif
-
-
-/***** AMD64 *****/
-#ifdef AFS_AMD64_LINUX20_ENV
-static SYSCALLTYPE *afs_ia32_sys_call_table;
-static SYSCALLTYPE ia32_ni_syscall = 0;
-
-extern asmlinkage long afs32_xsetgroups(int gidsetsize, u16 * grouplist);
-asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
-#ifdef AFS_LINUX24_ENV
-extern asmlinkage long afs32_xsetgroups32(int gidsetsize, gid_t * grouplist);
-asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
-#endif /* __NR_ia32_setgroups32 */
-#endif /* AFS_AMD64_LINUX20_ENV */
-
-
-/***** SPARC64 *****/
-#ifdef AFS_SPARC64_LINUX20_ENV
-extern SYSCALLTYPE *afs_sys_call_table32;
-static SYSCALLTYPE afs_ni_syscall32 = 0;
-
-extern asmlinkage long afs32_xsetgroups(int gidsetsize, u16 * grouplist);
-asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
- __kernel_gid_t32 * grouplist);
-#ifdef AFS_LINUX24_ENV
-/* This number is not exported for some bizarre reason. */
-#define __NR_setgroups32 82
-extern asmlinkage long afs32_xsetgroups32(int gidsetsize, gid_t * grouplist);
-asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
- __kernel_gid_t32 * grouplist);
-#endif
-
-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 */
-
-
-/***** IA64 *****/
-#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:\n\t"
- "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)\n\t"
- ".skip 8");
-}
-
-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:\n\t"
- "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)\n\t"
- ".skip 8");
-}
-
-struct fptr {
- void *ip;
- unsigned long gp;
-};
-
-#endif /* AFS_IA64_LINUX20_ENV */
-
-/**********************************************************************/
-/********************* System Call Initialization *********************/
-/**********************************************************************/
-
-int osi_syscall_init(void)
-{
-/***** IA64 *****/
-#ifdef AFS_IA64_LINUX20_ENV
- /* This needs to be first because we are declaring variables, and
- * also because the handling of syscall pointers is bizarre enough
- * that we want to special-case even the "common" part.
- */
- unsigned long kernel_gp = 0;
- static struct fptr sys_setgroups;
-
- afs_sys_call_table = osi_find_syscall_table(0);
- if (afs_sys_call_table) {
-
-#if !defined(AFS_LINUX24_ENV)
- /* XXX no sys_settimeofday on IA64? */
-#endif
-
- /* check we aren't already loaded */
- /* XXX this can't be right */
- if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
- == afs_syscall) {
- printf("AFS syscall entry point already in use!\n");
- return -EBUSY;
- }
-
- /* setup AFS entry point */
- afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
- afs_sys_call_table[_S(__NR_afs_syscall)] =
- POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
-
- /* setup setgroups */
- sys_setgroupsp = (void *)&sys_setgroups;
-
- ((struct fptr *)sys_setgroupsp)->ip =
- SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
- ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
-
- afs_sys_call_table[_S(__NR_setgroups)] =
- POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
- }
-
- /* XXX no 32-bit syscalls on IA64? */
-
-
-/***** COMMON (except IA64 or PPC64) *****/
-#else /* !AFS_IA64_LINUX20_ENV */
-
- afs_sys_call_table = osi_find_syscall_table(0);
- if (afs_sys_call_table) {
-#if !defined(AFS_LINUX24_ENV)
- sys_settimeofdayp =
- SYSCALL2POINTER afs_sys_call_table[_S(__NR_settimeofday)];
-#endif /* AFS_LINUX24_ENV */
-
- /* check we aren't already loaded */
- if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
- == afs_syscall) {
- printf("AFS syscall entry point already in use!\n");
- return -EBUSY;
- }
-
- /* setup AFS entry point */
- afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
-
- INSERT_SYSCALL(__NR_afs_syscall, afs_syscall_page, afs_syscall)
-
- /* setup setgroups */
- sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
- INSERT_SYSCALL(__NR_setgroups, afs_sys_setgroups_page, afs_xsetgroups)
-
-#if defined(__NR_setgroups32)
- /* setup setgroups32 */
- sys_setgroups32p = SYSCALL2POINTER afs_sys_call_table[__NR_setgroups32];
- INSERT_SYSCALL(__NR_setgroups32, afs_sys_setgroups32_page, afs_xsetgroups32)
-#endif
- }
-#endif /* !AFS_IA64_LINUX20_ENV */
-
-
-/***** AMD64 *****/
-#ifdef AFS_AMD64_LINUX20_ENV
- afs_ia32_sys_call_table = osi_find_syscall_table(1);
- if (afs_ia32_sys_call_table) {
- /* setup AFS entry point for IA32 */
- ia32_ni_syscall = afs_ia32_sys_call_table[__NR_ia32_afs_syscall];
- afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
- POINTER2SYSCALL afs_syscall;
-
- /* setup setgroups for IA32 */
- sys32_setgroupsp =
- SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups];
- afs_ia32_sys_call_table[__NR_ia32_setgroups] =
- POINTER2SYSCALL afs32_xsetgroups;
-
-#if AFS_LINUX24_ENV
- /* setup setgroups32 for IA32 */
- sys32_setgroups32p =
- SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups32];
- afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
- POINTER2SYSCALL afs32_xsetgroups32;
-#endif /* __NR_ia32_setgroups32 */
- }
-#endif /* AFS_AMD64_LINUX20_ENV */
-
-
-/***** SPARC64 *****/
-#ifdef AFS_SPARC64_LINUX20_ENV
- afs_sys_call_table32 = osi_find_syscall_table(1);
- if (afs_sys_call_table32) {
- /* setup AFS entry point for 32-bit SPARC */
- afs_ni_syscall32 = afs_sys_call_table32[__NR_afs_syscall];
- afs_sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
-
- /* setup setgroups for 32-bit SPARC */
- sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups];
- afs_sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
-
-#ifdef AFS_LINUX24_ENV
- /* setup setgroups32 for 32-bit SPARC */
- sys32_setgroups32p =
- SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups32];
- afs_sys_call_table32[__NR_setgroups32] =
- POINTER2SYSCALL afs32_xsetgroups32;
-#endif
- }
-#endif /* AFS_SPARC64_LINUX20_ENV */
- return 0;
-}
-
-
-
-/**********************************************************************/
-/************************ System Call Cleanup *************************/
-/**********************************************************************/
-
-void osi_syscall_clean(void)
-{
-/***** COMMON *****/
- if (afs_sys_call_table) {
- /* put back the AFS entry point */
- afs_sys_call_table[_S(__NR_afs_syscall)] = afs_ni_syscall;
-
- /* put back setgroups */
-#if defined(AFS_IA64_LINUX20_ENV)
- afs_sys_call_table[_S(__NR_setgroups)] =
- POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
-#else /* AFS_IA64_LINUX20_ENV */
- afs_sys_call_table[_S(__NR_setgroups)] =
- POINTER2SYSCALL sys_setgroupsp;
-#endif
-
-#if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
- /* put back setgroups32 */
- afs_sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
-#endif
-#if defined(AFS_S390X_LINUX24_ENV)
-#if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
- if (afs_sys_setgroups32_page)
- kfree(afs_sys_setgroups32_page);
-#endif
- if (afs_sys_setgroups_page)
- kfree(afs_sys_setgroups_page);
- if (afs_syscall_page)
- kfree(afs_syscall_page);
-#endif
- }
-
-
-/***** IA64 *****/
-#ifdef AFS_IA64_LINUX20_ENV
- /* XXX no 32-bit syscalls on IA64? */
-#endif
-
-
-/***** AMD64 *****/
-#ifdef AFS_AMD64_LINUX20_ENV
- if (afs_ia32_sys_call_table) {
- /* put back AFS entry point for IA32 */
- afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
- POINTER2SYSCALL ia32_ni_syscall;
-
- /* put back setgroups for IA32 */
- afs_ia32_sys_call_table[__NR_ia32_setgroups] =
- POINTER2SYSCALL sys32_setgroupsp;
-
-#ifdef AFS_LINUX24_ENV
- /* put back setgroups32 for IA32 */
- afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
- POINTER2SYSCALL sys32_setgroups32p;
-#endif
- }
-#endif
-
-
-/***** SPARC64 *****/
-#ifdef AFS_SPARC64_LINUX20_ENV
- if (afs_sys_call_table32) {
- /* put back AFS entry point for 32-bit SPARC */
- afs_sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
-
- /* put back setgroups for IA32 */
- afs_sys_call_table32[__NR_setgroups] =
- POINTER2SYSCALL sys32_setgroupsp;
-
-#ifdef AFS_LINUX24_ENV
- /* put back setgroups32 for IA32 */
- afs_sys_call_table32[__NR_setgroups32] =
- POINTER2SYSCALL sys32_setgroups32p;
-#endif
- }
-#endif
-}
+++ /dev/null
-/*
- * osi_sysctl.c: Linux sysctl interface to OpenAFS
- *
- * $Id$
- *
- * 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>
-#ifdef HAVE_LINUX_CONFIG_H
-#include <linux/config.h>
-#endif
-
-/* From afs_util.c */
-extern afs_int32 afs_new_inum;
-
-/* From afs_analyze.c */
-extern afs_int32 hm_retry_RO;
-extern afs_int32 hm_retry_RW;
-extern afs_int32 hm_retry_int;
-extern afs_int32 afs_blocksUsed_0;
-extern afs_int32 afs_blocksUsed_1;
-extern afs_int32 afs_blocksUsed_2;
-extern afs_int32 afs_pct1;
-extern afs_int32 afs_pct2;
-
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *afs_sysctl = NULL;
-
-static ctl_table afs_sysctl_table[] = {
- {
- .ctl_name = 1,
- .procname = "hm_retry_RO",
- .data = &hm_retry_RO,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 2,
- .procname = "hm_retry_RW",
- .data = &hm_retry_RW,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 3,
- .procname = "hm_retry_int",
- .data = &hm_retry_int,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 4,
- .procname = "GCPAGs",
- .data = &afs_gcpags,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 5,
- .procname = "rx_deadtime",
- .data = &afs_rx_deadtime,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 6,
- .procname = "bkVolPref",
- .data = &afs_bkvolpref,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 7,
- .procname = "afs_blocksUsed",
- .data = &afs_blocksUsed,
- .maxlen = sizeof(afs_int32),
- .mode = 0444,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 8,
- .procname = "afs_blocksUsed_0",
- .data = &afs_blocksUsed_0,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 9,
- .procname = "afs_blocksUsed_1",
- .data = &afs_blocksUsed_1,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 10,
- .procname = "afs_blocksUsed_2",
- .data = &afs_blocksUsed_2,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 11,
- .procname = "afs_pct1",
- .data = &afs_pct1,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 12,
- .procname = "afs_pct2",
- .data = &afs_pct2,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 13,
- .procname = "afs_cacheBlocks",
- .data = &afs_cacheBlocks,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = 14,
- .procname = "md5inum",
- .data = &afs_new_inum,
- .maxlen = sizeof(afs_int32),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {0}
-};
-
-static ctl_table fs_sysctl_table[] = {
- {
- .ctl_name = 1,
- .procname = "afs",
- .mode = 0555,
- .child = afs_sysctl_table
- },
- {0}
-};
-
-int
-osi_sysctl_init()
-{
-#if defined(REGISTER_SYSCTL_TABLE_NOFLAG)
- afs_sysctl = register_sysctl_table(fs_sysctl_table);
-#else
- afs_sysctl = register_sysctl_table(fs_sysctl_table, 0);
-#endif
- 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
- */
-
-#include <afsconfig.h>
-#include "afs/param.h"
-
-#include "afs/sysincludes.h" /*Standard vendor system headers */
-#include "afsincludes.h" /*AFS-based standard headers */
-
-#if defined(AFS_LINUX24_ENV)
-# define afs_linux_lock_dcache() spin_lock(&dcache_lock)
-# define afs_linux_unlock_dcache() spin_unlock(&dcache_lock)
-#else
-# define afs_linux_lock_dcache()
-# define afs_linux_unlock_dcache()
-#endif
-
-int
-osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
- int code;
- struct dentry *dentry;
- struct list_head *cur, *head;
-
- /* First, see if we can evict the inode from the dcache */
- if (defersleep && avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) {
- *slept = 1;
- ReleaseWriteLock(&afs_xvcache);
- AFS_GUNLOCK();
- afs_linux_lock_dcache();
- head = &(AFSTOV(avc))->i_dentry;
-
-restart:
- cur = head;
- while ((cur = cur->next) != head) {
- dentry = list_entry(cur, struct dentry, d_alias);
-
- if (d_unhashed(dentry))
- continue;
-
- dget_locked(dentry);
-
- afs_linux_unlock_dcache();
-
- if (d_invalidate(dentry) == -EBUSY) {
- dput(dentry);
- /* perhaps lock and try to continue? (use cur as head?) */
- goto inuse;
- }
- dput(dentry);
- afs_linux_lock_dcache();
- goto restart;
- }
- afs_linux_unlock_dcache();
-inuse:
- AFS_GLOCK();
- ObtainWriteLock(&afs_xvcache, 733);
- }
-
- /* See if we can evict it from the VLRUQ */
- if (VREFCOUNT_GT(avc,0) && !VREFCOUNT_GT(avc,1) && avc->opens == 0
- && (avc->f.states & CUnlinkedDel) == 0) {
- int didsleep = *slept;
-
- code = afs_FlushVCache(avc, slept);
- /* flushvcache wipes slept; restore slept if we did before */
- if (didsleep)
- *slept = didsleep;
-
- if (code == 0)
- return 1;
- }
-
- return 0;
-}
-
-struct vcache *
-osi_NewVnode(void)
-{
- struct inode *ip;
- struct vcache *tvc;
-
- AFS_GUNLOCK();
- ip = new_inode(afs_globalVFS);
- if (!ip)
- osi_Panic("afs_NewVCache: no more inodes");
- AFS_GLOCK();
-#if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
- tvc = VTOAFS(ip);
-#else
- tvc = afs_osi_Alloc(sizeof(struct vcache));
- osi_Assert(tvc != NULL);
- ip->u.generic_ip = tvc;
- tvc->v = ip;
-#endif
-
- return tvc;
-}
-
-/* XXX - This should probably be inline */
-void
-osi_PrePopulateVCache(struct vcache *avc) {
- avc->uncred = 0;
- memset(&(avc->f), 0, sizeof(struct fvcache));
-}
-
-/* XXX - This should become inline, or a #define */
-void
-osi_AttachVnode(struct vcache *avc, int seq) { }
-
-/* XXX - Again, inline or a #define */
-void
-osi_PostPopulateVCache(struct vcache *avc) {
- vSetType(avc, VREG);
-}
-
-void
-osi_ResetRootVCache(afs_uint32 volid)
-{
- struct vrequest *treq = NULL;
- struct vattr vattr;
- cred_t *credp;
- struct dentry *dp;
- struct vcache *vcp;
-
- afs_rootFid.Fid.Volume = volid;
- afs_rootFid.Fid.Vnode = 1;
- afs_rootFid.Fid.Unique = 1;
-
- credp = crref();
- if (afs_CreateReq(&treq, credp))
- goto out;
- vcp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
- if (!vcp)
- goto out;
- afs_getattr(vcp, &vattr, credp);
- afs_fill_inode(AFSTOV(vcp), &vattr);
-
- dp = d_find_alias(AFSTOV(afs_globalVp));
- spin_lock(&dcache_lock);
- list_del_init(&dp->d_alias);
- list_add(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
- dp->d_inode = AFSTOV(vcp);
- spin_unlock(&dcache_lock);
- dput(dp);
-
- AFS_FAST_RELE(afs_globalVp);
- afs_globalVp = vcp;
-out:
- crfree(credp);
- afs_DestroyReq(treq);
-}
+++ /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.
- */
-
-#ifndef OSI_VFS_H_
-#define OSI_VFS_H_
-
-typedef struct inode vnode_t;
-#define vnode inode
-
-/* Map vnode fields to inode fields */
-#define i_number i_ino
-#define v_count i_count
-#define v_op i_op
-#define v_fop i_fop
-#define v_type i_mode
-#define v_vfsp i_sb
-#define v_data u.generic_ip
-
-/* 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) (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))
-
-#ifndef HAVE_LINUX_I_SIZE_READ
-#define i_size_read(X) ((X)->i_size)
-#define i_size_write(X,Y) (X)->i_size = Y
-#endif
-
-#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"
-
-
-#define __NO_VERSION__ /* don't define kernel_version in module.h */
-#include <linux/module.h> /* early to avoid printf->printk mapping */
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#include "h/locks.h"
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-
-
-struct vcache *afs_globalVp = 0;
-struct vfs *afs_globalVFS = 0;
-#if defined(AFS_LINUX24_ENV)
-struct vfsmount *afs_cacheMnt;
-#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;
-extern int afs_notify_change(struct dentry *dp, struct iattr *iattrp);
-
-/* Forward declarations */
-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);
-
-/* 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.
- */
-
-
-/* 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_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
-
-struct super_block *
-afs_read_super(struct super_block *sb, void *data, int silent)
-{
- int code = 0;
-
- AFS_GLOCK();
- if (afs_was_mounted) {
- printf
- ("You must reload the AFS kernel extensions before remounting AFS.\n");
- AFS_GUNLOCK();
- return NULL;
- }
- afs_was_mounted = 1;
-
- /* Set basics of super_block */
-#if !defined(AFS_LINUX24_ENV)
- lock_super(sb);
-#endif
- MOD_INC_USE_COUNT;
-
- afs_globalVFS = sb;
- sb->s_flags |= MS_NOATIME;
- 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)
-#ifdef AFS_64BIT_CLIENT
-#if !defined(MAX_LFS_FILESIZE)
-#if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
-#elif BITS_PER_LONG==64
-#define MAX_LFS_FILESIZE 0x7fffffffffffffff
-#endif
-#endif
- sb->s_maxbytes = MAX_LFS_FILESIZE;
-#else
- sb->s_maxbytes = MAX_NON_LFS;
-#endif
-#endif
- code = afs_root(sb);
- if (code) {
- afs_globalVFS = NULL;
- MOD_DEC_USE_COUNT;
- }
-
-#if !defined(AFS_LINUX24_ENV)
- unlock_super(sb);
-#endif
-
- AFS_GUNLOCK();
- return code ? NULL : sb;
-}
-
-
-/* afs_root - stat the root of the file system. AFS global held on entry. */
-static int
-afs_root(struct super_block *afsp)
-{
- afs_int32 code = 0;
- struct vrequest treq;
- struct vcache *tvp = 0;
-
- AFS_STATCNT(afs_root);
- if (afs_globalVp && (afs_globalVp->f.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) {
- struct inode *ip = AFSTOV(tvp);
- struct vattr vattr;
-
- afs_getattr(tvp, &vattr, credp);
- afs_fill_inode(ip, &vattr);
-
- /* setup super_block and mount point inode. */
- afs_globalVp = tvp;
-#if defined(AFS_LINUX24_ENV)
- afsp->s_root = d_alloc_root(ip);
-#else
- afsp->s_root = d_alloc_root(ip, 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 */
-
-#if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
-#if defined(HAVE_KMEM_CACHE_T)
-static kmem_cache_t *afs_inode_cachep;
-#else
-struct kmem_cache *afs_inode_cachep;
-#endif
-
-static struct inode *
-afs_alloc_inode(struct super_block *sb)
-{
- struct vcache *vcp;
-
-#if defined(SLAB_KERNEL)
- vcp = (struct vcache *) kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
-#else
- vcp = (struct vcache *) kmem_cache_alloc(afs_inode_cachep, GFP_KERNEL);
-#endif
- if (!vcp)
- return NULL;
-
- return AFSTOV(vcp);
-}
-
-static void
-afs_destroy_inode(struct inode *inode)
-{
- kmem_cache_free(afs_inode_cachep, inode);
-}
-
-static void
-#if defined(HAVE_KMEM_CACHE_T)
-init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
-#else
-#if defined(KMEM_CACHE_INIT)
-init_once(struct kmem_cache * cachep, void * foo)
-#else
-init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
-#endif
-#endif
-{
- struct vcache *vcp = (struct vcache *) foo;
-
-#if defined(SLAB_CTOR_VERIFY)
- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR)
-#endif
- inode_init_once(AFSTOV(vcp));
-}
-
-int
-afs_init_inodecache(void)
-{
-#ifndef SLAB_RECLAIM_ACCOUNT
-#define SLAB_RECLAIM_ACCOUNT 0
-#endif
-
-#if defined(KMEM_CACHE_TAKES_DTOR)
- afs_inode_cachep = kmem_cache_create("afs_inode_cache",
- sizeof(struct vcache),
- 0, SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT,
- init_once, NULL);
-#else
- afs_inode_cachep = kmem_cache_create("afs_inode_cache",
- sizeof(struct vcache),
- 0, SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT,
- init_once);
-#endif
- if (afs_inode_cachep == NULL)
- return -ENOMEM;
- return 0;
-}
-
-void
-afs_destroy_inodecache(void)
-{
- if (afs_inode_cachep)
- (void) kmem_cache_destroy(afs_inode_cachep);
-}
-#else
-int
-afs_init_inodecache(void)
-{
- return 0;
-}
-
-void
-afs_destroy_inodecache(void)
-{
- return;
-}
-#endif
-
-static void
-afs_clear_inode(struct inode *ip)
-{
- struct vcache *vcp = VTOAFS(ip);
-
- if (vcp->vlruq.prev || vcp->vlruq.next)
- osi_Panic("inode freed while on LRU");
- if (vcp->hnext)
- osi_Panic("inode freed while still hashed");
-
-#if !defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
- afs_osi_Free(ip->u.generic_ip, sizeof(struct vcache));
-#endif
-}
-
-/* afs_put_super
- * Called from unmount to release super_block. */
-static void
-afs_put_super(struct super_block *sbp)
-{
- AFS_GLOCK();
- AFS_STATCNT(afs_unmount);
-
- if (!suser()) {
- AFS_GUNLOCK();
- return;
- }
-
- afs_globalVFS = 0;
- afs_globalVp = 0;
-
- afs_shutdown();
-#if defined(AFS_LINUX24_ENV)
- mntput(afs_cacheMnt);
-#endif
-
- osi_linux_verify_alloced_memory();
- AFS_GUNLOCK();
-
- sbp->s_dev = 0;
- MOD_DEC_USE_COUNT;
-}
-
-
-/* afs_statfs
- * statp is in user space, so we need to cobble together a statfs, then
- * copy it.
- */
-#if 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, *statp;
-
- if (size < sizeof(struct statfs))
- return;
-
- memset(&stat, 0, size);
- statp = &stat;
-#else
- memset(statp, 0, sizeof(*statp));
-#endif
-
- AFS_STATCNT(afs_statfs);
-
- /* hardcode in case that which is giveth is taken away */
- statp->f_type = 0x5346414F;
-#if defined(STATFS_TAKES_DENTRY)
- statp->f_bsize = dentry->d_sb->s_blocksize;
-#else
- statp->f_bsize = sbp->s_blocksize;
-#endif
- statp->f_blocks = statp->f_bfree = statp->f_bavail = statp->f_files =
- statp->f_ffree = AFS_VFS_FAKEFREE;
- 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;
-}
-
-struct super_operations afs_sops = {
-#if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
- .alloc_inode = afs_alloc_inode,
- .destroy_inode = afs_destroy_inode,
-#endif
- .clear_inode = afs_clear_inode,
- .put_super = afs_put_super,
- .statfs = afs_statfs,
-#if !defined(AFS_LINUX24_ENV)
- .notify_change = afs_notify_change,
-#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"
-
-
-#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. It must not be dropped.
- */
-int
-osi_VM_FlushVCache(struct vcache *avc)
-{
- struct inode *ip = AFSTOV(avc);
-
- if (VREFCOUNT(avc) > 1)
- return EBUSY;
-
- if (avc->opens != 0)
- return EBUSY;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- return vmtruncate(ip, 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, afs_ucred_t *acred, int sync)
-{
- struct inode *ip = AFSTOV(avc);
-
- invalidate_inode_pages(ip);
-}
-
-/* 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 = AFSTOV(avc);
-
- if (avc->f.states & CPageWrite)
- return; /* someone already writing */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
- /* filemap_fdatasync() only exported in 2.4.5 and above */
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
- filemap_fdatasync(ip->i_mapping);
- 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.
- */
-
-/* Note that for speed some of our Linux vnodeops do not initialise credp
- * before calling osi_FlushPages(). If credp is ever required on Linux,
- * then these callers should be updated.
- */
-void
-osi_VM_FlushPages(struct vcache *avc, afs_ucred_t *credp)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- struct inode *ip = AFSTOV(avc);
-
- truncate_inode_pages(&ip->i_data, 0);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- struct inode *ip = AFSTOV(avc);
-
- truncate_inode_pages(ip, 0);
-#else
- invalidate_inode_pages(AFSTOV(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, afs_ucred_t *acred)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- vmtruncate(AFSTOV(avc), alen);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
- struct inode *ip = AFSTOV(avc);
-
- truncate_inode_pages(ip, alen);
-#else
- invalidate_inode_pages(AFSTOV(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"
-
-
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "afs/afs_stats.h"
-#include "h/mm.h"
-#ifdef HAVE_MM_INLINE_H
-#include "h/mm_inline.h"
-#endif
-#include "h/pagemap.h"
-#if defined(AFS_LINUX24_ENV)
-#include "h/smp_lock.h"
-#endif
-#include "afs/lock.h"
-#include "afs/afs_bypasscache.h"
-
-#ifdef pgoff2loff
-#define pageoff(pp) pgoff2loff((pp)->index)
-#else
-#define pageoff(pp) pp->offset
-#endif
-
-#ifndef MAX_ERRNO
-#define MAX_ERRNO 1000L
-#endif
-
-extern struct vcache *afs_globalVp;
-#if defined(AFS_LINUX24_ENV)
-/* Some uses of BKL are perhaps not needed for bypass or memcache--
- * why don't we try it out? */
-extern struct afs_cacheOps afs_UfsCacheOps;
-#define maybe_lock_kernel() \
- do { \
- if(afs_cacheType == &afs_UfsCacheOps) \
- lock_kernel(); \
- } while(0);
-
-
-#define maybe_unlock_kernel() \
- do { \
- if(afs_cacheType == &afs_UfsCacheOps) \
- unlock_kernel(); \
- } while(0);
-#endif /* AFS_LINUX24_ENV */
-
-
-/* This function converts a positive error code from AFS into a negative
- * code suitable for passing into the Linux VFS layer. It checks that the
- * error code is within the permissable bounds for the ERR_PTR mechanism.
- *
- * _All_ error codes which come from the AFS layer should be passed through
- * this function before being returned to the kernel.
- */
-
-static inline int afs_convert_code(int code) {
- if ((code >= 0) && (code <= MAX_ERRNO))
- return -code;
- else
- return -EIO;
-}
-
-/* Linux doesn't require a credp for many functions, and crref is an expensive
- * operation. This helper function avoids obtaining it for VerifyVCache calls
- */
-
-static inline int afs_linux_VerifyVCache(struct vcache *avc, cred_t **retcred) {
- cred_t *credp = NULL;
- struct vrequest treq;
- int code;
-
- if (avc->f.states & CStatd) {
- if (retcred)
- *retcred = NULL;
- return 0;
- }
-
- credp = crref();
-
- code = afs_InitReq(&treq, credp);
- if (code == 0)
- code = afs_VerifyVCache2(avc, &treq);
-
- if (retcred != NULL)
- *retcred = credp;
- else
- crfree(credp);
-
- return afs_convert_code(code);
-}
-
-static ssize_t
-afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
-{
- ssize_t code = 0;
- struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- afs_size_t isize, offindex;
-#endif
-
- 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);
- code = afs_linux_VerifyVCache(vcp, NULL);
-
- if (code == 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
- offindex = *offp >> PAGE_CACHE_SHIFT;
- if(offindex > isize) {
- code=0;
- goto done;
- }
-#endif
- /* Linux's FlushPages implementation doesn't ever use credp,
- * so we optimise by not using it */
- osi_FlushPages(vcp, NULL); /* ensure stale pages are gone */
- AFS_GUNLOCK();
-#ifdef HAVE_LINUX_DO_SYNC_READ
- code = do_sync_read(fp, buf, count, offp);
-#else
- code = generic_file_read(fp, buf, count, offp);
-#endif
- AFS_GLOCK();
- }
-
- afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
- code);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-done:
-#endif
- AFS_GUNLOCK();
- 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;
- struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
- cred_t *credp;
-
- 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);
-
- code = afs_linux_VerifyVCache(vcp, &credp);
-
- ObtainWriteLock(&vcp->lock, 529);
- afs_FakeOpen(vcp);
- ReleaseWriteLock(&vcp->lock);
- if (code == 0) {
- AFS_GUNLOCK();
-#ifdef DO_SYNC_READ
- code = do_sync_write(fp, buf, count, offp);
-#else
- code = generic_file_write(fp, buf, count, offp);
-#endif
- AFS_GLOCK();
- }
-
- ObtainWriteLock(&vcp->lock, 530);
-
- if (vcp->execsOrWriters == 1 && !credp)
- credp = crref();
-
- afs_FakeClose(vcp, credp);
- 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);
-
- if (credp)
- crfree(credp);
- AFS_GUNLOCK();
- return code;
-}
-
-extern int BlobScan(struct dcache * afile, afs_int32 ablob);
-
-/* 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)
-{
- struct vcache *avc = VTOAFS(FILE_INODE(fp));
- struct vrequest treq;
- struct dcache *tdc;
- int code;
- int offset;
- int dirpos;
- struct DirEntry *de;
- struct DirBuffer entry;
- ino_t ino;
- int len;
- afs_size_t origOffset, tlen;
- cred_t *credp = crref();
- struct afs_fakestat_state fakestat;
-
- AFS_GLOCK();
- AFS_STATCNT(afs_readdir);
-
- code = afs_convert_code(afs_InitReq(&treq, credp));
- crfree(credp);
- if (code)
- goto out1;
-
- afs_InitFakeStat(&fakestat);
- code = afs_convert_code(afs_EvalFakeStat(&avc, &fakestat, &treq));
- if (code)
- goto out;
-
- /* update the cache entry */
- tagain:
- code = afs_convert_code(afs_VerifyVCache2(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;
- }
- ObtainSharedLock(&avc->lock, 810);
- UpgradeSToWLock(&avc->lock, 811);
- 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->f.states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseSharedLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainSharedLock(&avc->lock, 812);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->f.states & CStatd)
- || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseSharedLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- /* Set the readdir-in-progress flag, and downgrade the lock
- * to shared so others will be able to acquire a read lock.
- */
- avc->f.states |= CReadDir;
- avc->dcreaddir = tdc;
- avc->readdir_pid = MyPidxx2Pid(MyPidxx);
- ConvertWToSLock(&avc->lock);
-
- /* 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, offset);
- if (!dirpos)
- break;
-
- code = afs_dir_GetBlob(tdc, dirpos, &entry);
- if (code)
- break;
- de = (struct DirEntry *)entry.data;
-
- ino = afs_calc_inum(avc->f.fid.Cell, avc->f.fid.Fid.Volume,
- ntohl(de->fid.vnode));
-
- if (de->name)
- len = strlen(de->name);
- else {
- printf("afs_linux_readdir: afs_dir_GetBlob failed, null name (inode %lx, dirpos %d)\n",
- (unsigned long)&tdc->f.inode, dirpos);
- DRelease(&entry, 0);
- ReleaseSharedLock(&avc->lock);
- afs_PutDCache(tdc);
- code = -ENOENT;
- goto out;
- }
-
- /* filldir returns -EINVAL when the buffer is full. */
-#if (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->f.fid.Cell;
- afid.Fid.Volume = avc->f.fid.Fid.Volume;
- afid.Fid.Vnode = ntohl(de->fid.vnode);
- afid.Fid.Unique = ntohl(de->fid.vunique);
- if ((avc->f.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->f.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);
- }
- /*
- * If this is NFS readdirplus, then the filler is going to
- * call getattr on this inode, which will deadlock if we're
- * holding the GLOCK.
- */
- AFS_GUNLOCK();
- code = (*filldir) (dirbuf, de->name, len, offset, ino, type);
- AFS_GLOCK();
- }
-#else
- code = (*filldir) (dirbuf, de->name, len, offset, ino);
-#endif
- DRelease(&entry, 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);
- UpgradeSToWLock(&avc->lock, 813);
- avc->f.states &= ~CReadDir;
- avc->dcreaddir = 0;
- avc->readdir_pid = 0;
- ReleaseSharedLock(&avc->lock);
- code = 0;
-
-out:
- afs_PutFakeStat(&fakestat);
-out1:
- AFS_GUNLOCK();
- return code;
-}
-
-
-/* in afs_pioctl.c */
-extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
- unsigned long arg);
-
-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
-static long afs_unlocked_xioctl(struct file *fp, unsigned int com,
- unsigned long arg) {
- return afs_xioctl(FILE_INODE(fp), fp, com, arg);
-
-}
-#endif
-
-
-static int
-afs_linux_mmap(struct file *fp, struct vm_area_struct *vmap)
-{
- struct vcache *vcp = VTOAFS(FILE_INODE(fp));
- 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_linux_VerifyVCache(vcp, NULL);
-
- /* Linux's Flushpage implementation doesn't use credp, so optimise
- * our code to not need to crref() it */
- osi_FlushPages(vcp, NULL); /* ensure stale pages are gone */
- AFS_GUNLOCK();
- code = generic_file_mmap(fp, vmap);
- AFS_GLOCK();
- if (!code)
- vcp->f.states |= CMAPPED;
-
- AFS_GUNLOCK();
- return code;
-}
-
-static int
-afs_linux_open(struct inode *ip, struct file *fp)
-{
- struct vcache *vcp = VTOAFS(ip);
- cred_t *credp = crref();
- int code;
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
- code = afs_open(&vcp, fp->f_flags, credp);
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
-
- crfree(credp);
- return afs_convert_code(code);
-}
-
-static int
-afs_linux_release(struct inode *ip, struct file *fp)
-{
- struct vcache *vcp = VTOAFS(ip);
- cred_t *credp = crref();
- int code = 0;
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
- code = afs_close(vcp, fp->f_flags, credp);
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
-
- crfree(credp);
- return afs_convert_code(code);
-}
-
-static int
-#if defined(AFS_LINUX24_ENV)
-afs_linux_fsync(struct file *fp, struct dentry *dp, int datasync)
-#else
-afs_linux_fsync(struct file *fp, struct dentry *dp)
-#endif
-{
- int code;
- struct inode *ip = FILE_INODE(fp);
- cred_t *credp = crref();
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
- code = afs_fsync(VTOAFS(ip), credp);
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
- crfree(credp);
- return afs_convert_code(code);
-
-}
-
-
-static int
-afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
-{
- int code = 0;
- struct vcache *vcp = VTOAFS(FILE_INODE(fp));
- cred_t *credp = crref();
- struct AFS_FLOCK flock;
-#if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
- struct file_lock conflict;
-#elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
- struct file_lock *conflict;
-#endif
-
- /* Convert to a lock format afs_lockctl understands. */
- memset(&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;
- if (flp->fl_end == OFFSET_MAX)
- flock.l_len = 0; /* Lock to end of file */
- else
- flock.l_len = flp->fl_end - flp->fl_start + 1;
-
- /* 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_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
- AFS_GUNLOCK();
-
-#ifdef AFS_LINUX24_ENV
- if ((code == 0 || flp->fl_type == F_UNLCK) &&
- (cmd == F_SETLK || cmd == F_SETLKW)) {
-# ifdef POSIX_LOCK_FILE_WAIT_ARG
- code = posix_lock_file(fp, flp, 0);
-# else
- flp->fl_flags &=~ FL_SLEEP;
- code = posix_lock_file(fp, flp);
-# endif
- if (code && flp->fl_type != F_UNLCK) {
- struct AFS_FLOCK flock2;
- flock2 = flock;
- flock2.l_type = F_UNLCK;
- AFS_GLOCK();
- afs_lockctl(vcp, &flock2, F_SETLK, credp);
- AFS_GUNLOCK();
- }
- }
- /* If lockctl says there are no conflicting locks, then also check with the
- * kernel, as lockctl knows nothing about byte range locks
- */
- if (code == 0 && cmd == F_GETLK && flock.l_type == F_UNLCK) {
-# if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
- if (posix_test_lock(fp, flp, &conflict)) {
- locks_copy_lock(flp, &conflict);
- flp->fl_type = F_UNLCK;
- crfree(credp);
- return 0;
- }
-# elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
- if ((conflict = posix_test_lock(fp, flp))) {
- locks_copy_lock(flp, conflict);
- flp->fl_type = F_UNLCK;
- crfree(credp);
- return 0;
- }
-# else
- posix_test_lock(fp, flp);
- /* If we found a lock in the kernel's structure, return it */
- if (flp->fl_type != F_UNLCK) {
- crfree(credp);
- return 0;
- }
-# endif
- }
-
-#endif
- /* 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;
- if (flock.l_len == 0)
- flp->fl_end = OFFSET_MAX; /* Lock to end of file */
- else
- flp->fl_end = flock.l_start + flock.l_len - 1;
-
- crfree(credp);
- return code;
-}
-
-#ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
-static int
-afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
- int code = 0;
- struct vcache *vcp = VTOAFS(FILE_INODE(fp));
- cred_t *credp = crref();
- struct AFS_FLOCK flock;
- /* Convert to a lock format afs_lockctl understands. */
- memset(&flock, 0, sizeof(flock));
- flock.l_type = flp->fl_type;
- flock.l_pid = flp->fl_pid;
- flock.l_whence = 0;
- flock.l_start = 0;
- flock.l_len = 0;
-
- /* 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_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
- AFS_GUNLOCK();
-
- if ((code == 0 || flp->fl_type == F_UNLCK) &&
- (cmd == F_SETLK || cmd == F_SETLKW)) {
- flp->fl_flags &=~ FL_SLEEP;
- code = flock_lock_file_wait(fp, flp);
- if (code && flp->fl_type != F_UNLCK) {
- struct AFS_FLOCK flock2;
- flock2 = flock;
- flock2.l_type = F_UNLCK;
- AFS_GLOCK();
- afs_lockctl(vcp, &flock2, F_SETLK, credp);
- AFS_GUNLOCK();
- }
- }
- /* Convert flock back to Linux's file_lock */
- flp->fl_type = flock.l_type;
- flp->fl_pid = flock.l_pid;
-
- crfree(credp);
- return code;
-}
-#endif
-
-/* afs_linux_flush
- * essentially the same as afs_fsync() but we need to get the return
- * code for the sys_close() here, not afs_linux_release(), so call
- * afs_StoreAllSegments() with AFS_LASTSTORE
- */
-static int
-#if defined(FOP_FLUSH_TAKES_FL_OWNER_T)
-afs_linux_flush(struct file *fp, fl_owner_t id)
-#else
-afs_linux_flush(struct file *fp)
-#endif
-{
- struct vrequest treq;
- struct vcache *vcp;
- cred_t *credp;
- int code;
- int bypasscache;
-
- AFS_GLOCK();
-
- if ((fp->f_flags & O_ACCMODE) == O_RDONLY) { /* readers dont flush */
- AFS_GUNLOCK();
- return 0;
- }
-
- AFS_DISCON_LOCK();
-
- credp = crref();
- vcp = VTOAFS(FILE_INODE(fp));
-
- code = afs_InitReq(&treq, credp);
- if (code)
- goto out;
- /* If caching is bypassed for this file, or globally, just return 0 */
- if(cache_bypass_strategy == ALWAYS_BYPASS_CACHE)
- bypasscache = 1;
- else {
- ObtainReadLock(&vcp->lock);
- if(vcp->cachingStates & FCSBypass)
- bypasscache = 1;
- ReleaseReadLock(&vcp->lock);
- }
- if(bypasscache) {
- /* future proof: don't rely on 0 return from afs_InitReq */
- code = 0; goto out;
- }
-
- ObtainSharedLock(&vcp->lock, 535);
- if ((vcp->execsOrWriters > 0) && (file_count(fp) == 1)) {
- UpgradeSToWLock(&vcp->lock, 536);
- if (!AFS_IS_DISCONNECTED) {
- code = afs_StoreAllSegments(vcp,
- &treq,
- AFS_SYNC | AFS_LASTSTORE);
- } else {
- afs_DisconAddDirty(vcp, VDisconWriteOsiFlush, 1);
- }
- ConvertWToSLock(&vcp->lock);
- }
- code = afs_CheckCode(code, &treq, 54);
- ReleaseSharedLock(&vcp->lock);
-
-out:
- AFS_DISCON_UNLOCK();
- AFS_GUNLOCK();
-
- crfree(credp);
- return afs_convert_code(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,
-#ifdef HAVE_UNLOCKED_IOCTL
- .unlocked_ioctl = afs_unlocked_xioctl,
-#else
- .ioctl = afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
- .compat_ioctl = afs_unlocked_xioctl,
-#endif
- .open = afs_linux_open,
- .release = afs_linux_release,
-};
-
-struct file_operations afs_file_fops = {
- .read = afs_linux_read,
- .write = afs_linux_write,
-#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
-#endif
-#ifdef HAVE_UNLOCKED_IOCTL
- .unlocked_ioctl = afs_unlocked_xioctl,
-#else
- .ioctl = afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
- .compat_ioctl = afs_unlocked_xioctl,
-#endif
- .mmap = afs_linux_mmap,
- .open = afs_linux_open,
- .flush = afs_linux_flush,
- .release = afs_linux_release,
- .fsync = afs_linux_fsync,
- .lock = afs_linux_lock,
-#ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
- .flock = afs_linux_flock,
-#endif
-};
-
-static struct dentry *
-canonical_dentry(struct inode *ip)
-{
- struct vcache *vcp = VTOAFS(ip);
- struct dentry *first = NULL, *ret = NULL, *cur;
- struct list_head *head, *prev, *tmp;
-
- /* general strategy:
- * if vcp->target_link is set, and can be found in ip->i_dentry, use that.
- * otherwise, use the first dentry in ip->i_dentry.
- * if ip->i_dentry is empty, use the 'dentry' argument we were given.
- */
- /* note that vcp->target_link specifies which dentry to use, but we have
- * no reference held on that dentry. so, we cannot use or dereference
- * vcp->target_link itself, since it may have been freed. instead, we only
- * use it to compare to pointers in the ip->i_dentry list. */
-
- d_prune_aliases(ip);
-
- spin_lock(&dcache_lock);
-
- head = &ip->i_dentry;
- prev = ip->i_dentry.prev;
-
- while (prev != head) {
- tmp = prev;
- prev = tmp->prev;
- cur = list_entry(tmp, struct dentry, d_alias);
-
- if (!vcp->target_link || cur == vcp->target_link) {
- ret = cur;
- break;
- }
-
- if (!first) {
- first = cur;
- }
- }
- if (!ret && first) {
- ret = first;
- }
-
- vcp->target_link = ret;
-
- if (ret) {
- dget_locked(ret);
- }
- spin_unlock(&dcache_lock);
-
- return ret;
-}
-
-/**********************************************************************
- * AFS Linux dentry operations
- **********************************************************************/
-
-/* 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.
- */
-
-static inline void
-check_bad_parent(struct dentry *dp)
-{
- cred_t *credp;
- struct vcache *vcp = VTOAFS(dp->d_inode), *avc = NULL;
- struct vcache *pvc = VTOAFS(dp->d_parent->d_inode);
-
- if (vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) { /* bad parent */
- credp = crref();
-
- /* force a lookup, so vcp->mvid is fixed up */
- afs_lookup(pvc, (char *)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(AFSTOV(avc));
- crfree(credp);
- }
-
- return;
-}
-
-/* afs_linux_revalidate
- * Ensure vcache is stat'd before use. Return 0 if entry is valid.
- */
-static int
-afs_linux_revalidate(struct dentry *dp)
-{
- struct vattr vattr;
- struct vcache *vcp = VTOAFS(dp->d_inode);
- cred_t *credp;
- int code;
-
- if (afs_shuttingdown)
- return EIO;
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
-
-#ifdef notyet
- /* Make this a fast path (no crref), since it's called so often. */
- if (vcp->f.states & CStatd) {
-
- if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
- check_bad_parent(dp); /* check and correct mvid */
-
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- unlock_kernel();
-#endif
- return 0;
- }
-#endif
-
- /* This avoids the crref when we don't have to do it. Watch for
- * changes in afs_getattr that don't get replicated here!
- */
- if (vcp->f.states & CStatd &&
- (!afs_fakestat_enable || vcp->mvstat != 1) &&
- !afs_nfsexporter &&
- (vType(vcp) == VDIR || vType(vcp) == VLNK)) {
- code = afs_CopyOutAttrs(vcp, &vattr);
- } else {
- credp = crref();
- code = afs_getattr(vcp, &vattr, credp);
- crfree(credp);
- }
- if (!code)
- afs_fill_inode(AFSTOV(vcp), &vattr);
-
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
-
- return afs_convert_code(code);
-}
-
-/* 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) {
- vattrp->va_atime.tv_sec = iattrp->ia_atime;
- vattrp->va_atime.tv_usec = 0;
- }
- if (iattrp->ia_valid & ATTR_MTIME) {
- vattrp->va_mtime.tv_sec = iattrp->ia_mtime;
- vattrp->va_mtime.tv_usec = 0;
- }
- if (iattrp->ia_valid & ATTR_CTIME) {
- vattrp->va_ctime.tv_sec = iattrp->ia_ctime;
- vattrp->va_ctime.tv_usec = 0;
- }
-}
-
-/* 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;
-#ifdef STRUCT_INODE_HAS_I_BLKBITS
- ip->i_blkbits = AFS_BLKBITS;
-#endif
-#ifdef STRUCT_INODE_HAS_I_BLKSIZE
- ip->i_blksize = vp->va_blocksize;
-#endif
- ip->i_rdev = vp->va_rdev;
- ip->i_mode = vp->va_mode;
- ip->i_uid = vp->va_uid;
- ip->i_gid = vp->va_gid;
- i_size_write(ip, vp->va_size);
- ip->i_atime = vp->va_atime.tv_sec;
- ip->i_mtime = vp->va_mtime.tv_sec;
- ip->i_ctime = vp->va_ctime.tv_sec;
-}
-
-/* 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;
- cred_t *credp = crref();
- struct inode *ip = dp->d_inode;
- int code;
-
- VATTR_NULL(&vattr);
- iattr2vattr(&vattr, iattrp); /* Convert for AFS vnodeops call. */
-
- AFS_GLOCK();
- code = afs_setattr(VTOAFS(ip), &vattr, credp);
- if (!code) {
- afs_getattr(VTOAFS(ip), &vattr, credp);
- vattr2inode(ip, &vattr);
- }
- AFS_GUNLOCK();
- crfree(credp);
- return afs_convert_code(code);
-}
-
-/* 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..
- */
-static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
-#ifdef DOP_REVALIDATE_TAKES_NAMEIDATA
-afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
-#else
-afs_linux_dentry_revalidate(struct dentry *dp, int flags)
-#endif
-#else
-afs_linux_dentry_revalidate(struct dentry *dp)
-#endif
-{
- struct vattr vattr;
- cred_t *credp = NULL;
- struct vcache *vcp, *pvcp, *tvc = NULL;
- int valid;
- struct afs_fakestat_state fakestate;
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
- afs_InitFakeStat(&fakestate);
-
- if (dp->d_inode) {
-
- vcp = VTOAFS(dp->d_inode);
- pvcp = VTOAFS(dp->d_parent->d_inode); /* dget_parent()? */
-
- if (vcp == afs_globalVp)
- goto good_dentry;
-
- if (vcp->mvstat == 1) { /* mount point */
- if (vcp->mvid && (vcp->f.states & CMValid)) {
- int tryEvalOnly = 0;
- int code = 0;
- struct vrequest treq;
-
- credp = crref();
- code = afs_InitReq(&treq, credp);
- if (
-#ifdef AFS_DARWIN_ENV
- (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
- (strcmp(dp->d_name.name, "Contents") == 0) ||
-#endif
- (strcmp(dp->d_name.name, ".directory") == 0)) {
- tryEvalOnly = 1;
- }
- if (tryEvalOnly)
- code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
- else
- code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
- if ((tryEvalOnly && vcp->mvstat == 1) || code) {
- /* a mount point, not yet replaced by its directory */
- goto bad_dentry;
- }
- }
- } else
- if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
- check_bad_parent(dp); /* check and correct mvid */
-
-#ifdef notdef
- /* If the last looker changes, we should make sure the current
- * looker still has permission to examine this file. This would
- * always require a crref() which would be "slow".
- */
- if (vcp->last_looker != treq.uid) {
- if (!afs_AccessOK(vcp, (vType(vcp) == VREG) ? PRSFS_READ : PRSFS_LOOKUP, &treq, CHECK_MODE_BITS))
- goto bad_dentry;
-
- vcp->last_looker = treq.uid;
- }
-#endif
-
- /* If the parent's DataVersion has changed or the vnode
- * is longer valid, we need to do a full lookup. VerifyVCache
- * isn't enough since the vnode may have been renamed.
- */
-
- if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) {
-
- credp = crref();
- afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
- if (!tvc || tvc != vcp)
- goto bad_dentry;
-
- if (afs_getattr(vcp, &vattr, credp))
- goto bad_dentry;
-
- vattr2inode(AFSTOV(vcp), &vattr);
- dp->d_time = hgetlo(pvcp->f.m.DataVersion);
- }
-
- /* should we always update the attributes at this point? */
- /* unlikely--the vcache entry hasn't changed */
-
- } else {
-#ifdef notyet
- pvcp = VTOAFS(dp->d_parent->d_inode); /* dget_parent()? */
- if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time)
- goto bad_dentry;
-#endif
-
- /* No change in parent's DataVersion so this negative
- * lookup is still valid. BUT, if a server is down a
- * negative lookup can result so there should be a
- * liftime as well. For now, always expire.
- */
-
- goto bad_dentry;
- }
-
- good_dentry:
- valid = 1;
-
- done:
- /* Clean up */
- if (tvc)
- afs_PutVCache(tvc);
- afs_PutFakeStat(&fakestate);
- AFS_GUNLOCK();
- if (credp)
- crfree(credp);
-
- if (!valid) {
- shrink_dcache_parent(dp);
- d_drop(dp);
- }
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
- return valid;
-
- bad_dentry:
- if (have_submounts(dp))
- valid = 1;
- else
- valid = 0;
- goto done;
-}
-
-static void
-afs_dentry_iput(struct dentry *dp, struct inode *ip)
-{
- struct vcache *vcp = VTOAFS(ip);
-
- AFS_GLOCK();
- if (!AFS_IS_DISCONNECTED || (vcp->f.states & CUnlinked)) {
- (void) afs_InactiveVCache(vcp, NULL);
- }
- AFS_GUNLOCK();
-#ifdef DCACHE_NFSFS_RENAMED
- dp->d_flags &= ~DCACHE_NFSFS_RENAMED;
-#endif
-
- iput(ip);
-}
-
-static int
-afs_dentry_delete(struct dentry *dp)
-{
- if (dp->d_inode && (VTOAFS(dp->d_inode)->f.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,
- .d_iput = afs_dentry_iput,
-};
-
-/**********************************************************************
- * 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.
- */
-static int
-#ifdef IOP_CREATE_TAKES_NAMEIDATA
-afs_linux_create(struct inode *dip, struct dentry *dp, int mode,
- struct nameidata *nd)
-#else
-afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
-#endif
-{
- struct vattr vattr;
- cred_t *credp = crref();
- const char *name = dp->d_name.name;
- struct vcache *vcp;
- int code;
-
- VATTR_NULL(&vattr);
- vattr.va_mode = mode;
- vattr.va_type = mode & S_IFMT;
-
- AFS_GLOCK();
- code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
- &vcp, credp);
-
- if (!code) {
- struct inode *ip = AFSTOV(vcp);
-
- afs_getattr(vcp, &vattr, credp);
- afs_fill_inode(ip, &vattr);
- insert_inode_hash(ip);
- dp->d_op = &afs_dentry_operations;
- dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
- d_instantiate(dp, ip);
- }
- AFS_GUNLOCK();
-
- crfree(credp);
- return afs_convert_code(code);
-}
-
-/* afs_linux_lookup */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
-static struct dentry *
-#ifdef IOP_LOOKUP_TAKES_NAMEIDATA
-afs_linux_lookup(struct inode *dip, struct dentry *dp,
- struct nameidata *nd)
-#else
-afs_linux_lookup(struct inode *dip, struct dentry *dp)
-#endif
-#else
-static int
-afs_linux_lookup(struct inode *dip, struct dentry *dp)
-#endif
-{
- cred_t *credp = crref();
- struct vcache *vcp = NULL;
- const char *comp = dp->d_name.name;
- struct inode *ip = NULL;
- int code;
-
- AFS_GLOCK();
- code = afs_lookup(VTOAFS(dip), (char *)comp, &vcp, credp);
-
- if (vcp) {
- struct vattr vattr;
- struct vcache *parent_vc = VTOAFS(dip);
-
- if (parent_vc == vcp) {
- /* This is possible if the parent dir is a mountpoint to a volume,
- * and the dir entry we looked up is a mountpoint to the same
- * volume. Linux cannot cope with this, so return an error instead
- * of risking a deadlock or panic. */
- afs_PutVCache(vcp);
- code = EDEADLK;
- AFS_GUNLOCK();
- goto done;
- }
-
- ip = AFSTOV(vcp);
- afs_getattr(vcp, &vattr, credp);
- afs_fill_inode(ip, &vattr);
- if (
-#ifdef HAVE_LINUX_HLIST_UNHASHED
- hlist_unhashed(&ip->i_hash)
-#else
- ip->i_hash.prev == NULL
-#endif
- )
- insert_inode_hash(ip);
- }
- dp->d_op = &afs_dentry_operations;
- dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
- AFS_GUNLOCK();
-
-#if defined(AFS_LINUX24_ENV)
- if (ip && S_ISDIR(ip->i_mode)) {
- d_prune_aliases(ip);
- }
-#endif
- d_add(dp, ip);
-
- done:
- 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(afs_convert_code(code));
-#else
- if (code == ENOENT)
- code = 0;
- return afs_convert_code(code);
-#endif
-}
-
-static 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(VTOAFS(oldip), VTOAFS(dip), (char *)name, credp);
-
- AFS_GUNLOCK();
- crfree(credp);
- return afs_convert_code(code);
-}
-
-static int
-afs_linux_unlink(struct inode *dip, struct dentry *dp)
-{
- int code = EBUSY;
- cred_t *credp = crref();
- const char *name = dp->d_name.name;
- struct vcache *tvc = VTOAFS(dp->d_inode);
-
- if (VREFCOUNT(tvc) > 1 && tvc->opens > 0
- && !(tvc->f.states & CUnlinked)) {
- struct dentry *__dp;
- char *__name;
-
- __dp = NULL;
- __name = NULL;
- do {
- dput(__dp);
-
- AFS_GLOCK();
- if (__name)
- osi_FreeSmallSpace(__name);
- __name = afs_newname();
- AFS_GUNLOCK();
-
- __dp = lookup_one_len(__name, dp->d_parent, strlen(__name));
-
- if (IS_ERR(__dp))
- goto out;
- } while (__dp->d_inode != NULL);
-
- AFS_GLOCK();
- code = afs_rename(VTOAFS(dip), (char *)dp->d_name.name, VTOAFS(dip), (char *)__dp->d_name.name, credp);
- if (!code) {
- tvc->mvid = (void *) __name;
- crhold(credp);
- if (tvc->uncred) {
- crfree(tvc->uncred);
- }
- tvc->uncred = credp;
- tvc->f.states |= CUnlinked;
-#ifdef DCACHE_NFSFS_RENAMED
- dp->d_flags |= DCACHE_NFSFS_RENAMED;
-#endif
- } else {
- osi_FreeSmallSpace(__name);
- }
- AFS_GUNLOCK();
-
- if (!code) {
- __dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
- d_move(dp, __dp);
- }
- dput(__dp);
-
- goto out;
- }
-
- AFS_GLOCK();
- code = afs_remove(VTOAFS(dip), (char *)name, credp);
- AFS_GUNLOCK();
- if (!code)
- d_drop(dp);
-out:
- crfree(credp);
- return afs_convert_code(code);
-}
-
-
-static 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);
-
- VATTR_NULL(&vattr);
- AFS_GLOCK();
- code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL,
- credp);
- AFS_GUNLOCK();
- crfree(credp);
- return afs_convert_code(code);
-}
-
-static 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;
-
- VATTR_NULL(&vattr);
- vattr.va_mask = ATTR_MODE;
- vattr.va_mode = mode;
- AFS_GLOCK();
- code = afs_mkdir(VTOAFS(dip), (char *)name, &vattr, &tvcp, credp);
-
- if (tvcp) {
- struct inode *ip = AFSTOV(tvcp);
-
- afs_getattr(tvcp, &vattr, credp);
- afs_fill_inode(ip, &vattr);
-
- dp->d_op = &afs_dentry_operations;
- dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
- d_instantiate(dp, ip);
- }
- AFS_GUNLOCK();
-
- crfree(credp);
- return afs_convert_code(code);
-}
-
-static int
-afs_linux_rmdir(struct inode *dip, struct dentry *dp)
-{
- int code;
- cred_t *credp = crref();
- const char *name = dp->d_name.name;
-
- /* locking kernel conflicts with glock? */
-
- AFS_GLOCK();
- code = afs_rmdir(VTOAFS(dip), (char *)name, credp);
- AFS_GUNLOCK();
-
- /* 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);
- }
-
- crfree(credp);
- return afs_convert_code(code);
-}
-
-
-static 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;
- struct dentry *rehash = NULL;
-
- if (!list_empty(&newdp->d_hash)) {
- d_drop(newdp);
- rehash = newdp;
- }
-
-#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&olddp->d_count) > 1)
- shrink_dcache_parent(olddp);
-#endif
-
- AFS_GLOCK();
- code = afs_rename(VTOAFS(oldip), (char *)oldname, VTOAFS(newip), (char *)newname, credp);
- AFS_GUNLOCK();
-
- if (!code)
- olddp->d_time = 0; /* force to revalidate */
-
- if (rehash)
- d_rehash(rehash);
-
- crfree(credp);
- return afs_convert_code(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();
- struct uio tuio;
- struct iovec iov;
-
- memset(&tuio, 0, sizeof(tuio));
- memset(&iov, 0, sizeof(iov));
-
- setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
- code = afs_readlink(VTOAFS(ip), &tuio, credp);
- crfree(credp);
-
- if (!code)
- return maxlen - tuio.uio_resid;
- else
- return afs_convert_code(code);
-}
-
-#if !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
-/* afs_linux_readlink
- * Fill target (which is in user space) with contents of symlink.
- */
-static 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.
- */
-#if defined(AFS_LINUX24_ENV)
-static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- int code;
- char *name;
-
- name = osi_Alloc(PATH_MAX);
- if (!name) {
- return -EIO;
- }
-
- AFS_GLOCK();
- code = afs_linux_ireadlink(dentry->d_inode, name, PATH_MAX - 1, AFS_UIOSYS);
- AFS_GUNLOCK();
-
- if (code < 0) {
- goto out;
- }
-
- name[code] = '\0';
- code = vfs_follow_link(nd, name);
-
-out:
- osi_Free(name, PATH_MAX);
-
- return code;
-}
-
-#else /* !defined(AFS_LINUX24_ENV) */
-
-static 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);
- if (code < -MAX_ERRNO)
- res = ERR_PTR(-EIO);
- else
- 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_LINUX24_ENV */
-#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
-
-static inline int
-afs_linux_can_bypass(struct inode *ip) {
- switch(cache_bypass_strategy) {
- case NEVER_BYPASS_CACHE:
- return 0;
- case ALWAYS_BYPASS_CACHE:
- return 1;
- case LARGE_FILES_BYPASS_CACHE:
- if(i_size_read(ip) > cache_bypass_threshold)
- return 1;
- default:
- return 0;
- }
-}
-
-/* afs_linux_readpage
- * all reads come through here. A strategy-like read call.
- */
-static int
-afs_linux_readpage(struct file *fp, struct page *pp)
-{
- afs_int32 code;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- char *address;
- afs_offs_t offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
-#else
- ulong address = afs_linux_page_address(pp);
- afs_offs_t offset = pageoff(pp);
-#endif
- afs_int32 bypasscache = 0; /* bypass for this read */
- struct nocache_read_request *ancr;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- afs_int32 isize;
-#endif
- struct uio *auio;
- struct iovec *iovecp;
- struct inode *ip = FILE_INODE(fp);
- afs_int32 cnt = page_count(pp);
- struct vcache *avc = VTOAFS(ip);
- cred_t *credp;
-
- credp = crref();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- address = kmap(pp);
- ClearPageError(pp);
-#else
- atomic_add(1, &pp->count);
- set_bit(PG_locked, &pp->flags); /* other bits? See mm.h */
- clear_bit(PG_error, &pp->flags);
-#endif
- /* if bypasscache, receiver frees, else we do */
- auio = osi_Alloc(sizeof(struct uio));
- iovecp = osi_Alloc(sizeof(struct iovec));
-
- setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
- AFS_UIOSYS);
-
- bypasscache = afs_linux_can_bypass(ip);
-
- /* In the new incarnation of selective caching, a file's caching policy
- * can change, eg because file size exceeds threshold, etc. */
- trydo_cache_transition(avc, credp, bypasscache);
-
- if(bypasscache) {
- if(address)
- kunmap(pp);
- /* save the page for background map */
- auio->uio_iov->iov_base = (void*) pp;
- /* the background thread will free this */
- ancr = osi_Alloc(sizeof(struct nocache_read_request));
- ancr->auio = auio;
- ancr->offset = offset;
- ancr->length = PAGE_SIZE;
-
- maybe_lock_kernel();
- code = afs_ReadNoCache(avc, ancr, credp);
- maybe_unlock_kernel();
-
- goto done; /* skips release page, doing it in bg thread */
- }
-
-#ifdef AFS_LINUX24_ENV
- maybe_lock_kernel();
-#endif
- AFS_GLOCK();
- AFS_DISCON_LOCK();
- 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 */
-
- code = afs_rdwr(avc, auio, UIO_READ, 0, 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_DISCON_UNLOCK();
- AFS_GUNLOCK();
-#ifdef AFS_LINUX24_ENV
- maybe_unlock_kernel();
-#endif
- if (!code) {
- /* XXX valid for no-cache also? Check last bits of files... :)
- * Cognate code goes in afs_NoCacheFetchProc. */
- if (auio->uio_resid) /* zero remainder of page */
- memset((void *)(address + (PAGE_SIZE - auio->uio_resid)), 0,
- auio->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
- } /* !code */
-
-#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
-
- /* do not call afs_GetDCache if cache is bypassed */
- if(bypasscache)
- goto done;
-
- /* free if not bypassing cache */
- osi_Free(auio, sizeof(struct uio));
- osi_Free(iovecp, sizeof(struct iovec));
-
- if (!code && AFS_CHUNKOFFSET(offset) == 0) {
- struct dcache *tdc;
- struct vrequest treq;
-
- AFS_GLOCK();
- 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);
- }
- AFS_GUNLOCK();
- }
-
-done:
- crfree(credp);
- return afs_convert_code(code);
-}
-
-#if defined(AFS_LINUX24_ENV)
-static int
-afs_linux_writepage_sync(struct inode *ip, struct page *pp,
- unsigned long offset, unsigned int count)
-{
- struct vcache *vcp = VTOAFS(ip);
- char *buffer;
- afs_offs_t base;
- int code = 0;
- cred_t *credp;
- struct uio tuio;
- struct iovec iovec;
- int f_flags = 0;
-
- memset(&tuio, 0, sizeof(tuio));
- memset(&iovec, 0, sizeof(iovec));
-
- buffer = kmap(pp) + offset;
- base = (((loff_t) pp->index) << PAGE_CACHE_SHIFT) + offset;
-
- credp = crref();
- maybe_lock_kernel();
- AFS_GLOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
- ICL_TYPE_INT32, 99999);
-
- ObtainWriteLock(&vcp->lock, 532);
- if (vcp->f.states & CPageWrite) {
- ReleaseWriteLock(&vcp->lock);
- AFS_GUNLOCK();
- maybe_unlock_kernel();
- crfree(credp);
- kunmap(pp);
- /* should mark it dirty? */
- return(0);
- }
- vcp->f.states |= CPageWrite;
- ReleaseWriteLock(&vcp->lock);
-
- setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
-
- code = afs_write(vcp, &tuio, f_flags, credp, 0);
-
- i_size_write(ip, vcp->f.m.Length);
- ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
-
- ObtainWriteLock(&vcp->lock, 533);
- if (!code) {
- struct vrequest treq;
-
- if (!afs_InitReq(&treq, credp))
- code = afs_DoPartialWrite(vcp, &treq);
- }
- code = code ? afs_convert_code(code) : count - tuio.uio_resid;
-
- vcp->f.states &= ~CPageWrite;
- ReleaseWriteLock(&vcp->lock);
-
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
- ICL_TYPE_INT32, code);
-
- AFS_GUNLOCK();
- maybe_unlock_kernel();
- crfree(credp);
- kunmap(pp);
-
- return code;
-}
-
-
-static int
-#ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
-afs_linux_writepage(struct page *pp, struct writeback_control *wbc)
-#else
-afs_linux_writepage(struct page *pp)
-#endif
-{
- struct address_space *mapping = pp->mapping;
- struct inode *inode;
- unsigned long end_index;
- unsigned offset = PAGE_CACHE_SIZE;
- long status;
-
- if (PageLaunder(pp)) {
- return(fail_writepage(pp));
- }
-
- inode = (struct inode *)mapping->host;
- end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
-
- /* easy case */
- if (pp->index < end_index)
- goto do_it;
- /* things got complicated... */
- offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
- /* OK, are we completely out? */
- if (pp->index >= end_index + 1 || !offset)
- return -EIO;
- do_it:
- status = afs_linux_writepage_sync(inode, pp, 0, offset);
- SetPageUptodate(pp);
- UnlockPage(pp);
- if (status == offset)
- return 0;
- else
- return status;
-}
-#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.
- */
-static int
-afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
- unsigned int count, int sync)
-{
- struct vcache *vcp = VTOAFS(FILE_INODE(fp));
- u8 *page_addr = (u8 *) afs_linux_page_address(pp);
- int code = 0;
- cred_t *credp;
- struct uio tuio;
- struct iovec iovec;
-
- memset(&tuio, 0, sizeof(tuio));
- memset(&iovec, 0, sizeof(iovec));
-
- set_bit(PG_locked, &pp->flags);
-
- credp = crref();
- AFS_GLOCK();
- AFS_DISCON_LOCK();
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
- 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);
-
- i_size_write(ip, vcp->f.m.Length);
- ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
-
- if (!code) {
- struct vrequest treq;
-
- ObtainWriteLock(&vcp->lock, 533);
- vcp->f.m.Date = osi_Time(); /* set modification time */
- if (!afs_InitReq(&treq, credp))
- code = afs_DoPartialWrite(vcp, &treq);
- ReleaseWriteLock(&vcp->lock);
- }
-
- code = code ? afs_convert_code(code) : count - tuio.uio_resid;
- afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
- ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
- ICL_TYPE_INT32, code);
-
- AFS_DISCON_UNLOCK();
- AFS_GUNLOCK();
- crfree(credp);
-
- clear_bit(PG_locked, &pp->flags);
- return code;
-}
-#endif
-
-/* afs_linux_permission
- * Check access rights - returns error if can't check or permission denied.
- */
-static int
-#ifdef IOP_PERMISSION_TAKES_NAMEIDATA
-afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
-#else
-afs_linux_permission(struct inode *ip, int mode)
-#endif
-{
- 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(VTOAFS(ip), tmp, credp);
-
- AFS_GUNLOCK();
- crfree(credp);
- return afs_convert_code(code);
-}
-
-#if defined(AFS_LINUX24_ENV) && !defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
-static int
-afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
- unsigned to)
-{
- int code;
-
- code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
- offset, to - offset);
- kunmap(page);
-
- return code;
-}
-
-static int
-afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
- unsigned to)
-{
-/* sometime between 2.4.0 and 2.4.19, the callers of prepare_write began to
- call kmap directly instead of relying on us to do it */
- kmap(page);
- return 0;
-}
-#endif
-
-#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
-static int
-afs_linux_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
-{
- int code;
- unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-
- code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
- from, copied);
- unlock_page(page);
- page_cache_release(page);
- return code;
-}
-
-static int
-afs_linux_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
-{
- struct page *page;
- pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-#if defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN)
- page = grab_cache_page_write_begin(mapping, index, flags);
-#else
- page = __grab_cache_page(mapping, index);
-#endif
- *pagep = page;
-
- return 0;
-}
-#endif
-
-static int
-afs_linux_dir_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct dentry **dpp;
- struct dentry *target;
-
- target = canonical_dentry(dentry->d_inode);
-
- dpp = &nd->dentry;
-
- dput(*dpp);
-
- if (target) {
- *dpp = target;
- } else {
- *dpp = dget(dentry);
- }
-
- nd->last_type = LAST_BIND;
-
- return 0;
-}
-
-static struct inode_operations afs_file_iops = {
-#if 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)
-static struct address_space_operations afs_file_aops = {
- .readpage = afs_linux_readpage,
- .writepage = afs_linux_writepage,
-#if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
- .write_begin = afs_linux_write_begin,
- .write_end = afs_linux_write_end,
-#else
- .commit_write = afs_linux_commit_write,
- .prepare_write = afs_linux_prepare_write,
-#endif
-};
-#endif
-
-
-/* Separate ops vector for directories. Linux 2.2 tests type of inode
- * by what sort of operation is allowed.....
- */
-
-static 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,
- .revalidate = afs_linux_revalidate,
- .permission = afs_linux_permission,
- .follow_link = afs_linux_dir_follow_link,
-};
-
-/* 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(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
-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;
-
- maybe_lock_kernel();
- AFS_GLOCK();
- code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
- AFS_GUNLOCK();
-
- if (code < 0)
- goto fail;
- p[code] = '\0'; /* null terminate? */
- maybe_unlock_kernel();
-
- SetPageUptodate(page);
- kunmap(page);
- UnlockPage(page);
- return 0;
-
- fail:
- maybe_unlock_kernel();
-
- SetPageError(page);
- kunmap(page);
- UnlockPage(page);
- return code;
-}
-
-static struct address_space_operations afs_symlink_aops = {
- .readpage = afs_symlink_filler
-};
-#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
-
-static struct inode_operations afs_symlink_iops = {
-#if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
- .readlink = page_readlink,
-#if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
- .follow_link = page_follow_link,
-#else
- .follow_link = page_follow_link_light,
- .put_link = page_put_link,
-#endif
-#else /* !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE) */
- .readlink = afs_linux_readlink,
- .follow_link = afs_linux_follow_link,
-#if !defined(AFS_LINUX24_ENV)
- .permission = afs_linux_permission,
- .revalidate = afs_linux_revalidate,
-#endif
-#endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
-#if defined(AFS_LINUX24_ENV)
- .setattr = afs_notify_change,
-#endif
-};
-
-void
-afs_fill_inode(struct inode *ip, struct vattr *vattr)
-{
-
- if (vattr)
- vattr2inode(ip, vattr);
-
-/* Reset ops if symlink or directory. */
- if (S_ISREG(ip->i_mode)) {
- ip->i_op = &afs_file_iops;
-#if defined(AFS_LINUX24_ENV)
- ip->i_fop = &afs_file_fops;
- ip->i_data.a_ops = &afs_file_aops;
-#endif
-
- } else if (S_ISDIR(ip->i_mode)) {
- ip->i_op = &afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
- ip->i_fop = &afs_dir_fops;
-#endif
-
- } else if (S_ISLNK(ip->i_mode)) {
- ip->i_op = &afs_symlink_iops;
-#if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
- ip->i_data.a_ops = &afs_symlink_aops;
- ip->i_mapping = &ip->i_data;
-#endif
- }
-
-}