linux-dynamic-inodes-20050710
authorChas Williams <chas@cmf.nrl.navy.mil>
Mon, 11 Jul 2005 19:45:47 +0000 (19:45 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 11 Jul 2005 19:45:47 +0000 (19:45 +0000)
i slipped a rollback on the linux 2.4 dentry stuff for osi_UFS* in here
at the same time. this patch lets us use kernel inodes instead of our own pool.

19 files changed:
acinclude.m4
src/afs/LINUX/osi_file.c
src/afs/LINUX/osi_machdep.h
src/afs/LINUX/osi_misc.c
src/afs/LINUX/osi_module.c
src/afs/LINUX/osi_prototypes.h
src/afs/LINUX/osi_vfs.hin
src/afs/LINUX/osi_vfsops.c
src/afs/LINUX/osi_vm.c
src/afs/LINUX/osi_vnodeops.c
src/afs/VNOPS/afs_vnop_attrs.c
src/afs/VNOPS/afs_vnop_lookup.c
src/afs/afs.h
src/afs/afs_osi.h
src/afs/afs_prototypes.h
src/afs/afs_vcache.c
src/cf/linux-test2.m4
src/cf/linux-test4.m4
src/venus/kdump.c

index 6d96aab..8755620 100644 (file)
@@ -581,6 +581,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_COMPLETION_H_EXISTS
                 LINUX_DEFINES_FOR_EACH_PROCESS
                 LINUX_DEFINES_PREV_TASK
+                LINUX_FS_STRUCT_SUPER_HAS_ALLOC_INODE
                 LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
                 LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_GFP_MASK
                 LINUX_FS_STRUCT_INODE_HAS_I_ALLOC_SEM
@@ -638,7 +639,8 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                             linux_syscall_method=kallsyms_symbol
                          fi
                          if test "x$linux_syscall_method" = "xnone"; then
-                        AC_MSG_ERROR([no available sys_call_table access method])
+                           AC_MSG_WARN([no available sys_call_table access method -- guessing scan])
+                            linux_syscall_method=scan
                          fi
                    fi
                  fi
@@ -687,6 +689,9 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 if test "x$ac_cv_linux_func_write_inode_returns_int" = "xyes" ; then
                  AC_DEFINE(WRITE_INODE_NOT_VOID, 1, [define if your sops.write_inode returns non-void])
                 fi
+                if test "x$ac_cv_linux_fs_struct_super_has_alloc_inode" = "xyes" ; then
+                 AC_DEFINE(STRUCT_SUPER_HAS_ALLOC_INODE, 1, [define if your struct super_operations has alloc_inode])
+                fi
                 if test "x$ac_cv_linux_fs_struct_address_space_has_page_lock" = "xyes"; then 
                  AC_DEFINE(STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK, 1, [define if your struct address_space has page_lock])
                 fi
index 83c06bf..7711a75 100644 (file)
@@ -31,30 +31,13 @@ extern struct vfsmount *afs_cacheMnt;
 #endif
 extern struct super_block *afs_cacheSBp;
 
-/*#if defined(AFS_LINUX26_ENV) && (defined(CONFIG_EXPORTFS) || defined(CONFIG_EXPORTFS_MODULE))
-#define HAS_UFSOPEN
-extern struct export_operations export_op_default;
-
-#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
-XXX something based on encode_fh / find_exported_dentry 
-This would require us to store an inode -> fh mapping (acquired by
-afs_InitCacheFile or lookupname), but probably solves the resiserfs issue.
-#elif... */
-
-#if defined(AFS_LINUX24_ENV) && !defined(HAS_UFSOPEN)
-#define HAS_UFSOPEN
+#if defined(AFS_LINUX26_ENV) 
 void *
 osi_UFSOpen(afs_int32 ainode)
 {
     register struct osi_file *afile = NULL;
     extern int cacheDiskType;
     struct inode *tip = NULL;
-#ifndef AFS_LINUX26_ENV
-    afs_int32 code = 0;
-    struct list_head *lp = NULL;
-    struct dentry *tdp = NULL;
-#endif
     struct dentry *dp = NULL;
     struct file *filp = NULL;
     AFS_STATCNT(osi_UFSOpen);
@@ -79,33 +62,11 @@ osi_UFSOpen(afs_int32 ainode)
        osi_Panic("Can't get inode %d\n", ainode);
     tip->i_flags |= MS_NOATIME;        /* Disable updating access times. */
 
-#ifdef AFS_LINUX26_ENV
     dp = d_alloc_anon(tip);
-#else
-    spin_lock(&dcache_lock);
-    for (lp = tip->i_dentry.next;  lp != &tip->i_dentry; lp = lp->next) {
-        tdp = list_entry(lp, struct dentry, d_alias);
-        if ( !(tdp->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-             dget_locked(tdp);
-             dp=tdp;
-             break;
-        }
-    }
-    if (tdp && !dp) {
-             dget_locked(tdp);
-             dp=tdp;
-    }
-    tdp = NULL;
-    spin_unlock(&dcache_lock);
-    if (!dp)
-           dp = d_alloc_root(tip);
-    iput(tip);
-#endif
     if (!dp) 
            osi_Panic("Can't get dentry for inode %d\n", ainode);          
 
     filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR);
-
     if (IS_ERR(filp))
        osi_Panic("Can't open inode %d\n", ainode);
     afile->filp = filp;
@@ -116,9 +77,7 @@ osi_UFSOpen(afs_int32 ainode)
     afile->inum = ainode;      /* for hint validity checking */
     return (void *)afile;
 }
-#endif
-
-#if !defined(HAS_UFSOPEN)
+#else
 void *
 osi_UFSOpen(afs_int32 ainode)
 {
@@ -152,9 +111,6 @@ osi_UFSOpen(afs_int32 ainode)
     FILE_INODE(filp) = tip;
     tip->i_flags |= MS_NOATIME;        /* Disable updating access times. */
     filp->f_flags = O_RDWR;
-#if defined(AFS_LINUX26_ENV)
-    filp->f_mapping = tip->i_mapping;
-#endif
 #if defined(AFS_LINUX24_ENV)
     filp->f_mode = FMODE_READ|FMODE_WRITE;
     filp->f_op = fops_get(tip->i_fop);
@@ -194,14 +150,14 @@ afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat)
     return code;
 }
 
-#ifdef AFS_LINUX24_ENV
+#ifdef AFS_LINUX26_ENV
 int
 osi_UFSClose(register struct osi_file *afile)
 {
     AFS_STATCNT(osi_Close);
     if (afile) {
        if (OSIFILE_INODE(afile)) {
-             filp_close(afile->filp, NULL);
+           filp_close(afile->filp, NULL);
        }
     }
 
index 7d13d64..fd28337 100644 (file)
 #undef gop_lookupname
 #define gop_lookupname osi_lookupname
 
-#define osi_vnhold(v, n) do { VN_HOLD(AFSTOV(v)); } while (0)
-
-#if defined(AFS_LINUX24_ENV)
-#define VN_HOLD(V) atomic_inc(&((vnode_t *) V)->i_count)
-#else
-#define VN_HOLD(V) ((vnode_t *) V)->i_count++
-#endif
-
-#if defined(AFS_LINUX24_ENV)
-#define VN_RELE(V) iput((struct inode *) V)
-#else
-#define VN_RELE(V) osi_iput((struct inode *) V)
-#endif
-
-#define osi_AllocSmall afs_osi_Alloc
-#define osi_FreeSmall afs_osi_Free
+#define 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) ((( vnode_t *)V)->v_type & S_IFMT)
+#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 */
 
-/* IsAfsVnode relies on the fast that there is only one vnodeop table for AFS.
- * Use the same type of test as other OS's for compatibility.
- */
 #undef IsAfsVnode
-extern struct vnodeops afs_file_iops, afs_dir_iops, afs_symlink_iops;
-#define IsAfsVnode(v) (((v)->v_op == &afs_file_iops) ? 1 : \
-                       ((v)->v_op == &afs_dir_iops) ? 1 : \
-                       ((v)->v_op == &afs_symlink_iops))
+#define IsAfsVnode(V) ((V)->i_sb == afs_globalVFS)     /* test superblock instead */
 #undef SetAfsVnode
