linux26-more-updates-20040420
authorChas Williams <chas@cmf.nrl.navy.mil>
Wed, 21 Apr 2004 03:20:21 +0000 (03:20 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 21 Apr 2004 03:20:21 +0000 (03:20 +0000)
FIXES 4027

        . osi_cred now uses struct group_info
        . the big kernel lock has been moved from the fs generic code
          for some of the operations in 2.6
        . 2.6 now just uses iput() and hooks the appropriate routines
        . the dummy inode list handling should be clearer

src/afs/LINUX/osi_cred.c
src/afs/LINUX/osi_groups.c
src/afs/LINUX/osi_machdep.h
src/afs/LINUX/osi_misc.c
src/afs/LINUX/osi_vfs.hin
src/afs/LINUX/osi_vfsops.c
src/afs/LINUX/osi_vnodeops.c
src/afs/afs_osi.c
src/afs/afs_osi_pag.c
src/afs/afs_vcache.c

index 12a9586..9cad716 100644 (file)
@@ -63,6 +63,9 @@ crget(void)
     CRED_UNLOCK();
 
     memset(tmp, 0, sizeof(cred_t));
+#if defined(AFS_LINUX26_ENV)
+    tmp->cr_group_info = groups_alloc(0);
+#endif
     tmp->cr_ref = 1;
     return tmp;
 }
@@ -71,6 +74,9 @@ void
 crfree(cred_t * cr)
 {
     if (cr->cr_ref > 1) {
+#if defined(AFS_LINUX26_ENV)
+       put_group_info(cr->cr_group_info);
+#endif
        cr->cr_ref--;
        return;
     }
@@ -88,7 +94,24 @@ cred_t *
 crdup(cred_t * cr)
 {
     cred_t *tmp = crget();
-    *tmp = *cr;
+
+    tmp->cr_uid = cr->cr_uid;
+    tmp->cr_ruid = cr->cr_ruid;
+    tmp->cr_gid = cr->cr_gid;
+#if defined(AFS_LINUX26_ENV)
+{
+    struct group_info *old_info;
+
+    old_info = tmp->cr_group_info;
+    get_group_info(cr->cr_group_info);
+    tmp->cr_group_info = cr->cr_group_info;
+    put_group_info(old_info);
+}
+#else
+    memcpy(tmp->cr_groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
+    tmp->cr_ngroups = cr->cr_ngroups;
+#endif
+
     tmp->cr_ref = 1;
     return tmp;
 }
@@ -97,17 +120,19 @@ cred_t *
 crref(void)
 {
     cred_t *cr = crget();
+
     cr->cr_uid = current->fsuid;
     cr->cr_ruid = current->uid;
     cr->cr_gid = current->fsgid;
     cr->cr_rgid = current->gid;
 #if defined(AFS_LINUX26_ENV)
 {
-    int i;
+    struct group_info *old_info;
 
-    for(i = 0; i < current->group_info->ngroups && i < NGROUPS; ++i)
-        cr->cr_groups[i] = GROUP_AT(current->group_info, i);
-    cr->cr_ngroups = current->group_info->ngroups;
+    old_info = cr->cr_group_info;
+    get_group_info(current->group_info);
+    cr->cr_group_info = current->group_info;
+    put_group_info(old_info);
 }
 #else
     memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
@@ -127,14 +152,13 @@ crset(cred_t * cr)
     current->gid = cr->cr_rgid;
 #if defined(AFS_LINUX26_ENV)
 {
-    struct group_info *new_info;
-    int i;
+    struct group_info *old_info;
 
-    new_info = groups_alloc(cr->cr_ngroups);
-    for(i = 0; i < cr->cr_ngroups; ++i)
-       GROUP_AT(new_info, i) = cr->cr_groups[i];
-    set_current_groups(new_info);
-    put_group_info(new_info);
+    /* using set_current_groups() will sort the groups */
+    old_info = current->group_info;
+    get_group_info(cr->cr_group_info);
+    current->group_info = cr->cr_group_info;
+    put_group_info(old_info);
 }
 #else
     memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
index 1d6b679..b0000c4 100644 (file)
@@ -26,32 +26,93 @@ RCSID
 #include "h/smp_lock.h"
 #endif
 
-static int afs_getgroups(cred_t * cr, gid_t * groups);
-static int afs_setgroups(cred_t ** cr, int ngroups, gid_t * gidset,
-                        int change_parent);
+#if defined(AFS_LINUX26_ENV)
+static int
+afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent)
+{
+    struct group_info *old_info;
 
-/* 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)
+    AFS_STATCNT(afs_setgroups);
+
+    old_info = (*cr)->cr_group_info;
+    get_group_info(group_info);
+    (*cr)->cr_group_info = group_info;
+    put_group_info(old_info);
+
+    crset(*cr);
+
+    if (change_parent) {
+       old_info = current->parent->group_info;
+       get_group_info(group_info);
+       current->parent->group_info = group_info;
+       put_group_info(old_info);
+    }
+
+    return (0);
+}
+#else
+static int
+afs_setgroups(cred_t **cr, int ngroups, gid_t * gidset, int change_parent)
 {
+    int ngrps;
     int i;
-#if defined(AFS_LINUX26_ENV)
-    struct group_info *old_info, *new_info;
+    gid_t *gp;
 
-    old_info = current->parent->group_info;
-    new_info = groups_alloc(old_info->ngroups + 2);
+    AFS_STATCNT(afs_setgroups);
 
-    for(i = 0; i < old_info->ngroups; ++i)
-       GROUP_AT(new_info, i) = GROUP_AT(old_info, i);
+    if (ngroups > NGROUPS)
+       return EINVAL;
 
-    GROUP_AT(new_info, i++) = g0;
-    GROUP_AT(new_info, i++) = g1;
+    gp = (*cr)->cr_groups;
+    if (ngroups < NGROUPS)
+       gp[ngroups] = (gid_t) NOGROUP;
 
-    current->parent->group_info = new_info;
-    put_group_info(old_info);
+    for (i = ngroups; i > 0; i--) {
+       *gp++ = *gidset++;
+    }
+
+    (*cr)->cr_ngroups = ngroups;
+    crset(*cr);
+    return (0);
+}
+#endif
+
+#if defined(AFS_LINUX26_ENV)
+static struct group_info *
+afs_getgroups(cred_t * cr)
+{
+    AFS_STATCNT(afs_getgroups);
+
+    get_group_info(cr->cr_group_info);
+    return cr->cr_group_info;
+}
 #else
+/* Returns number of groups. And we trust groups to be large enough to
+ * hold all the groups.
+ */
+static int
+afs_getgroups(cred_t *cr, gid_t *groups)
+{
+    int i;
+    AFS_STATCNT(afs_getgroups);
+
+    gid_t *gp = cr->cr_groups;
+    int n = cr->cr_ngroups;
+
+    for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++)
+       *groups++ = *gp++;
+    return i;
+}
+#endif
+
+#if !defined(AFS_LINUX26_ENV)
+/* Only propogate the PAG to the parent process. Unix's propogate to 
+ * all processes sharing the cred.
+ */
+int
+set_pag_in_parent(int pag, int g0, int g1)
+{
+    int i;
 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
     gid_t *gp = current->parent->groups;
     int ngroups = current->parent->ngroups;
@@ -80,14 +141,47 @@ set_pag_in_parent(int pag, int g0, int g1)
 #else
     current->p_pptr->ngroups = ngroups;
 #endif
-#endif
     return 0;
 }
+#endif
 
 int
 setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
        int change_parent)
 {
+#if defined(AFS_LINUX26_ENV)
+    struct group_info *group_info;
+    gid_t g0, g1;
+
+    AFS_STATCNT(setpag);
+
+    group_info = afs_getgroups(*cr);
+    g0 = GROUP_AT(group_info, 0);
+    g1 = GROUP_AT(group_info, 1);
+
+    if (afs_get_pag_from_groups(g0, g1) == NOPAG) {
+       /* We will have to make sure group_info is big enough for pag */
+       struct group_info *tmp;
+       int i;
+       
+       tmp = groups_alloc(group_info->ngroups + 2);
+       for (i = 0; i < group_info->ngroups; ++i)
+               GROUP_AT(tmp, i + 2) = GROUP_AT(group_info, i);
+       put_group_info(group_info);
+       group_info = tmp;
+    }
+
+    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    afs_get_groups_from_pag(*newpag, &g0, &g1);
+    GROUP_AT(group_info, 0) = g0;
+    GROUP_AT(group_info, 1) = g1;
+
+    afs_setgroups(cr, group_info, change_parent);
+
+    put_group_info(group_info);
+
+    return 0;
+#else
     gid_t *gidset;
     afs_int32 ngroups, code = 0;
     int j;
@@ -121,6 +215,7 @@ setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
 
     osi_Free((char *)gidset, NGROUPS * sizeof(int));
     return code;
+#endif
 }
 
 
@@ -297,44 +392,3 @@ afs32_xsetgroups32(int gidsetsize, gid_t * grouplist)
 #endif
 #endif
 
-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;
-    gid_t *gp = cr->cr_groups;
-    int n = cr->cr_ngroups;
-    AFS_STATCNT(afs_getgroups);
-
-    for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++) {
-       *groups++ = *gp++;
-    }
-    return i;
-}
index e740c5c..6cd4eb9 100644 (file)
 #undef gop_lookupname
 #define gop_lookupname osi_lookupname
 