-#define SetAfsVnode(v)
+#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.
@@ -183,7 +166,7 @@ typedef struct uio {
 /* Get/set the inode in the osifile struct. */
 #define FILE_INODE(F) (F)->f_dentry->d_inode
 
-#ifdef AFS_LINUX24_ENV
+#ifdef AFS_LINUX26_ENV
 #define OSIFILE_INODE(a) FILE_INODE((a)->filp)
 #else
 #define OSIFILE_INODE(a) FILE_INODE(&(a)->file)
index 261e428..09b3f22 100644 (file)
@@ -141,7 +141,7 @@ osi_InitCacheInfo(char *aname)
 int
 osi_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
 {
-#ifdef AFS_LINUX24_ENV
+#ifdef AFS_LINUX26_ENV
     struct file *filp = osifile->filp;
 #else
     struct file *filp = &osifile->file;
@@ -324,147 +324,28 @@ afs_osi_SetTime(osi_timeval_t * tvp)
 #endif
 }
 
-/* Free all the pages on any of the vnodes in the vlru. Must be done before
- * freeing all memory.
+/* osi_linux_free_inode_pages
+ *
+ * Free all vnodes remaining in the afs hash.  Must be done before
+ * shutting down afs and freeing all memory.
  */
 void
 osi_linux_free_inode_pages(void)
 {
     int i;
-    struct vcache *tvc;
-    struct inode *ip;
+    struct vcache *tvc, *nvc;
     extern struct vcache *afs_vhashT[VCSIZE];
 
     for (i = 0; i < VCSIZE; i++) {
-       for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-           ip = AFSTOI(tvc);
-#if defined(AFS_LINUX24_ENV)
-           if (ip->i_data.nrpages) {
-#else
-           if (ip->i_nrpages) {
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-               truncate_inode_pages(&ip->i_data, 0);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
-               truncate_inode_pages(ip, 0);
-#else
-               invalidate_inode_pages(ip);
-#endif
-#if defined(AFS_LINUX24_ENV)
-               if (ip->i_data.nrpages) {
-#else
-               if (ip->i_nrpages) {
-#endif
-                   printf("Failed to invalidate all pages on inode 0x%lx\n",
-                          (unsigned long)ip);
-               }
-           }
-       }
-    }
-}
-
-#if !defined(AFS_LINUX24_ENV)
-void
-osi_clear_inode(struct inode *ip)
-{
-    cred_t *credp = crref();
-    struct vcache *vcp = ITOAFS(ip);
-
-    if (ip->i_count > 1)
-       printf("afs_put_inode: ino %ld (0x%lx) has count %ld\n",
-              (long)ip->i_ino, (unsigned long)ip, (long)ip->i_count);
-
-    afs_InactiveVCache(vcp, credp);
-    ObtainWriteLock(&vcp->lock, 504);
-    ip->i_nlink = 0;           /* iput checks this after calling this routine. */
-#ifdef I_CLEAR
-    ip->i_state = I_CLEAR;
-#endif
-    ReleaseWriteLock(&vcp->lock);
-    crfree(credp);
-}
-
-/* iput an inode. Since we still have a separate inode pool, we don't want
- * to call iput on AFS inodes, since they would then end up on Linux's
- * inode_unsed list.
- */
-void
-osi_iput(struct inode *ip)
-{
-    extern struct vfs *afs_globalVFS;
-
-    AFS_GLOCK();
-
-    if (afs_globalVFS && ip->i_sb != afs_globalVFS)
-       osi_Panic("IPUT Not an afs inode\n");
-
-#if defined(AFS_LINUX24_ENV)
-    if (atomic_read(&ip->i_count) == 0)
-#else
-    if (ip->i_count == 0)
-#endif
-       osi_Panic("IPUT Bad refCount %d on inode 0x%x\n",
-#if defined(AFS_LINUX24_ENV)
-                 atomic_read(&ip->i_count),
-#else
-                 ip->i_count,
-#endif
-                               ip);
-
-#if defined(AFS_LINUX24_ENV)
-    if (atomic_dec_and_test(&ip->i_count))
-#else
-    if (!--ip->i_count)
-#endif
-                                          {
-       osi_clear_inode(ip);
-       ip->i_state = 0;
-    }
-    AFS_GUNLOCK();
-}
-#endif
-
-/* check_bad_parent() : Checks if this dentry's vcache is a root vcache
- * that has its mvid (parent dir's fid) pointer set to the wrong directory
- * due to being mounted in multiple points at once. If so, check_bad_parent()
- * calls afs_lookup() to correct the vcache's mvid, as well as the volume's
- * dotdotfid and mtpoint fid members.
- * Parameters:
- *  dp - dentry to be checked.
- * Return Values:
- *  None.
- * Sideeffects:
- *   This dentry's vcache's mvid will be set to the correct parent directory's
- *   fid.
- *   This root vnode's volume will have its dotdotfid and mtpoint fids set
- *    to the correct parent and mountpoint fids.
- */
-
-void
-check_bad_parent(struct dentry *dp)
-{
-    cred_t *credp;
-    struct vcache *vcp = ITOAFS(dp->d_inode), *avc = NULL;
-    struct vcache *pvc = ITOAFS(dp->d_parent->d_inode);
-
-    if (vcp->mvid->Fid.Volume != pvc->fid.Fid.Volume) {        /* bad parent */
-       credp = crref();
-
-
-       /* force a lookup, so vcp->mvid is fixed up */
-       afs_lookup(pvc, dp->d_name.name, &avc, credp);
-       if (!avc || vcp != avc) {       /* bad, very bad.. */
-           afs_Trace4(afs_iclSetp, CM_TRACE_TMP_1S3L, ICL_TYPE_STRING,
-                      "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
-                      ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
-                      ICL_TYPE_POINTER, dp);
+       for (tvc = afs_vhashT[i]; tvc; ) {
+           int slept;
+       
+           nvc = tvc->hnext;
+           if (afs_FlushVCache(tvc, &slept))           /* slept always 0 for linux? */
+               printf("Failed to invalidate all pages on inode 0x%p\n", tvc);
+           tvc = nvc;
        }
-       if (avc)
-           AFS_RELE(avc);
-       crfree(credp);
     }
-    /* if bad parent */
-    return;
 }
 
 struct task_struct *rxk_ListenerTask;
index 3031527..88ac57c 100644 (file)
@@ -686,7 +686,7 @@ int
 init_module(void)
 #endif
 {
-    int e;
+    int err;
     RWLOCK_INIT(&afs_xosi, "afs_xosi");
 
 #if !defined(AFS_LINUX24_ENV)
@@ -704,8 +704,12 @@ init_module(void)
 
     osi_Init();
 
-    e = osi_syscall_init();
-    if (e) return e;
+    err = osi_syscall_init();
+    if (err)
+       return err;
+    err = afs_init_inodecache();
+    if (err)
+       return err;
     register_filesystem(&afs_fs_type);
     osi_sysctl_init();
 #ifdef AFS_LINUX24_ENV
@@ -727,7 +731,7 @@ cleanup_module(void)
     osi_syscall_clean();
     unregister_filesystem(&afs_fs_type);
 
-    osi_linux_free_inode_pages();      /* Invalidate all pages using AFS inodes. */
+    afs_destroy_inodecache();
     osi_linux_free_afs_memory();
 
 #ifdef AFS_LINUX24_ENV
index 4265e00..bf8b88c 100644 (file)
@@ -37,7 +37,6 @@ extern int osi_InitCacheInfo(char *aname);
 extern int osi_rdwr(struct osi_file *osifile, uio_t * uiop, int rw);
 extern void afs_osi_SetTime(osi_timeval_t * tvp);
 extern void osi_linux_free_inode_pages(void);
-extern void check_bad_parent(struct dentry *dp);
 
 /* osi_probe.c */
 extern void *osi_find_syscall_table(int which);
@@ -61,12 +60,11 @@ extern void osi_VM_Truncate(struct vcache *avc, int alen,
                            struct AFS_UCRED *acred);
 
 /* osi_vfsops.c */
-extern void set_inode_cache(struct inode *ip, struct vattr *vp);
-extern void put_inode_on_dummy_list(struct inode *ip);
 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 int afs_linux_writepage_sync(struct inode *ip, struct page *pp,
-                                   unsigned long offset, unsigned int count);
+extern void afs_fill_inode(struct inode *ip, struct vattr *vattr);
 
 #endif /* _OSI_PROTO_H_ */
index c6c52f4..b94a2ca 100644 (file)
@@ -9,39 +9,24 @@
 
 /*
  * Linux interpretations of vnode and vfs structs.
- *
- * The Linux "inode" has been abstracted to the fs independent part to avoid
- * wasting 100+bytes per vnode.
  */
 
 #ifndef OSI_VFS_H_
 #define OSI_VFS_H_
 
-#if !defined(AFS_LINUX26_ENV)
-/* The vnode should match the current implementation of the fs independent
- * part of the Linux inode.
- */
-/* The first cut is to continue to use a separate vnode pool. */
-/* LINUX VNODE INCLUDED BELOW -- DO NOT MODIFY */
-
-typedef struct vnode vnode_t;
-#else
 typedef struct inode vnode_t;
 #define vnode inode
-#endif
 
-/* Map vnode fields to inode fields. */
+/* Map vnode fields to inode fields */
 #define i_number       i_ino
 #define v_count                i_count
 #define v_op           i_op
-#if defined(AFS_LINUX24_ENV)
 #define v_fop           i_fop
-#endif
 #define v_type         i_mode
 #define v_vfsp         i_sb
-#define vfs_vnodecovered s_covered
+#define v_data         u.generic_ip
 
-/* v_type bits map to mode bits: */
+/* v_type bits map to mode bits */
 #define VNON 0
 #define VREG S_IFREG
 #define VDIR S_IFDIR
@@ -58,15 +43,12 @@ enum vcexcl { EXCL, NONEXCL } ;
 #define FWRITE O_WRONLY|O_RDWR|O_APPEND
 #define FTRUNC O_TRUNC
 
-
 #define IO_APPEND O_APPEND
 #define FSYNC O_SYNC
 
-#define VTOI(V)  ((struct inode*)V)
+#define 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
@@ -74,7 +56,6 @@ enum vcexcl { EXCL, NONEXCL } ;
 #define VSUID  S_ISUID
 #define VSGID  S_ISGID
 
-
 #define vfs super_block
 
 typedef struct vattr {
@@ -97,7 +78,4 @@ typedef struct vattr {
 
 #define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
 
-
-#define vnodeops inode_operations
-
 #endif /* OSI_VFS_H_ */
index a0ed85e..f799b79 100644 (file)
@@ -46,7 +46,6 @@ extern struct dentry_operations afs_dentry_operations;
 
 /* Forward declarations */
 static void iattr2vattr(struct vattr *vattrp, struct iattr *iattrp);
-static void update_inode_cache(struct inode *ip, struct vattr *vp);
 static int afs_root(struct super_block *afsp);
 struct super_block *afs_read_super(struct super_block *sb, void *data, int silent);
 int afs_fill_super(struct super_block *sb, void *data, int silent);
@@ -180,23 +179,18 @@ afs_root(struct super_block *afsp)
        if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
            tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
            if (tvp) {
-               extern struct inode_operations afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
-               extern struct file_operations afs_dir_fops;
-#endif
+               struct inode *ip = AFSTOV(tvp);
+               struct vattr vattr;
 
-               /* "/afs" is a directory, reset inode ops accordingly. */
-               AFSTOV(tvp)->v_op = &afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
-               AFSTOV(tvp)->v_fop = &afs_dir_fops;
-#endif
+               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(AFSTOI(tvp));
+               afsp->s_root = d_alloc_root(ip);
 #else
-               afsp->s_root = d_alloc_root(AFSTOI(tvp), NULL);
+               afsp->s_root = d_alloc_root(ip, NULL);
 #endif
                afsp->s_root->d_op = &afs_dentry_operations;
            } else
@@ -220,109 +214,133 @@ int
 afs_notify_change(struct dentry *dp, struct iattr *iattrp)
 {
     struct vattr vattr;
-    int code;
     cred_t *credp = crref();
     struct inode *ip = dp->d_inode;
+    int code;
 
-    AFS_GLOCK();
-#if defined(AFS_LINUX26_ENV)
-    lock_kernel();
-#endif
     VATTR_NULL(&vattr);
     iattr2vattr(&vattr, iattrp);       /* Convert for AFS vnodeops call. */
-    update_inode_cache(ip, &vattr);
-    code = afs_setattr(ITOAFS(ip), &vattr, credp);
-    afs_CopyOutAttrs(ITOAFS(ip), &vattr);
-    /* Note that the inode may still not have all the correct info. But at
-     * least we've got the newest version of what was supposed to be set.
-     */
 
 #if defined(AFS_LINUX26_ENV)
-    unlock_kernel();
+    lock_kernel();
 #endif
+    AFS_GLOCK();
+    code = afs_setattr(VTOAFS(ip), &vattr, credp);
+    if (!code) {
+       afs_getattr(VTOAFS(ip), &vattr, credp);
+       vattr2inode(ip, &vattr);
+    }
     AFS_GUNLOCK();
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     crfree(credp);
     return -code;
 }
 
 
-/* This list is simply used to initialize the i_list member of the
- * linux inode. This stops linux inode syncing code from choking on our
- * inodes.
- */
-static LIST_HEAD(dummy_inode_list);
+#if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
+static kmem_cache_t *afs_inode_cachep;
 
+static struct inode *
+afs_alloc_inode(struct super_block *sb)
+{
+    struct vcache *vcp;
+
+    vcp = (struct vcache *) kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
+    if (!vcp)
+       return NULL;
+
+    return AFSTOV(vcp);
+}
 
-/* This is included for documentation only. */
-/* afs_write_inode
- * Used to flush in core inode to disk. We don't need to do this. Top level
- * write_inode() routine will clear i_dirt. If this routine is in the table,
- * it's expected to do the cleaning and clear i_dirt.
- * 
- * 9/24/99: This is what we thought until we discovered msync() does end up calling
- * this function to sync a single inode to disk. msync() only flushes selective
- * pages to disk. So it needs an inode syncing function to update metadata when it
- * has synced some pages of a file to disk.
- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#ifdef WRITE_INODE_NOT_VOID
-static int
-#else
 static void
-#endif
-afs_write_inode(struct inode *ip, int unused)
-#else
+afs_destroy_inode(struct inode *inode)
+{
+    kmem_cache_free(afs_inode_cachep, inode);
+}
+
 static void
-afs_write_inode(struct inode *ip)
-#endif
+init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
 {
-    list_del(&ip->i_list);
-    /* and put it back on our dummy list. */
-    put_inode_on_dummy_list(ip);
+    struct vcache *vcp = (struct vcache *) foo;
 
-    /* for now we don't actually update the metadata during msync. This
-     * is just to keep linux happy.  */
-#ifdef WRITE_INODE_NOT_VOID
-    return 0;
-#endif
+    if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+       SLAB_CTOR_CONSTRUCTOR)
+       inode_init_once(AFSTOV(vcp));
 }
 
-static void
-afs_destroy_inode(struct inode *ip)
+int
+afs_init_inodecache(void)
 {
-    cred_t *credp = crref();
+#ifndef SLAB_RECLAIM_ACCOUNT
+#define SLAB_RECLAIM_ACCOUNT 0
+#endif
 
-    /* locked by clear_inode() */
-    put_inode_on_dummy_list(ip);
-    ip->i_state = 0;
-    afs_InactiveVCache(ITOAFS(ip), credp); /* afs_FlushVCache()? */
-    AFS_GUNLOCK();
-    crfree(credp);
+    afs_inode_cachep = kmem_cache_create("afs_inode_cache",
+                                        sizeof(struct vcache),
+                                        0, SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT,
+                                        init_once, NULL);
+    if (afs_inode_cachep == NULL)
+       return -ENOMEM;
+    return 0;
 }
 
+void
+afs_destroy_inodecache(void)
+{
+    if (kmem_cache_destroy(afs_inode_cachep))
+       printk(KERN_INFO "afs_inode_cache: not all structures were freed\n");
+}
+#else
+int
+afs_init_inodecache(void)
+{
+    return 0;
+}
 
-/* afs_put_inode
- * called from iput when count goes to zero. Linux version of inactive.
- * For Linux 2.2, this funcionality has moved to the delete inode super op.
- * If we use the common inode pool, we'll need to set i_nlink to 0 here.
- * That will trigger the call to delete routine.
- */
+void
+afs_destroy_inodecache(void)
+{
+    return;
+}
+#endif
 
-#if defined(AFS_LINUX24_ENV)
 static void
 afs_clear_inode(struct inode *ip)
 {
-    AFS_GLOCK();       /* unlocked by destroy_inode() */
+    struct vcache *vcp = VTOAFS(ip);
+
+    if (vcp->vlruq.prev || vcp->vlruq.next)
+       osi_Panic("inode freed while on LRU");
+    if (vcp->hnext || vcp->vhnext)
+       osi_Panic("inode freed while still hashed");
+
+#if !defined(STRUCT_SUPER_HAS_ALLOC_INODE)
+    afs_osi_Free(ip->u.generic_ip, sizeof(struct vcache));
+#endif
 }
-#else
+
+/* afs_put_inode
+ * Linux version of inactive.  When refcount == 2, we are about to
+ * decrement to 1 and the only reference remaining should be for
+ * the VLRU
+ */
+
 static void
-afs_delete_inode(struct inode *ip)
+afs_put_inode(struct inode *ip)
 {
-    AFS_GLOCK();               /* after spin_unlock(inode_lock) */
-    osi_clear_inode(ip);
+    cred_t *credp = crref();
+    struct vcache *vcp = VTOAFS(ip);
+
+    AFS_GLOCK();
+    ObtainReadLock(&vcp->lock);
+    if (VREFCOUNT(vcp) == 2)
+       afs_InactiveVCache(vcp, credp);
+    ReleaseReadLock(&vcp->lock);
     AFS_GUNLOCK();
+    crfree(credp);
 }
-#endif
 
 /* afs_put_super
  * Called from unmount to release super_block. */
@@ -343,6 +361,8 @@ afs_put_super(struct super_block *sbp)
 
     afs_globalVFS = 0;
     afs_globalVp = 0;
+
+    osi_linux_free_inode_pages();      /* invalidate and release remaining AFS inodes. */
     afs_shutdown();
 #if defined(AFS_LINUX24_ENV)
     mntput(afs_cacheMnt);
@@ -412,13 +432,12 @@ afs_umount_begin(struct super_block *sbp)
 }
 
 struct super_operations afs_sops = {
-#if defined(AFS_LINUX24_ENV)
+#if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
+  .alloc_inode =       afs_alloc_inode,
   .destroy_inode =     afs_destroy_inode,
-  .clear_inode =        afs_clear_inode,
-#else
-  .delete_inode =       afs_delete_inode,
 #endif
-  .write_inode =       afs_write_inode,
+  .clear_inode =       afs_clear_inode,
+  .put_inode =         afs_put_inode,
   .put_super =         afs_put_super,
   .statfs =            afs_statfs,
   .umount_begin =      afs_umount_begin
@@ -470,41 +489,6 @@ iattr2vattr(struct vattr *vattrp, struct iattr *iattrp)
     }
 }
 
-/* update_inode_cache
- * Update inode with info from vattr struct. Use va_mask to determine what
- * to update.
- */
-static void
-update_inode_cache(struct inode *ip, struct vattr *vp)
-{
-    if (vp->va_mask & ATTR_MODE)
-       ip->i_mode = vp->va_mode;
-    if (vp->va_mask & ATTR_UID)
-       ip->i_uid = vp->va_uid;
-    if (vp->va_mask & ATTR_GID)
-       ip->i_gid = vp->va_gid;
-    if (vp->va_mask & ATTR_SIZE)
-       ip->i_size = vp->va_size;
-    if (vp->va_mask & ATTR_ATIME)
-#if defined(AFS_LINUX26_ENV)
-       ip->i_atime.tv_sec = vp->va_atime.tv_sec;
-#else
-       ip->i_atime = vp->va_atime.tv_sec;
-#endif
-    if (vp->va_mask & ATTR_MTIME)
-#if defined(AFS_LINUX26_ENV)
-       ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
-#else
-       ip->i_mtime = vp->va_mtime.tv_sec;
-#endif
-    if (vp->va_mask & ATTR_CTIME)
-#if defined(AFS_LINUX26_ENV)
-       ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
-#else
-       ip->i_ctime = vp->va_ctime.tv_sec;
-#endif
-}
-
 /* vattr2inode
  * Rewrite the inode cache from the attr. Assumes all vattr fields are valid.
  */
@@ -530,35 +514,3 @@ vattr2inode(struct inode *ip, struct vattr *vp)
     ip->i_ctime = vp->va_ctime.tv_sec;
 #endif
 }
-
-/* Put this afs inode on our own dummy list. Linux expects to see inodes
- * nicely strung up in lists. Linux inode syncing code chokes on our inodes if
- * they're not on any lists.
- */
-void
-put_inode_on_dummy_list(struct inode *ip)
-{
-    /* Initialize list. See explanation above. */
-    list_add(&ip->i_list, &dummy_inode_list);
-}
-
-/* And yet another routine to update the inode cache - called from ProcessFS */
-void
-vcache2inode(struct vcache *avc)
-{
-    struct vattr vattr;
-
-    VATTR_NULL(&vattr);
-    afs_CopyOutAttrs(avc, &vattr);     /* calls vattr2inode */
-}
-
-/* Yet another one for fakestat'ed mountpoints */
-void
-vcache2fakeinode(struct vcache *rootvp, struct vcache *mpvp)
-{
-    struct vattr vattr;
-
-    VATTR_NULL(&vattr);
-    afs_CopyOutAttrs(rootvp, &vattr);
-    vattr2inode(AFSTOI(mpvp), &vattr);
-}
index 552697f..2776aff 100644 (file)
@@ -43,9 +43,9 @@ RCSID
 int
 osi_VM_FlushVCache(struct vcache *avc, int *slept)
 {
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
-    if (VREFCOUNT(avc) != 0)
+    if (VREFCOUNT(avc) > 1)
        return EBUSY;
 
     if (avc->opens != 0)
@@ -73,7 +73,7 @@ osi_VM_FlushVCache(struct vcache *avc, int *slept)
 void
 osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
 {
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
 #if defined(AFS_LINUX26_ENV)
     invalidate_inode_pages(ip->i_mapping);
@@ -100,7 +100,7 @@ osi_VM_FSyncInval(struct vcache *avc)
 void
 osi_VM_StoreAllSegments(struct vcache *avc)
 {
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5)
     /* filemap_fdatasync() only exported in 2.4.5 and above */
@@ -125,15 +125,15 @@ void
 osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
     truncate_inode_pages(&ip->i_data, 0);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
     truncate_inode_pages(ip, 0);
 #else
-    invalidate_inode_pages(AFSTOI(avc));
+    invalidate_inode_pages(AFSTOV(avc));
 #endif
 }
 
@@ -147,14 +147,14 @@ void
 osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
     truncate_inode_pages(&ip->i_data, alen);
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)
-    struct inode *ip = AFSTOI(avc);
+    struct inode *ip = AFSTOV(avc);
 
     truncate_inode_pages(ip, alen);
 #else
-    invalidate_inode_pages(AFSTOI(avc));
+    invalidate_inode_pages(AFSTOV(avc));
 #endif
 }