-#define osi_vnhold(v, n)  VN_HOLD(v)
+#define osi_vnhold(v, n) do { VN_HOLD(AFSTOV(v)); } while (0)
+
+#if defined(AFS_LINUX24_ENV)
+#define VN_HOLD(V) atomic_inc(&((vnode_t *) V)->i_count)
+#else
+#define VN_HOLD(V) ((vnode_t *) V)->i_count++
+#endif
+
+#if defined(AFS_LINUX26_ENV)
+#define VN_RELE(V) iput((struct inode *) V)
+#else
+#define VN_RELE(V) osi_iput((struct inode *) V)
+#endif
 
 #define osi_AllocSmall afs_osi_Alloc
 #define osi_FreeSmall afs_osi_Free
@@ -105,9 +117,6 @@ extern struct vnodeops afs_file_iops, afs_dir_iops, afs_symlink_iops;
 
 
 #define PAGESIZE PAGE_SIZE
-#ifndef NGROUPS
-#define NGROUPS NGROUPS_MAX
-#endif
 
 /* cred struct */
 typedef struct cred {          /* maps to task field: */
@@ -120,8 +129,12 @@ typedef struct cred {              /* maps to task field: */
     uid_t cr_ruid;             /* uid */
     gid_t cr_gid;              /* egid */
     gid_t cr_rgid;             /* gid */
+#if defined(AFS_LINUX26_ENV)
+    struct group_info *cr_group_info;
+#else
     gid_t cr_groups[NGROUPS];  /* 32 groups - empty set to NOGROUP */
     int cr_ngroups;
+#endif
 } cred_t;
 #define AFS_UCRED cred
 #define AFS_PROC struct task_struct
index 91fc0ce..135429b 100644 (file)
@@ -376,16 +376,13 @@ osi_clear_inode(struct inode *ip)
 
     afs_InactiveVCache(vcp, credp);
     ObtainWriteLock(&vcp->lock, 504);
-#if defined(AFS_LINUX24_ENV)
-    atomic_set(&ip->i_count, 0);
-#else
-    ip->i_count = 0;
-#endif
     ip->i_nlink = 0;           /* iput checks this after calling this routine. */
+    ip->i_state = I_CLEAR;
     ReleaseWriteLock(&vcp->lock);
     crfree(credp);
 }
 