index 33eeefa..4b6889b 100644 (file)
@@ -50,22 +50,13 @@ RCSID
 #endif
 
 extern struct vcache *afs_globalVp;
-extern afs_rwlock_t afs_xvcache;
-
-#if defined(AFS_LINUX24_ENV)
-extern struct inode_operations afs_file_iops;
-extern struct address_space_operations afs_file_aops;
-struct address_space_operations afs_symlink_aops;
-#endif
-extern struct inode_operations afs_dir_iops;
-extern struct inode_operations afs_symlink_iops;
 
 
 static ssize_t
 afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
 {
     ssize_t code;
-    struct vcache *vcp = ITOAFS(fp->f_dentry->d_inode);
+    struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
     cred_t *credp = crref();
     struct vrequest treq;
 
@@ -147,7 +138,7 @@ afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
 {
     ssize_t code = 0;
     int code2 = 0;
-    struct vcache *vcp = ITOAFS(fp->f_dentry->d_inode);
+    struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
     struct vrequest treq;
     cred_t *credp = crref();
     afs_offs_t toffs;
@@ -263,7 +254,7 @@ static int
 afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
 {
     extern struct DirEntry *afs_dir_GetBlob();
-    struct vcache *avc = ITOAFS(FILE_INODE(fp));
+    struct vcache *avc = VTOAFS(FILE_INODE(fp));
     struct vrequest treq;
     register struct dcache *tdc;
     int code;
@@ -443,7 +434,7 @@ static int afs_private_mmap_ops_inited = 0;
 static struct vm_operations_struct afs_shared_mmap_ops;
 static int afs_shared_mmap_ops_inited = 0;
 
-void
+static void
 afs_linux_vma_close(struct vm_area_struct *vmap)
 {
     struct vcache *vcp;
@@ -453,7 +444,7 @@ afs_linux_vma_close(struct vm_area_struct *vmap)
     if (!vmap->vm_file)
        return;
 
-    vcp = ITOAFS(FILE_INODE(vmap->vm_file));
+    vcp = VTOAFS(FILE_INODE(vmap->vm_file));
     if (!vcp)
        return;
 
@@ -502,7 +493,7 @@ afs_linux_vma_close(struct vm_area_struct *vmap)
 static int
 afs_linux_mmap(struct file *fp, struct vm_area_struct *vmap)
 {
-    struct vcache *vcp = ITOAFS(FILE_INODE(fp));
+    struct vcache *vcp = VTOAFS(FILE_INODE(fp));
     cred_t *credp = crref();
     struct vrequest treq;
     int code;
@@ -576,17 +567,18 @@ afs_linux_mmap(struct file *fp, struct vm_area_struct *vmap)
     return code;
 }
 
-int
+static int
 afs_linux_open(struct inode *ip, struct file *fp)
 {
-    int code;
+    struct vcache *vcp = VTOAFS(ip);
     cred_t *credp = crref();
+    int code;
 
 #ifdef AFS_LINUX24_ENV
     lock_kernel();
 #endif
     AFS_GLOCK();
-    code = afs_open((struct vcache **)&ip, fp->f_flags, credp);
+    code = afs_open(&vcp, fp->f_flags, credp);
     AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
     unlock_kernel();
@@ -599,7 +591,7 @@ afs_linux_open(struct inode *ip, struct file *fp)
 static int
 afs_linux_release(struct inode *ip, struct file *fp)
 {
-    struct vcache *vcp = ITOAFS(ip);
+    struct vcache *vcp = VTOAFS(ip);
     cred_t *credp = crref();
     int code = 0;
 
@@ -617,11 +609,10 @@ afs_linux_release(struct inode *ip, struct file *fp)
     return -code;
 }
 
-#if defined(AFS_LINUX24_ENV)
 static int
+#if defined(AFS_LINUX24_ENV)
 afs_linux_fsync(struct file *fp, struct dentry *dp, int datasync)
 #else
-static int
 afs_linux_fsync(struct file *fp, struct dentry *dp)
 #endif
 {
@@ -633,7 +624,7 @@ afs_linux_fsync(struct file *fp, struct dentry *dp)
     lock_kernel();
 #endif
     AFS_GLOCK();
-    code = afs_fsync(ITOAFS(ip), credp);
+    code = afs_fsync(VTOAFS(ip), credp);
     AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
     unlock_kernel();
@@ -648,7 +639,7 @@ static int
 afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 {
     int code = 0;
-    struct vcache *vcp = ITOAFS(FILE_INODE(fp));
+    struct vcache *vcp = VTOAFS(FILE_INODE(fp));
     cred_t *credp = crref();
     struct AFS_FLOCK flock;
     /* Convert to a lock format afs_lockctl understands. */
@@ -689,11 +680,11 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
  * code for the sys_close() here, not afs_linux_release(), so call
  * afs_StoreAllSegments() with AFS_LASTSTORE
  */
-int
+static int
 afs_linux_flush(struct file *fp)
 {
     struct vrequest treq;
-    struct vcache *vcp = ITOAFS(FILE_INODE(fp));
+    struct vcache *vcp = VTOAFS(FILE_INODE(fp));
     cred_t *credp = crref();
     int code;
 
@@ -778,40 +769,71 @@ struct file_operations afs_file_fops = {
  * 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->fid.Fid.Volume) {        /* bad parent */
+printk("check_bad_parent(%s): bad parent vcp->mvid->Fid.Volume != pvc->fid.Fid.Volume\n", dp->d_name.name);
+       credp = crref();
+
+       /* force a lookup, so vcp->mvid is fixed up */
+       afs_lookup(pvc, dp->d_name.name, &avc, credp);
+       if (!avc || vcp != avc) {       /* bad, very bad.. */
+           afs_Trace4(afs_iclSetp, CM_TRACE_TMP_1S3L, ICL_TYPE_STRING,
+                      "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
+                      ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
+                      ICL_TYPE_POINTER, dp);
+       }
+       if (avc)
+           AFS_RELE(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)
 {
-    int code;
+    struct vattr vattr;
+    struct vcache *vcp = VTOAFS(dp->d_inode);
     cred_t *credp;
-    struct vrequest treq;
-    struct vcache *vcp = ITOAFS(dp->d_inode);
-    struct vcache *rootvp = NULL;
+    int code;
 
 #ifdef AFS_LINUX24_ENV
     lock_kernel();
 #endif
     AFS_GLOCK();
 
-    if (afs_fakestat_enable && vcp->mvstat == 1 && vcp->mvid
-       && (vcp->states & CMValid) && (vcp->states & CStatd)) {
-       ObtainSharedLock(&afs_xvcache, 680);
-       rootvp = afs_FindVCache(vcp->mvid, 0, 0);
-       ReleaseSharedLock(&afs_xvcache);
-    }
-
     /* Make this a fast path (no crref), since it's called so often. */
     if (vcp->states & CStatd) {
+
        if (*dp->d_name.name != '/' && vcp->mvstat == 2)        /* root vnode */
            check_bad_parent(dp);       /* check and correct mvid */
-       if (rootvp)
-           vcache2fakeinode(rootvp, vcp);
-       else
-           vcache2inode(vcp);
-       if (rootvp)
-           afs_PutVCache(rootvp);
+
        AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
        unlock_kernel();
@@ -820,9 +842,9 @@ afs_linux_revalidate(struct dentry *dp)
     }
 
     credp = crref();
-    code = afs_InitReq(&treq, credp);
+    code = afs_getattr(vcp, &vattr, credp);
     if (!code)
-       code = afs_VerifyVCache(vcp, &treq);
+        vattr2inode(AFSTOV(vcp), &vattr);
 
     AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
@@ -838,8 +860,9 @@ static int
 afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
         int err = afs_linux_revalidate(dentry);
-        if (!err)
+        if (!err) {
                 generic_fillattr(dentry->d_inode, stat);
+}
         return err;
 }
 #endif
@@ -851,20 +874,18 @@ afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *sta
  * 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
-static int
 afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
 #else
-static int
 afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 #endif
 #else
-static int
 afs_linux_dentry_revalidate(struct dentry *dp)
 #endif
 {
-    struct vrequest treq;
+    struct vattr vattr;
     cred_t *credp = NULL;
     struct vcache *vcp, *pvcp, *tvc = NULL;
     int valid;
@@ -874,16 +895,16 @@ afs_linux_dentry_revalidate(struct dentry *dp)
 #endif
     AFS_GLOCK();
 
-    vcp = ITOAFS(dp->d_inode);
-    pvcp = ITOAFS(dp->d_parent->d_inode);              /* dget_parent()? */
+    if (dp->d_inode) {
 
-    if (vcp) {
+       vcp = VTOAFS(dp->d_inode);
+       pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
 
-       /* If it's the AFS root no chance it needs revalidating */
        if (vcp == afs_globalVp)
            goto good_dentry;
 
-       /* check_bad_parent()? */
+       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
@@ -902,27 +923,38 @@ afs_linux_dentry_revalidate(struct dentry *dp)
         * is longer valid, we need to do a full lookup.  VerifyVCache
         * isn't enough since the vnode may have been renamed.
         */
+
        if (hgetlo(pvcp->m.DataVersion) > dp->d_time || !(vcp->states & CStatd)) {
 
            credp = crref();
-           if (afs_InitReq(&treq, credp))
-               goto bad_dentry;
            afs_lookup(pvcp, dp->d_name.name, &tvc, credp);
            if (!tvc || tvc != vcp)
                goto bad_dentry;
-           if (afs_VerifyVCache(vcp, &treq))   /* update inode attributes */
+
+           if (afs_getattr(vcp, &vattr, credp))
                goto bad_dentry;
 
+           vattr2inode(AFSTOV(vcp), &vattr);
            dp->d_time = hgetlo(pvcp->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->m.DataVersion) > dp->d_time)
            goto bad_dentry;
+#endif
 
        /* No change in parent's DataVersion so this negative
-        * lookup is still valid.
+        * 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:
@@ -950,19 +982,23 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     goto done;
 }
 
-#if !defined(AFS_LINUX24_ENV)
-/* afs_dentry_iput */
 static void
 afs_dentry_iput(struct dentry *dp, struct inode *ip)
 {
-    osi_iput(ip);
+    struct vcache *vcp = VTOAFS(ip);
+
+    AFS_GLOCK();
+    if (vcp->states & CUnlinked)
+       (void) afs_remunlink(vcp, 1);           /* perhaps afs_InactiveVCache() instead */
+    AFS_GUNLOCK();
+
+    iput(ip);
 }
-#endif
 
 static int
 afs_dentry_delete(struct dentry *dp)
 {
-    if (dp->d_inode && (ITOAFS(dp->d_inode)->states & CUnlinked))
+    if (dp->d_inode && (VTOAFS(dp->d_inode)->states & CUnlinked))
        return 1;               /* bad inode? */
 
     return 0;
@@ -971,9 +1007,7 @@ afs_dentry_delete(struct dentry *dp)
 struct dentry_operations afs_dentry_operations = {
   .d_revalidate =      afs_linux_dentry_revalidate,
   .d_delete =          afs_dentry_delete,
-#if !defined(AFS_LINUX24_ENV)
   .d_iput =            afs_dentry_iput,
-#endif
 };
 
 /**********************************************************************
@@ -988,62 +1022,42 @@ struct dentry_operations afs_dentry_operations = {
  *
  * name is in kernel space at this point.
  */
+static int
 #ifdef IOP_CREATE_TAKES_NAMEIDATA
-int
 afs_linux_create(struct inode *dip, struct dentry *dp, int mode,
                 struct nameidata *nd)
 #else
-int
 afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
 #endif
 {
-    int code;
-    cred_t *credp = crref();
     struct vattr vattr;
+    cred_t *credp = crref();
     const char *name = dp->d_name.name;
-    struct inode *ip;
+    struct vcache *vcp;
+    int code;
 
     VATTR_NULL(&vattr);
     vattr.va_mode = mode;
+    vattr.va_type = mode & S_IFMT;
 
 #if defined(AFS_LINUX26_ENV)
     lock_kernel();
 #endif
     AFS_GLOCK();
-    code =
-       afs_create(ITOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
-                  (struct vcache **)&ip, credp);
+    code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
+                     &vcp, credp);
 
     if (!code) {
-       vattr2inode(ip, &vattr);
-       /* Reset ops if symlink or directory. */
-#if defined(AFS_LINUX24_ENV)
-       if (S_ISREG(ip->i_mode)) {
-           ip->i_op = &afs_file_iops;
-           ip->i_fop = &afs_file_fops;
-           ip->i_data.a_ops = &afs_file_aops;
-       } else if (S_ISDIR(ip->i_mode)) {
-           ip->i_op = &afs_dir_iops;
-           ip->i_fop = &afs_dir_fops;
-       } else if (S_ISLNK(ip->i_mode)) {
-           ip->i_op = &afs_symlink_iops;
-           ip->i_data.a_ops = &afs_symlink_aops;
-           ip->i_mapping = &ip->i_data;
-       } else
-           printk("afs_linux_create: FIXME\n");
-#else
-       if (S_ISDIR(ip->i_mode))
-           ip->i_op = &afs_dir_iops;
-       else if (S_ISLNK(ip->i_mode))
-           ip->i_op = &afs_symlink_iops;
-#endif
+       struct inode *ip = AFSTOV(vcp);
 
+       afs_getattr(vcp, &vattr, credp);
+       afs_fill_inode(ip, &vattr);
        dp->d_op = &afs_dentry_operations;
-       dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
+       dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion);
        d_instantiate(dp, ip);
     }
-
     AFS_GUNLOCK();
+
 #if defined(AFS_LINUX26_ENV)
     unlock_kernel();
 #endif
@@ -1053,77 +1067,52 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
 
 /* afs_linux_lookup */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
+static struct dentry *
 #ifdef IOP_LOOKUP_TAKES_NAMEIDATA
-struct dentry *
 afs_linux_lookup(struct inode *dip, struct dentry *dp,
                 struct nameidata *nd)
 #else
-struct dentry *
 afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
 #else
-int
+static int
 afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
 {
-    int code = 0;
+    struct vattr vattr;
     cred_t *credp = crref();
     struct vcache *vcp = NULL;
     const char *comp = dp->d_name.name;
-#if 1
-    struct dentry *res = 0;
-#endif
+    struct dentry *res = NULL;
+    struct inode *ip = NULL;
+    int code;
 
 #if defined(AFS_LINUX26_ENV)
     lock_kernel();
 #endif
     AFS_GLOCK();
-    code = afs_lookup(ITOAFS(dip), comp, &vcp, credp);
-    AFS_GUNLOCK();
+    code = afs_lookup(VTOAFS(dip), comp, &vcp, credp);
     
     if (vcp) {
-       struct inode *ip = AFSTOI(vcp);
-       /* Reset ops if symlink or directory. */
+       ip = AFSTOV(vcp);
+
+       afs_getattr(vcp, &vattr, credp);
+       afs_fill_inode(ip, &vattr);
+    }
+    dp->d_op = &afs_dentry_operations;
+    dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion);
+    AFS_GUNLOCK();
 #if defined(AFS_LINUX24_ENV)
-       if (S_ISREG(ip->i_mode)) {
-           ip->i_op = &afs_file_iops;
-           ip->i_fop = &afs_file_fops;
-           ip->i_data.a_ops = &afs_file_aops;
-       } else if (S_ISDIR(ip->i_mode)) {
-           ip->i_op = &afs_dir_iops;
-           ip->i_fop = &afs_dir_fops;
+    if (ip && S_ISDIR(ip->i_mode)) {
             d_prune_aliases(ip);
             res = d_find_alias(ip);
-       } else if (S_ISLNK(ip->i_mode)) {
-           ip->i_op = &afs_symlink_iops;
-           ip->i_data.a_ops = &afs_symlink_aops;
-           ip->i_mapping = &ip->i_data;
-       } else
-           printk
-               ("afs_linux_lookup: ip->i_mode 0x%x  dp->d_name.name %s  code %d\n",
-                ip->i_mode, dp->d_name.name, code);
-#ifdef STRUCT_INODE_HAS_I_SECURITY
-       if (ip->i_security == NULL) {
-           if (security_inode_alloc(ip))
-               panic("afs_linux_lookup: Cannot allocate inode security");
-       }
-#endif
-#else
-       if (S_ISDIR(ip->i_mode))
-           ip->i_op = &afs_dir_iops;
-       else if (S_ISLNK(ip->i_mode))
-           ip->i_op = &afs_symlink_iops;
-#endif
     }
-    dp->d_op = &afs_dentry_operations;
-    dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
-#if defined(AFS_LINUX24_ENV)
     if (res) {
        if (d_unhashed(res))
            d_rehash(res);
     } else
 #endif
-    d_add(dp, AFSTOI(vcp));
+    d_add(dp, ip);
 
 #if defined(AFS_LINUX26_ENV)
     unlock_kernel();
@@ -1149,7 +1138,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
 }
 
-int
+static int
 afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
 {
     int code;
@@ -1163,20 +1152,20 @@ afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
     d_drop(newdp);
 
     AFS_GLOCK();
-    code = afs_link(ITOAFS(oldip), ITOAFS(dip), name, credp);
+    code = afs_link(VTOAFS(oldip), VTOAFS(dip), name, credp);
 
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
 }
 
-int
+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 = ITOAFS(dp->d_inode);
+    struct vcache *tvc = VTOAFS(dp->d_inode);
 
 #if defined(AFS_LINUX26_ENV)
     lock_kernel();
@@ -1205,9 +1194,9 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
        } while (__dp->d_inode != NULL);
 
        AFS_GLOCK();
-       code = afs_rename(ITOAFS(dip), dp->d_name.name, ITOAFS(dip), __dp->d_name.name, credp);
+       code = afs_rename(VTOAFS(dip), dp->d_name.name, VTOAFS(dip), __dp->d_name.name, credp);
        if (!code) {
-            tvc->mvid = __name;
+            tvc->mvid = (void *) __name;
             crhold(credp);
             if (tvc->uncred) {
                 crfree(tvc->uncred);
@@ -1218,7 +1207,7 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
        AFS_GUNLOCK();
 
        if (!code) {
-           __dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
+           __dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion);
            d_move(dp, __dp);
        }
        dput(__dp);
@@ -1227,7 +1216,7 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
     }
 
     AFS_GLOCK();
-    code = afs_remove(ITOAFS(dip), name, credp);
+    code = afs_remove(VTOAFS(dip), name, credp);
     AFS_GUNLOCK();
     if (!code)
        d_drop(dp);
@@ -1240,7 +1229,7 @@ out:
 }
 
 
-int
+static int
 afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
 {
     int code;
@@ -1253,15 +1242,15 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
      */
     d_drop(dp);
 
-    AFS_GLOCK();
     VATTR_NULL(&vattr);
-    code = afs_symlink(ITOAFS(dip), name, &vattr, target, credp);
+    AFS_GLOCK();
+    code = afs_symlink(VTOAFS(dip), name, &vattr, target, credp);
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
 }
 
-int
+static int
 afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
 {
     int code;
@@ -1273,22 +1262,23 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
 #if defined(AFS_LINUX26_ENV)
     lock_kernel();
 #endif
-    AFS_GLOCK();
     VATTR_NULL(&vattr);
     vattr.va_mask = ATTR_MODE;
     vattr.va_mode = mode;
-    code = afs_mkdir(ITOAFS(dip), name, &vattr, &tvcp, credp);
-    AFS_GUNLOCK();
+    AFS_GLOCK();
+    code = afs_mkdir(VTOAFS(dip), name, &vattr, &tvcp, credp);
 
     if (tvcp) {
-       tvcp->v.v_op = &afs_dir_iops;
-#if defined(AFS_LINUX24_ENV)
-       tvcp->v.v_fop = &afs_dir_fops;
-#endif
+       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(ITOAFS(dip)->m.DataVersion);
-       d_instantiate(dp, AFSTOI(tvcp));
+       dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion);
+       d_instantiate(dp, ip);
     }
+    AFS_GUNLOCK();
 
 #if defined(AFS_LINUX26_ENV)
     unlock_kernel();
@@ -1297,7 +1287,7 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
     return -code;
 }
 
-int
+static int
 afs_linux_rmdir(struct inode *dip, struct dentry *dp)
 {
     int code;
@@ -1308,7 +1298,7 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
     lock_kernel();
 #endif
     AFS_GLOCK();
-    code = afs_rmdir(ITOAFS(dip), name, credp);
+    code = afs_rmdir(VTOAFS(dip), name, credp);
     AFS_GUNLOCK();
 
     /* Linux likes to see ENOTEMPTY returned from an rmdir() syscall
@@ -1331,8 +1321,7 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
 }
 
 
-
-int
+static int
 afs_linux_rename(struct inode *oldip, struct dentry *olddp,
                 struct inode *newip, struct dentry *newdp)
 {
@@ -1369,7 +1358,7 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp,
 #endif
 
     AFS_GLOCK();
-    code = afs_rename(ITOAFS(oldip), oldname, ITOAFS(newip), newname, credp);
+    code = afs_rename(VTOAFS(oldip), oldname, VTOAFS(newip), newname, credp);
     AFS_GUNLOCK();
 
     if (rehash)
@@ -1397,7 +1386,7 @@ afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
     struct iovec iov;
 
     setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
-    code = afs_readlink(ITOAFS(ip), &tuio, credp);
+    code = afs_readlink(VTOAFS(ip), &tuio, credp);
     crfree(credp);
 
     if (!code)
@@ -1410,7 +1399,7 @@ afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
 /* afs_linux_readlink 
  * Fill target (which is in user space) with contents of symlink.
  */
-int
+static int
 afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
 {
     int code;
@@ -1426,7 +1415,7 @@ afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
 /* afs_linux_follow_link
  * a file system dependent link following routine.
  */
-struct dentry *
+static struct dentry *
 afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
                      unsigned int follow)
 {
@@ -1464,7 +1453,7 @@ afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
 /* afs_linux_readpage
  * all reads come through here. A strategy-like read call.
  */
-int
+static int
 afs_linux_readpage(struct file *fp, struct page *pp)
 {
     int code;
@@ -1480,7 +1469,7 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     struct iovec iovec;
     struct inode *ip = FILE_INODE(fp);
     int cnt = page_count(pp);
-    struct vcache *avc = ITOAFS(ip);
+    struct vcache *avc = VTOAFS(ip);
 
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
@@ -1551,89 +1540,13 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     return -code;
 }
 
-#if defined(AFS_LINUX24_ENV)
-#ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
-int
-afs_linux_writepage(struct page *pp, struct writeback_control *wbc)
-#else
-int
-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 defined(AFS_LINUX26_ENV)
-    if (PageReclaim(pp)) {
-       return WRITEPAGE_ACTIVATE;
-    }
-#else
-    if (PageLaunder(pp)) {
-       return(fail_writepage(pp));
-    }
-#endif
-
-    inode = (struct inode *)mapping->host;
-    end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-
-    /* easy case */
-    if (pp->index < end_index)
-       goto do_it;
-    /* things got complicated... */
-    offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
-    /* OK, are we completely out? */
-    if (pp->index >= end_index + 1 || !offset)
-       return -EIO;
-  do_it:
-    status = afs_linux_writepage_sync(inode, pp, 0, offset);
-    SetPageUptodate(pp);
-    UnlockPage(pp);
-    if (status == offset)
-       return 0;
-    else
-       return status;
-}
-#endif
-
-/* afs_linux_permission
- * Check access rights - returns error if can't check or permission denied.
- */
-#ifdef IOP_PERMISSION_TAKES_NAMEIDATA
-int
-afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
-#else
-int
-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(ITOAFS(ip), tmp, credp);
-
-    AFS_GUNLOCK();
-    crfree(credp);
-    return -code;
-}
-
 
 #if defined(AFS_LINUX24_ENV)
-int
+static int
 afs_linux_writepage_sync(struct inode *ip, struct page *pp,
                         unsigned long offset, unsigned int count)
 {
-    struct vcache *vcp = ITOAFS(ip);
+    struct vcache *vcp = VTOAFS(ip);
     char *buffer;
     afs_offs_t base;
     int code = 0;
@@ -1656,7 +1569,8 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
 
     code = afs_write(vcp, &tuio, f_flags, credp, 0);
 
-    vcache2inode(vcp);
+    ip->i_size = vcp->m.Length;
+    ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1;
 
     if (!code
        && afs_stats_cmperf.cacheCurrDirtyChunks >
@@ -1682,17 +1596,61 @@ afs_linux_writepage_sync(struct inode *ip, struct page *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 defined(AFS_LINUX26_ENV)
+    if (PageReclaim(pp)) {
+       return WRITEPAGE_ACTIVATE;
+    }
+#else
+    if (PageLaunder(pp)) {
+       return(fail_writepage(pp));
+    }
+#endif
+
+    inode = (struct inode *)mapping->host;
+    end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+
+    /* easy case */
+    if (pp->index < end_index)
+       goto do_it;
+    /* things got complicated... */
+    offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+    /* OK, are we completely out? */
+    if (pp->index >= end_index + 1 || !offset)
+       return -EIO;
+  do_it:
+    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.
  */
-int
+static int
 afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
                     unsigned int count, int sync)
 {
-    struct vcache *vcp = ITOAFS(FILE_INODE(fp));
+    struct vcache *vcp = VTOAFS(FILE_INODE(fp));
     u8 *page_addr = (u8 *) afs_linux_page_address(pp);
     int code = 0;
     cred_t *credp;
@@ -1712,7 +1670,8 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
 
     code = afs_write(vcp, &tuio, fp->f_flags, credp, 0);
 
-    vcache2inode(vcp);
+    ip->i_size = vcp->m.Length;
+    ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1;
 
     code = code ? -code : count - tuio.uio_resid;
     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
@@ -1727,6 +1686,34 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
 }
 #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 -code;
+}
+
 #if defined(AFS_LINUX24_ENV)
 static int
 afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
@@ -1758,7 +1745,7 @@ afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
 extern int afs_notify_change(struct dentry *dp, struct iattr *iattrp);
 #endif
 
-struct inode_operations afs_file_iops = {
+static struct inode_operations afs_file_iops = {
 #if defined(AFS_LINUX26_ENV)
   .permission =                afs_linux_permission,
   .getattr =           afs_linux_getattr,
@@ -1776,7 +1763,7 @@ struct inode_operations afs_file_iops = {
 };
 
 #if defined(AFS_LINUX24_ENV)
-struct address_space_operations afs_file_aops = {
+static struct address_space_operations afs_file_aops = {
   .readpage =          afs_linux_readpage,
   .writepage =         afs_linux_writepage,
   .commit_write =      afs_linux_commit_write,
@@ -1789,7 +1776,7 @@ struct address_space_operations afs_file_aops = {
  * by what sort of operation is allowed.....
  */
 
-struct inode_operations afs_dir_iops = {
+static struct inode_operations afs_dir_iops = {
 #if !defined(AFS_LINUX24_ENV)
   .default_file_ops =  &afs_dir_fops,
 #else
@@ -1846,12 +1833,12 @@ afs_symlink_filler(struct file *file, struct page *page)
     return code;
 }
 
-struct address_space_operations afs_symlink_aops = {
+static struct address_space_operations afs_symlink_aops = {
   .readpage =  afs_symlink_filler
 };
 #endif
 
-struct inode_operations afs_symlink_iops = {
+static struct inode_operations afs_symlink_iops = {
 #if defined(AFS_LINUX24_ENV)
   .readlink =          page_readlink,
 #if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
@@ -1868,3 +1855,35 @@ struct inode_operations afs_symlink_iops = {
   .revalidate =                afs_linux_revalidate,
 #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(AFS_LINUX24_ENV)
+       ip->i_data.a_ops = &afs_symlink_aops;
+       ip->i_mapping = &ip->i_data;
+#endif
+    }
+
+    /* insert_inode_hash(ip);  -- this would make iget() work (if we used it) */
+}
index 84fd3f2..8c8a722 100644 (file)
@@ -177,10 +177,6 @@ afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
 #endif
 #endif /* ! AFS_OSF_ENV && !AFS_DARWIN_ENV && !AFS_XBSD_ENV */
 
-#ifdef AFS_LINUX22_ENV
-    /* And linux has its own stash as well. */
-    vattr2inode(AFSTOV(avc), attrs);
-#endif
     return 0;
 }
 
@@ -297,8 +293,8 @@ afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, struct AFS_UCRED *acred)
                     * confuses getwd()... */
 #ifdef AFS_LINUX22_ENV
                    if (avc == afs_globalVp) {
-                       struct inode *ip = avc->v.i_sb->s_root->d_inode;
-                       attrs->va_nodeid = ip->i_ino;
+                       struct inode *ip = AFSTOV(avc)->i_sb->s_root->d_inode;
+                       attrs->va_nodeid = ip->i_ino;   /* VTOI()? */
                    }
 #else
                    if (AFSTOV(avc)->v_flag & VROOT) {
index c82496a..b64d32d 100644 (file)
@@ -31,10 +31,6 @@ RCSID
 
 extern struct DirEntry *afs_dir_GetBlob();
 
-#ifdef AFS_LINUX22_ENV
-extern struct inode_operations afs_symlink_iops, afs_dir_iops;
-#endif
-
 
 afs_int32 afs_bkvolpref = 0;
 afs_int32 afs_bulkStatsDone;
@@ -974,12 +970,8 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
         * We only do this if the entry looks clear.
         */
        afs_ProcessFS(tvcp, &statsp[i], areqp);
-#ifdef AFS_LINUX22_ENV
-       /* overwrite the ops if it's a directory or symlink. */
-       if (vType(tvcp) == VDIR)
-           tvcp->v.v_op = &afs_dir_iops;
-       else if (vType(tvcp) == VLNK)
-           tvcp->v.v_op = &afs_symlink_iops;
+#if defined(AFS_LINUX22_ENV)
+       afs_fill_inode(AFSTOV(tvcp), NULL);     /* reset inode operations */
 #endif
 
        /* do some accounting for bulk stats: mark this entry as
index 95c8a34..c7ec1fe 100644 (file)
@@ -558,10 +558,10 @@ struct SimpleLocks {
 #endif /* AFS_XBSD_ENV */
 
 #if defined(AFS_LINUX24_ENV)
-#define VREFCOUNT(v)           atomic_read(&((vnode_t *) v)->v_count)
-#define VREFCOUNT_SET(v, c)    atomic_set(&((vnode_t *) v)->v_count, c)
-#define VREFCOUNT_DEC(v)       atomic_dec(&((vnode_t *) v)->v_count)
-#define VREFCOUNT_INC(v)       atomic_inc(&((vnode_t *) v)->v_count)
+#define VREFCOUNT(v)           atomic_read(&(AFSTOV(v)->v_count))
+#define VREFCOUNT_SET(v, c)    atomic_set(&(AFSTOV(v)->v_count), c)
+#define VREFCOUNT_DEC(v)       atomic_dec(&(AFSTOV(v)->v_count))
+#define VREFCOUNT_INC(v)       atomic_inc(&(AFSTOV(v)->v_count))
 #else
 #define VREFCOUNT(v)           ((v)->vrefCount)
 #define VREFCOUNT_SET(v, c)    (v)->vrefCount = c;
@@ -580,7 +580,7 @@ struct SimpleLocks {
 
 extern afs_int32 vmPageHog;    /* counter for # of vnodes which are page hogs. */
 
-#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV)
+#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
 #define VTOAFS(v) ((struct vcache *)(v)->v_data)
 #define AFSTOV(vc) ((vc)->v)
 #else
@@ -588,25 +588,22 @@ extern afs_int32 vmPageHog;       /* counter for # of vnodes which are page hogs. */
 #define AFSTOV(V) (&(V)->v)
 #endif
 
-#ifdef AFS_LINUX22_ENV
-#define ITOAFS(V) ((struct vcache*)(V))
-#define AFSTOI(V) (struct inode *)(&(V)->v)
-#endif
-
 /* INVARIANTs: (vlruq.next != NULL) == (vlruq.prev != NULL)
  *             nextfree => !vlruq.next && ! vlruq.prev
  * !(avc->nextfree) && !avc->vlruq.next => (FreeVCList == avc->nextfree)
  */
 struct vcache {
-#if defined(AFS_XBSD_ENV)||defined(AFS_DARWIN_ENV)
+#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
     struct vnode *v;
 #else
     struct vnode v;            /* Has reference count in v.v_count */
 #endif
     struct afs_q vlruq;                /* lru q next and prev */
+#if !defined(AFS_LINUX22_ENV)
     struct vcache *nextfree;   /* next on free list (if free) */
+#endif
     struct vcache *hnext;      /* Hash next */
-    struct vcache *vhnext; /* vol hash next */
+    struct vcache *vhnext;     /* vol hash next */
     struct VenusFid fid;
     struct mstat {
        afs_size_t Length;
@@ -1069,11 +1066,6 @@ extern struct brequest afs_brs[NBRS];    /* request structures */
  * GetVCache incantation, and could eliminate even this code from afs_UFSRead 
  * by making intentionally invalidating quick.stamp in the various callbacks
  * expiration/breaking code */
-#ifdef AFS_LINUX20_ENV
-#define afs_VerifyVCache(avc, areq)  \
-  (((avc)->states & CStatd) ? (vcache2inode(avc), 0) : \
-   afs_VerifyVCache2((avc),areq))
-#else
 #ifdef AFS_DARWIN_ENV
 #define afs_VerifyVCache(avc, areq)  \
   (((avc)->states & CStatd) ? (osi_VM_Setup(avc, 0), 0) : \
@@ -1082,7 +1074,6 @@ extern struct brequest afs_brs[NBRS];     /* request structures */
 #define afs_VerifyVCache(avc, areq)  \
   (((avc)->states & CStatd) ? 0 : afs_VerifyVCache2((avc),areq))
 #endif
-#endif
 
 #define DO_STATS 1             /* bits used by FindVCache */
 #define DO_VLRU 2
index 2e2879d..99ce313 100644 (file)
@@ -48,7 +48,7 @@ struct osi_stat {
 
 struct osi_file {
     afs_int32 size;            /* file size in bytes XXX Must be first field XXX */
-#ifdef AFS_LINUX24_ENV
+#ifdef AFS_LINUX26_ENV
     struct file *filp;         /* May need this if we really open the file. */
 #else
 #ifdef AFS_LINUX22_ENV
@@ -123,7 +123,7 @@ struct afs_osi_WaitHandle {
 /*
  * Vnode related macros
  */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_LINUX22_ENV)
 #define vSetVfsp(vc, vfsp)      AFSTOV(vc)->v_mount = (vfsp)
 #define vSetType(vc, type)      AFSTOV(vc)->v_type = (type)
 #define vType(vc)               AFSTOV(vc)->v_type
@@ -263,7 +263,7 @@ typedef struct timeval osi_timeval_t;
    calling VREF does not */
 #define AFS_FAST_HOLD(vp) osi_vnhold((vp),0)
 #else
-#define AFS_FAST_HOLD(vp) VN_HOLD(&(vp)->v)
+#define AFS_FAST_HOLD(vp) VN_HOLD(AFSTOV(vp))
 #endif
 #define AFS_FAST_RELE(vp) AFS_RELE(AFSTOV(vp))
 
index 1fc969e..fbe1a3d 100644 (file)
@@ -547,8 +547,6 @@ extern void setup_uio(uio_t * uiop, struct iovec *iovecp, const char *buf,
                      uio_seg_t seg);
 extern int uiomove(char *dp, int length, uio_flag_t rw, uio_t * uiop);
 extern void osi_linux_free_inode_pages(void);
-extern void osi_clear_inode(struct inode *ip);
-extern void check_bad_parent(struct dentry *dp);
 #endif
 extern void osi_linux_mask(void);
 extern void osi_linux_unmask(void);
index 4c9dc09..d006eb1 100644 (file)
@@ -47,7 +47,7 @@ RCSID
 #include "afs/afs_cbqueue.h"
 #include "afs/afs_osidnlc.h"
 
-#ifdef AFS_OSF_ENV
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
 afs_int32 afs_maxvcount = 0;   /* max number of vcache entries */
 afs_int32 afs_vcount = 0;      /* number of vcache in use now */
 #endif /* AFS_OSF_ENV */
@@ -63,8 +63,10 @@ char *makesname();
 /* Exported variables */
 afs_rwlock_t afs_xvcache;      /*Lock: alloc new stat cache entries */
 afs_lock_t afs_xvcb;           /*Lock: fids on which there are callbacks */
-struct vcache *freeVCList;     /*Free list for stat cache entries */
-struct vcache *Initial_freeVCList;     /*Initial list for above */
+#if !defined(AFS_LINUX22_ENV)
+static struct vcache *freeVCList;      /*Free list for stat cache entries */
+static struct vcache *Initial_freeVCList;      /*Initial list for above */
+#endif
 struct afs_q VLRU;             /*vcache LRU */
 afs_int32 vcachegen = 0;
 unsigned int afs_paniconwarn = 0;
@@ -151,9 +153,11 @@ afs_FlushVCache(struct vcache *avc, int *slept)
        code = EBUSY;
        goto bad;
     }
+#if !defined(AFS_LINUX22_ENV)
     if (avc->nextfree || !avc->vlruq.prev || !avc->vlruq.next) {       /* qv afs.h */
        refpanic("LRU vs. Free inconsistency");
     }
+#endif
     avc->states |= CVFlushed;
     /* pull the entry out of the lruq and put it on the free list */
     QRemove(&avc->vlruq);
@@ -231,32 +235,36 @@ afs_FlushVCache(struct vcache *avc, int *slept)
     else
        afs_evenZaps++;
 
-#if    !defined(AFS_OSF_ENV)
+#if !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
     /* put the entry in the free list */
     avc->nextfree = freeVCList;
     freeVCList = avc;
     if (avc->vlruq.prev || avc->vlruq.next) {
        refpanic("LRU vs. Free inconsistency");
     }
+    avc->states |= CVFlushed;
 #else
     /* This should put it back on the vnode free list since usecount is 1 */
     afs_vcount--;
     vSetType(avc, VREG);
     if (VREFCOUNT(avc) > 0) {
+#if defined(AFS_OSF_ENV)
        VN_UNLOCK(AFSTOV(avc));
+#endif
        AFS_RELE(AFSTOV(avc));
     } else {
        if (afs_norefpanic) {
            printf("flush vc refcnt < 1");
            afs_norefpanic++;
+#if defined(AFS_OSF_ENV)
            (void)vgone(avc, VX_NOSLEEP, NULL);
            AFS_GLOCK();
            VN_UNLOCK(AFSTOV(avc));
+#endif
        } else
            osi_Panic("flush vc refcnt < 1");
     }
 #endif /* AFS_OSF_ENV */
-    avc->states |= CVFlushed;
     return 0;
 
   bad:
@@ -599,9 +607,9 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
     int code, fv_slept;
 
     AFS_STATCNT(afs_NewVCache);
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
-    if (afs_vcount >= afs_maxvcount) {
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
+#if defined(AFS_OSF30_ENV) || defined(AFS_LINUX22_ENV)
+    if (afs_vcount >= afs_maxvcount)
 #else
     /*
      * If we are using > 33 % of the total system vnodes for AFS vcache
@@ -610,8 +618,9 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
      * our usage is > afs_maxvcount, set elsewhere to 0.5*nvnode,
      * we _must_ free some -- no choice).
      */
-    if (((3 * afs_vcount) > nvnode) || (afs_vcount >= afs_maxvcount)) {
+    if (((3 * afs_vcount) > nvnode) || (afs_vcount >= afs_maxvcount))
 #endif
+    {
        struct afs_q *tq, *uq;
        int i;
        char *panicstr;
@@ -620,14 +629,59 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
        for (tq = VLRU.prev; tq != &VLRU && anumber > 0; tq = uq) {
            tvc = QTOV(tq);
            uq = QPrev(tq);
-           if (tvc->states & CVFlushed)
+           if (tvc->states & CVFlushed) {
                refpanic("CVFlushed on VLRU");
-           else if (i++ > afs_maxvcount)
+           } else if (i++ > afs_maxvcount) {
                refpanic("Exceeded pool of AFS vnodes(VLRU cycle?)");
-           else if (QNext(uq) != tq)
+           } else if (QNext(uq) != tq) {
                refpanic("VLRU inconsistent");
-           else if (VREFCOUNT(tvc) < 1)
+           } else if (VREFCOUNT(tvc) < 1) {
                refpanic("refcnt 0 on VLRU");
+           }
+
+#if defined(AFS_LINUX22_ENV)
+           if (tvc != afs_globalVp && VREFCOUNT(tvc) > 1 && tvc->opens == 0) {
+                struct dentry *dentry;
+                struct list_head *cur, *head;
+                AFS_FAST_HOLD(tvc);
+                AFS_GUNLOCK();
+#if defined(AFS_LINUX24_ENV)
+                spin_lock(&dcache_lock);
+#endif
+               head = &(AFSTOV(tvc))->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);
+
+#if defined(AFS_LINUX24_ENV)
+                   spin_unlock(&dcache_lock);
+#endif
+                   if (d_invalidate(dentry) == -EBUSY) {
+                       dput(dentry);
+                       /* perhaps lock and try to continue? (use cur as head?) */
+                       goto inuse;
+                   }
+                   dput(dentry);
+#if defined(AFS_LINUX24_ENV)
+                   spin_lock(&dcache_lock);
+#endif
+                   goto restart;
+               }                   
+#if defined(AFS_LINUX24_ENV)
+               spin_unlock(&dcache_lock);
+#endif
+           inuse:
+               AFS_GLOCK();
+               AFS_FAST_RELE(tvc);
+           }
+#endif
 
            if (VREFCOUNT(tvc) == 1 && tvc->opens == 0
                && (tvc->states & CUnlinkedDel) == 0) {
@@ -655,6 +709,24 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
        }
     }
 
+#if defined(AFS_LINUX22_ENV)
+{
+    struct inode *ip;
+
+    AFS_GUNLOCK();
+    ip = new_inode(afs_globalVFS);
+    if (!ip)
+       osi_Panic("afs_NewVCache: no more inodes");
+    AFS_GLOCK();
+#if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
+    tvc = VTOAFS(ip);
+#else
+    tvc = afs_osi_Alloc(sizeof(struct vcache));
+    ip->u.generic_ip = tvc;
+    tvc->v = ip;
+#endif
+}
+#else
     AFS_GUNLOCK();
     if (getnewvnode(MOUNT_AFS, &Afs_vnodeops, &nvc)) {
        /* What should we do ???? */
@@ -664,6 +736,7 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
 
     tvc = nvc;
     tvc->nextfree = NULL;
+#endif
     afs_vcount++;
 #else /* AFS_OSF_ENV */
     /* pull out a free cache entry */
@@ -682,45 +755,6 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
            } else if (QNext(uq) != tq) {
                refpanic("VLRU inconsistent");
            }
-#if defined(AFS_LINUX22_ENV)
-           if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) {
-                struct dentry *dentry;
-                struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
-                AFS_FAST_HOLD(tvc);
-                AFS_GUNLOCK();
-
-restart:
-#if defined(AFS_LINUX24_ENV)
-                spin_lock(&dcache_lock);
-#endif
-                cur = head;
-                while ((cur = cur->next) != head) {
-                    dentry = list_entry(cur, struct dentry, d_alias);
-
-                   if (d_unhashed(dentry))
-                       continue;
-
-                   dget_locked(dentry);
-
-#if defined(AFS_LINUX24_ENV)
-                   spin_unlock(&dcache_lock);
-#endif
-                   if (d_invalidate(dentry) == -EBUSY) {
-                       dput(dentry);
-                       /* perhaps lock and try to continue? (use cur as head?) */
-                       goto inuse;
-                   }
-                   dput(dentry);
-                   goto restart;
-               }                   
-#if defined(AFS_LINUX24_ENV)
-               spin_unlock(&dcache_lock);
-#endif
-           inuse:
-               AFS_GLOCK();
-               AFS_FAST_RELE(tvc);
-           }
-#endif
 
            if (((VREFCOUNT(tvc) == 0) 
 #if defined(AFS_DARWIN_ENV) && !defined(UKERNEL) 
@@ -797,7 +831,7 @@ restart:
        panic("afs_NewVCache(): free vcache with vnode attached");
 #endif
 
-#if !defined(AFS_SGI_ENV) && !defined(AFS_OSF_ENV)
+#if !defined(AFS_SGI_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
     memset((char *)tvc, 0, sizeof(struct vcache));
 #else
     tvc->uncred = 0;
@@ -871,92 +905,8 @@ restart:
     hzero(tvc->mapDV);
     tvc->truncPos = AFS_NOTRUNC;       /* don't truncate until we need to */
     hzero(tvc->m.DataVersion); /* in case we copy it into flushDV */
-#if defined(AFS_LINUX22_ENV)
-    {
-       struct inode *ip = AFSTOI(tvc);
-#if defined(AFS_LINUX24_ENV)
-       struct address_space *mapping = &ip->i_data;
-#endif
-
-#if defined(AFS_LINUX26_ENV)
-       inode_init_once(ip);
-#else
-       sema_init(&ip->i_sem, 1);
-       INIT_LIST_HEAD(&ip->i_hash);
-       INIT_LIST_HEAD(&ip->i_dentry);
-#if defined(AFS_LINUX24_ENV)
-       sema_init(&ip->i_zombie, 1);
-       init_waitqueue_head(&ip->i_wait);
-       spin_lock_init(&ip->i_data.i_shared_lock);
-#ifdef STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
-       spin_lock_init(&ip->i_data.page_lock);
-#endif
-       INIT_LIST_HEAD(&ip->i_data.clean_pages);
-       INIT_LIST_HEAD(&ip->i_data.dirty_pages);
-       INIT_LIST_HEAD(&ip->i_data.locked_pages);
-       INIT_LIST_HEAD(&ip->i_dirty_buffers);
-#ifdef STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
-       INIT_LIST_HEAD(&ip->i_dirty_data_buffers);
-#endif
-#ifdef STRUCT_INODE_HAS_I_DEVICES
-       INIT_LIST_HEAD(&ip->i_devices);
-#endif
-#ifdef STRUCT_INODE_HAS_I_TRUNCATE_SEM
-       init_rwsem(&ip->i_truncate_sem);
-#endif
-#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
-       init_rwsem(&ip->i_alloc_sem);
-#endif
-
-#else /* AFS_LINUX22_ENV */
-       sema_init(&ip->i_atomic_write, 1);
-       init_waitqueue(&ip->i_wait);
-#endif
-#endif
 
-#if defined(AFS_LINUX24_ENV)
-       mapping->host = ip;
-       ip->i_mapping = mapping;
-#ifdef STRUCT_ADDRESS_SPACE_HAS_GFP_MASK
-       ip->i_data.gfp_mask = GFP_HIGHUSER;
-#endif
-#if defined(AFS_LINUX26_ENV)
-       mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
-       {
-           extern struct backing_dev_info afs_backing_dev_info;
-
-           mapping->backing_dev_info = &afs_backing_dev_info;
-       }
-#endif
-#endif
-
-#if !defined(AFS_LINUX26_ENV)
-       if (afs_globalVFS)
-           ip->i_dev = afs_globalVFS->s_dev;
-#else
-#ifdef STRUCT_INODE_HAS_I_SECURITY
-       ip->i_security = NULL;
-       if (security_inode_alloc(ip))
-           panic("Cannot allocate inode security");
-#endif
-#endif
-       ip->i_sb = afs_globalVFS;
-       put_inode_on_dummy_list(ip);
-#ifdef STRUCT_INODE_HAS_I_SB_LIST
-       list_add(&ip->i_sb_list, &ip->i_sb->s_inodes);
-#endif
-#if defined(STRUCT_INODE_HAS_INOTIFY_LOCK) || defined(STRUCT_INODE_HAS_INOTIFY_SEM)
-       INIT_LIST_HEAD(&ip->inotify_watches); 
-#if defined(STRUCT_INODE_HAS_INOTIFY_SEM) 
-       sema_init(&ip->inotify_sem, 1); 
-#else
-       spin_lock_init(&ip->inotify_lock); 
-#endif 
-#endif 
-    }
-#endif
-
-#ifdef AFS_OSF_ENV
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
     /* Hold it for the LRU (should make count 2) */
     VN_HOLD(AFSTOV(tvc));
 #else /* AFS_OSF_ENV */
@@ -1040,7 +990,9 @@ restart:
        tvc->mvstat = 2;
     if (afs_globalVFS == 0)
        osi_Panic("afs globalvfs");
+#if !defined(AFS_LINUX22_ENV)
     vSetVfsp(tvc, afs_globalVFS);
+#endif
     vSetType(tvc, VREG);
 #ifdef AFS_AIX_ENV
     tvc->v.v_vfsnext = afs_globalVFS->vfs_vnodes;      /* link off vfs */
@@ -1576,10 +1528,6 @@ afs_ProcessFS(register struct vcache *avc,
        else                    /* not found, add a new one if possible */
            afs_AddAxs(avc->Access, areq->uid, astat->CallerAccess);
     }
-#ifdef AFS_LINUX22_ENV
-    vcache2inode(avc);         /* Set the inode attr cache */
-#endif
-
 }                              /*afs_ProcessFS */
 
 
@@ -1709,9 +1657,6 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq,
     ObtainWriteLock(&tvc->lock, 54);
 
     if (tvc->states & CStatd) {
-#ifdef AFS_LINUX22_ENV
-       vcache2inode(tvc);
-#endif
        ReleaseWriteLock(&tvc->lock);
        return tvc;
     }
@@ -2572,10 +2517,6 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
        else
            afs_stats_cmperf.vremoteAccesses++;
     }
-#ifdef AFS_LINUX22_ENV
-    if (tvc && (tvc->states & CStatd))
-       vcache2inode(tvc);      /* mainly to reset i_nlink */
-#endif
     return tvc;
 }                              /*afs_FindVCache */
 
@@ -2730,9 +2671,11 @@ afs_vcacheInit(int astatSize)
 {
     register struct vcache *tvp;
     int i;
-#if    defined(AFS_OSF_ENV)
+#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
     if (!afs_maxvcount) {
-#if    defined(AFS_OSF30_ENV)
+#if defined(AFS_LINUX22_ENV)
+       afs_maxvcount = astatSize;      /* no particular limit on linux? */
+#elif defined(AFS_OSF30_ENV)
        afs_maxvcount = max_vnodes / 2; /* limit ourselves to half the total */
 #else
        afs_maxvcount = nvnode / 2;     /* limit ourselves to half the total */
@@ -2748,18 +2691,7 @@ afs_vcacheInit(int astatSize)
     RWLOCK_INIT(&afs_xvcache, "afs_xvcache");
     LOCK_INIT(&afs_xvcb, "afs_xvcb");
 
-#if    !defined(AFS_OSF_ENV)
-#ifdef AFS_LINUX26_ENV
-    printf("old style would have needed %d contiguous bytes\n", astatSize *
-          sizeof(struct vcache));
-    Initial_freeVCList = freeVCList = tvp = (struct vcache *)
-       afs_osi_Alloc(sizeof(struct vcache));
-    for (i = 0; i < astatSize; i++) {
-       tvp->nextfree = (struct vcache *) afs_osi_Alloc(sizeof(struct vcache));
-       tvp = tvp->nextfree;
-    }
-    tvp->nextfree = NULL;
-#else
+#if !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
     /* Allocate and thread the struct vcache entries */
     tvp = (struct vcache *)afs_osi_Alloc(astatSize * sizeof(struct vcache));
     memset((char *)tvp, 0, sizeof(struct vcache) * astatSize);
@@ -2774,7 +2706,6 @@ afs_vcacheInit(int astatSize)
     pin((char *)tvp, astatSize * sizeof(struct vcache));       /* XXX */
 #endif
 #endif
-#endif
 
 #if defined(AFS_SGI_ENV)
     for (i = 0; i < astatSize; i++) {
@@ -2884,26 +2815,14 @@ shutdown_vcache(void)
     }
     afs_cbrSpace = 0;
 
-#ifdef AFS_LINUX26_ENV
-    {
-       struct vcache *tvp = Initial_freeVCList;
-       while (tvp) {
-           struct vcache *next = tvp->nextfree;
-           
-           afs_osi_Free(tvp, sizeof(struct vcache));
-           tvp = next;
-       }
-    }
-#else
 #ifdef  KERNEL_HAVE_PIN
     unpin(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
 #endif
-#if    !defined(AFS_OSF_ENV)
+#if !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
     afs_osi_Free(Initial_freeVCList, afs_cacheStats * sizeof(struct vcache));
 #endif
-#endif
 
-#if    !defined(AFS_OSF_ENV)
+#if !defined(AFS_OSF_ENV) && !defined(AFS_LINUX22_ENV)
     freeVCList = Initial_freeVCList = 0;
 #endif
     RWLOCK_INIT(&afs_xvcache, "afs_xvcache");
index cc7d39c..96bfe2e 100644 (file)
@@ -82,6 +82,7 @@ AC_MSG_CHECKING(whether to build osi_vfs.h)
 configdir=ifelse([$1], ,[src/config],$1)
 outputdir=ifelse([$2], ,[src/afs/LINUX],$2)
 tmpldir=ifelse([$3], ,[src/afs/LINUX],$3)
-chmod +x $configdir/make_vnode.pl
-$configdir/make_vnode.pl -i $LINUX_KERNEL_PATH -t ${tmpldir} -o $outputdir
+cp  $tmpldir/osi_vfs.hin $outputdir/osi_vfs.h
+# chmod +x $configdir/make_vnode.pl
+# $configdir/make_vnode.pl -i $LINUX_KERNEL_PATH -t ${tmpldir} -o $outputdir
 ])
index ffb96e4..64032f9 100644 (file)
@@ -467,3 +467,18 @@ ac_cv_linux_sched_struct_task_struct_has_exit_state=yes,
 ac_cv_linux_sched_struct_task_struct_has_exit_state=no)])
 AC_MSG_RESULT($ac_cv_linux_sched_struct_task_struct_has_exit_state)
 CPPFLAGS="$save_CPPFLAGS"])
+
+AC_DEFUN([LINUX_FS_STRUCT_SUPER_HAS_ALLOC_INODE], [
+AC_MSG_CHECKING(for alloc_inode in struct super_operations)
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="-I${LINUX_KERNEL_PATH}/include -I${LINUX_KERNEL_PATH}/include/asm/mach-${SUBARCH} -D__KERNEL__ $CPPFLAGS"
+AC_CACHE_VAL(ac_cv_linux_fs_struct_super_has_alloc_inode, 
+[
+AC_TRY_COMPILE(
+[#include <linux/fs.h>],
+[struct super_operations _super;
+printf("%p\n", _super.alloc_inode);], 
+ac_cv_linux_fs_struct_super_has_alloc_inode=yes,
+ac_cv_linux_fs_struct_super_has_alloc_inode=no)])
+AC_MSG_RESULT($ac_cv_linux_fs_struct_super_has_alloc_inode)
+CPPFLAGS="$save_CPPFLAGS"])
index b16d919..ceeb8ce 100644 (file)
@@ -2885,7 +2885,7 @@ print_vcache(kmem, vep, ptr, pnt)
            printf("\n");
 #ifdef AFS33
        printf("%lx: refC=%d, pv=%d, pu=%d, flushDv=%d.%d, mapDV=%d.%d, ",
-              ptr, vep->vrefCount, vep->parentVnode, vep->parentUnique,
+              ptr, VREFCOUNT(vep), vep->parentVnode, vep->parentUnique,
               vep->flushDV.high, vep->flushDV.low, vep->mapDV.high,
               vep->mapDV.low);
 #ifdef AFS_64BIT_CLIENT