+#if !defined(AFS_LINUX26_ENV)
 /* iput an inode. Since we still have a separate inode pool, we don't want
  * to call iput on AFS inodes, since they would then end up on Linux's
  * inode_unsed list.
@@ -418,9 +415,13 @@ osi_iput(struct inode *ip)
 #else
     if (!--ip->i_count)
 #endif
-           osi_clear_inode(ip);
+                                          {
+       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
@@ -453,7 +454,7 @@ check_bad_parent(struct dentry *dp)
        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,
-                      "afs_linux_revalidate : bad pointer returned from afs_lookup origvc newvc dentry",
+                      "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
                       ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
                       ICL_TYPE_POINTER, dp);
        }
index 4231a3d..87d58fe 100644 (file)
@@ -63,12 +63,6 @@ enum vcexcl { EXCL, NONEXCL } ;
 #define FSYNC O_SYNC
 
 #define VTOI(V)  ((struct inode*)V)
-#ifdef 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
-#define VN_RELE(V) osi_iput((struct inode *)V);
 #define VFS_STATFS(V, S) ((V)->s_op->statfs)((V), (S), sizeof(*(S)))
 
 
@@ -110,7 +104,9 @@ typedef struct vattr {
  */
 #define AT_SIZE                ATTR_SIZE
 #define AT_MODE                ATTR_MODE
+#undef AT_UID
 #define AT_UID         ATTR_UID
+#undef AT_GID
 #define AT_GID         ATTR_GID
 #define AT_MTIME       ATTR_MTIME
 
index 046da30..14c12c4 100644 (file)
@@ -225,6 +225,9 @@ afs_notify_change(struct dentry *dp, struct iattr *iattrp)
     struct inode *ip = dp->d_inode;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     VATTR_NULL(&vattr);
     iattr2vattr(&vattr, iattrp);       /* Convert for AFS vnodeops call. */
     update_inode_cache(ip, &vattr);
@@ -234,6 +237,9 @@ afs_notify_change(struct dentry *dp, struct iattr *iattrp)
      * least we've got the newest version of what was supposed to be set.
      */
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
@@ -275,21 +281,12 @@ afs_write_inode(struct inode *ip)
 }
 
 
-#if defined(AFS_LINUX26_ENV)
 static void
 afs_destroy_inode(struct inode *ip)
 {
-    /* afs inodes cannot be destroyed */
+    ip->i_state = 0;
 }
 
-static void
-afs_clear_inode(struct inode *ip)
-{
-    AFS_GLOCK();
-    osi_clear_inode(ip);
-    AFS_GUNLOCK();
-}
-#else
 
 /* afs_put_inode
  * called from iput when count goes to zero. Linux version of inactive.
@@ -303,11 +300,14 @@ afs_delete_inode(struct inode *ip)
 {
     struct vcache *vp = ITOAFS(ip);
 
+#ifdef AFS_LINUX26_ENV
+    put_inode_on_dummy_list(ip);
+#endif
+
     AFS_GLOCK();
     osi_clear_inode(ip);
     AFS_GUNLOCK();
 }
-#endif
 
 
 /* afs_put_super
@@ -400,11 +400,10 @@ afs_umount_begin(struct super_block *sbp)
 
 struct super_operations afs_sops = {
 #if defined(AFS_LINUX26_ENV)
+  .drop_inode =                generic_delete_inode,
   .destroy_inode =     afs_destroy_inode,
-  .clear_inode =       afs_clear_inode,
-#else
-  .delete_inode =      afs_delete_inode,
 #endif
+  .delete_inode =      afs_delete_inode,
   .write_inode =       afs_write_inode,
   .put_super =         afs_put_super,
   .statfs =            afs_statfs,
@@ -516,14 +515,6 @@ vattr2inode(struct inode *ip, struct vattr *vp)
     ip->i_mtime = vp->va_mtime.tv_sec;
     ip->i_ctime = vp->va_ctime.tv_sec;
 #endif
-
-    /* we should put our inodes on a dummy inode list to keep linux happy. */
-    if (!ip->i_list.prev && !ip->i_list.next) {
-       /* this might be bad as we are reaching under the covers of the 
-        * list structure but we want to avoid putting the inode 
-        * on the list more than once.   */
-       put_inode_on_dummy_list(ip);
-    }
 }
 
 /* Put this afs inode on our own dummy list. Linux expects to see inodes
index 6e3cb80..ebefdc8 100644 (file)
@@ -47,7 +47,6 @@ RCSID
 extern struct vcache *afs_globalVp;
 extern afs_rwlock_t afs_xvcache;
 
-extern struct dentry_operations *afs_dops;
 #if defined(AFS_LINUX24_ENV)
 extern struct inode_operations afs_file_iops;
 extern struct address_space_operations afs_file_aops;
@@ -272,39 +271,33 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
     struct afs_fakestat_state fakestat;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     AFS_STATCNT(afs_readdir);
 
     code = afs_InitReq(&treq, credp);
     crfree(credp);
-    if (code) {
-       AFS_GUNLOCK();
-       return -code;
-    }
+    if (code)
+       goto out1;
 
     afs_InitFakeStat(&fakestat);
     code = afs_EvalFakeStat(&avc, &fakestat, &treq);
-    if (code) {
-       afs_PutFakeStat(&fakestat);
-       AFS_GUNLOCK();
-       return -code;
-    }
+    if (code)
+       goto out;
 
     /* update the cache entry */
   tagain:
     code = afs_VerifyVCache(avc, &treq);
-    if (code) {
-       afs_PutFakeStat(&fakestat);
-       AFS_GUNLOCK();
-       return -code;
-    }
+    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) {
-       afs_PutFakeStat(&fakestat);
-       AFS_GUNLOCK();
-       return -ENOENT;
+       code = -ENOENT;
+       goto out;
     }
     ObtainReadLock(&avc->lock);
     ObtainReadLock(&tdc->lock);
@@ -335,7 +328,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
      * takes an offset in units of blobs, rather than bytes.
      */
     code = 0;
-    offset = (int)fp->f_pos;
+    offset = (int) fp->f_pos;
     while (1) {
        dirpos = BlobScan(&tdc->f.inode, offset);
        if (!dirpos)
@@ -352,11 +345,11 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
        else {
            printf("afs_linux_readdir: afs_dir_GetBlob failed, null name (inode %x, dirpos %d)\n", 
                   &tdc->f.inode, dirpos);
-           DRelease(de, 0);
+           DRelease((struct buffer *) de, 0);
            afs_PutDCache(tdc);
            ReleaseReadLock(&avc->lock);
-           afs_PutFakeStat(&fakestat);
-           return -ENOENT;
+           code = -ENOENT;
+           goto out;
        }
 
        /* filldir returns -EINVAL when the buffer is full. */
@@ -396,7 +389,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
 #else
        code = (*filldir) (dirbuf, de->name, len, offset, ino);
 #endif
-       DRelease(de, 0);
+       DRelease((struct buffer *)de, 0);
        if (code)
            break;
        offset = dirpos + 1 + ((len + 16) >> 5);
@@ -409,9 +402,16 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
     ReleaseReadLock(&tdc->lock);
     afs_PutDCache(tdc);
     ReleaseReadLock(&avc->lock);
+    code = 0;
+
+out:
     afs_PutFakeStat(&fakestat);
+out1:
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
-    return 0;
+    return code;
 }
 
 
@@ -763,15 +763,6 @@ struct file_operations afs_file_fops = {
  * AFS Linux dentry operations
  **********************************************************************/
 
-static int
-afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
-        int err = afs_linux_revalidate(dentry);
-        if (!err)
-                generic_fillattr(dentry->d_inode, stat);
-        return err;
-}
-
 /* afs_linux_revalidate
  * Ensure vcache is stat'd before use. Return 0 if entry is valid.
  */
@@ -827,6 +818,16 @@ afs_linux_revalidate(struct dentry *dp)
     return -code;
 }
 
+#if defined(AFS_LINUX26_ENV)
+static int
+afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+        int err = afs_linux_revalidate(dentry);
+        if (!err)
+                generic_fillattr(dentry->d_inode, stat);
+        return err;
+}
+#endif
 
 /* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
  * In kernels 2.2.10 and above, we are passed an additional flags var which
@@ -918,6 +919,7 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     return !bad_dentry;
 }
 
+#if !defined(AFS_LINUX26_ENV)
 /* afs_dentry_iput */
 static void
 afs_dentry_iput(struct dentry *dp, struct inode *ip)
@@ -932,6 +934,7 @@ afs_dentry_iput(struct dentry *dp, struct inode *ip)
 
     osi_iput(ip);
 }
+#endif
 
 static int
 afs_dentry_delete(struct dentry *dp)
@@ -952,10 +955,11 @@ afs_dentry_delete(struct dentry *dp)
 
 struct dentry_operations afs_dentry_operations = {
   .d_revalidate =      afs_linux_dentry_revalidate,
-  .d_iput =            afs_dentry_iput,
   .d_delete =          afs_dentry_delete,
+#if !defined(AFS_LINUX26_ENV)
+  .d_iput =            afs_dentry_iput,
+#endif
 };
-struct dentry_operations *afs_dops = &afs_dentry_operations;
 
 /**********************************************************************
  * AFS Linux inode operations
@@ -983,6 +987,9 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
     vattr.va_mode = mode;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     code =
        afs_create(ITOAFS(dip), name, &vattr, NONEXCL, mode,
                   (struct vcache **)&ip, credp);
@@ -1011,11 +1018,14 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
            ip->i_op = &afs_symlink_iops;
 #endif
 
-       dp->d_op = afs_dops;
+       dp->d_op = &afs_dentry_operations;
        dp->d_time = jiffies;
        d_instantiate(dp, ip);
     }
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
@@ -1034,7 +1044,11 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
     cred_t *credp = crref();
     struct vcache *vcp = NULL;
     const char *comp = dp->d_name.name;
+
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     code = afs_lookup(ITOAFS(dip), comp, &vcp, credp);
     
     if (vcp) {
@@ -1064,9 +1078,12 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
     }
     dp->d_time = jiffies;
-    dp->d_op = afs_dops;
+    dp->d_op = &afs_dentry_operations;
     d_add(dp, AFSTOI(vcp));
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
     crfree(credp);
 
@@ -1114,10 +1131,16 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
     const char *name = dp->d_name.name;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     code = afs_remove(ITOAFS(dip), name, credp);
-    AFS_GUNLOCK();
     if (!code)
        d_drop(dp);
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
+    AFS_GUNLOCK();
     crfree(credp);
     return -code;
 }
@@ -1154,6 +1177,9 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
     const char *name = dp->d_name.name;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     VATTR_NULL(&vattr);
     vattr.va_mask = ATTR_MODE;
     vattr.va_mode = mode;
@@ -1164,11 +1190,14 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
 #if defined(AFS_LINUX24_ENV)
        tvcp->v.v_fop = &afs_dir_fops;
 #endif
-       dp->d_op = afs_dops;
+       dp->d_op = &afs_dentry_operations;
        dp->d_time = jiffies;
        d_instantiate(dp, AFSTOI(tvcp));
     }
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
@@ -1182,6 +1211,9 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
     const char *name = dp->d_name.name;
 
     AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     code = afs_rmdir(ITOAFS(dip), name, credp);
 
     /* Linux likes to see ENOTEMPTY returned from an rmdir() syscall
@@ -1196,6 +1228,9 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp)
        d_drop(dp);
     }
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
     AFS_GUNLOCK();
     crfree(credp);
     return -code;
@@ -1212,20 +1247,27 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp,
     const char *oldname = olddp->d_name.name;
     const char *newname = newdp->d_name.name;
 
+    AFS_GLOCK();
+#if defined(AFS_LINUX26_ENV)
+    lock_kernel();
+#endif
     /* Remove old and new entries from name hash. New one will change below.
      * While it's optimal to catch failures and re-insert newdp into hash,
      * it's also error prone and in that case we're already dealing with error
      * cases. Let another lookup put things right, if need be.
      */
-    if (!list_empty(&olddp->d_hash)) {
+#if defined(AFS_LINUX26_ENV)
+    if (!d_unhashed(olddp))
        d_drop(olddp);
-    }
-    if (!list_empty(&newdp->d_hash)) {
+    if (!d_unhashed(newdp))
        d_drop(newdp);
-    }
-    AFS_GLOCK();
+#else
+    if (!list_empty(&olddp->d_hash))
+       d_drop(olddp);
+    if (!list_empty(&newdp->d_hash))
+       d_drop(newdp);
+#endif
     code = afs_rename(ITOAFS(oldip), oldname, ITOAFS(newip), newname, credp);
-    AFS_GUNLOCK();
 
     if (!code) {
        /* update time so it doesn't expire immediately */
@@ -1233,6 +1275,11 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp,
        d_move(olddp, newdp);
     }
 
+#if defined(AFS_LINUX26_ENV)
+    unlock_kernel();
+#endif
+    AFS_GUNLOCK();
+
     crfree(credp);
     return -code;
 }
index 6400ed7..04065e0 100644 (file)
@@ -74,7 +74,9 @@ osi_Init(void)
 #endif /* AFS_HPUX_ENV */
 
     if (!afs_osicred_initialized) {
-#ifdef AFS_XBSD_ENV
+#if defined(AFS_LINUX26_ENV)
+       afs_osi_credp = crref();
+#elif defined(AFS_XBSD_ENV)
        /* Can't just invent one, must use crget() because of mutex */
        afs_osi_credp = crdup(osi_curcred());
 #else
@@ -1059,15 +1061,8 @@ afs_osi_proc2cred(AFS_PROC * pr)
        cr.cr_ref = 1;
        cr.cr_uid = pr->uid;
 #if defined(AFS_LINUX26_ENV)
-{
-       int i;
-
-       memset(cr.cr_groups, 0, NGROUPS * sizeof(gid_t));
-
-       cr.cr_ngroups = pr->group_info->ngroups;
-       for(i = 0; i < pr->group_info->ngroups; ++i)
-               cr.cr_groups[i] = GROUP_AT(pr->group_info, i);
-}
+       get_group_info(pr->group_info);
+       cr.cr_group_info = pr->group_info;
 #else
        cr.cr_ngroups = pr->ngroups;
        memcpy(cr.cr_groups, pr->groups, NGROUPS * sizeof(gid_t));
index db1e7b4..3d8a8bb 100644 (file)
@@ -450,25 +450,27 @@ PagInCred(const struct AFS_UCRED *cred)
     g0 = cred->cr_groups[1];
     g1 = cred->cr_groups[2];
 #else
-#ifdef AFS_AIX_ENV
-#ifdef AFS_AIX51_ENV
+#if defined(AFS_AIX51_ENV)
     if (kcred_getpag(cred, PAG_AFS, &pag) < 0 || pag == 0)
        pag = NOPAG;
     return pag;
-#else
+#elif defined(AFS_AIX_ENV)
     if (cred->cr_ngrps < 2) {
        return NOPAG;
     }
-#endif
-#else
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DUX40_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
+#elif defined(AFS_LINUX26_ENV)
+    if (cred->cr_group_info->ngroups < 2)
+       return NOPAG;
+#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DUX40_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
     if (cred->cr_ngroups < 2)
        return NOPAG;
 #endif
-#endif
-#ifdef AFS_AIX51_ENV
+#if defined(AFS_AIX51_ENV)
     g0 = cred->cr_groupset.gs_union.un_groups[0];
     g1 = cred->cr_groupset.gs_union.un_groups[1];
+#elif defined(AFS_LINUX26_ENV)
+    g0 = GROUP_AT(cred->cr_group_info, 0);
+    g1 = GROUP_AT(cred->cr_group_info, 1);
 #else
     g0 = cred->cr_groups[0];
     g1 = cred->cr_groups[1];
index b01641d..18137aa 100644 (file)
@@ -1024,6 +1024,7 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
        ip->i_dev = afs_globalVFS->s_dev;
 #endif
     ip->i_sb = afs_globalVFS;
+    put_inode_on_dummy_list(ip);
 }
 #endif