diff --git a/src/afs/LINUX/osi_cred.c b/src/afs/LINUX/osi_cred.c index 12a95868ae..9cad7168a7 100644 --- a/src/afs/LINUX/osi_cred.c +++ b/src/afs/LINUX/osi_cred.c @@ -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)); diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c index 1d6b67900d..b0000c4d5f 100644 --- a/src/afs/LINUX/osi_groups.c +++ b/src/afs/LINUX/osi_groups.c @@ -26,10 +26,86 @@ 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; + AFS_STATCNT(afs_setgroups); + + old_info = (*cr)->cr_group_info; + get_group_info(group_info); + (*cr)->cr_group_info = group_info; + put_group_info(old_info); + + crset(*cr); + + if (change_parent) { + old_info = current->parent->group_info; + get_group_info(group_info); + current->parent->group_info = group_info; + put_group_info(old_info); + } + + return (0); +} +#else +static int +afs_setgroups(cred_t **cr, int ngroups, gid_t * gidset, int change_parent) +{ + int ngrps; + int i; + gid_t *gp; + + AFS_STATCNT(afs_setgroups); + + if (ngroups > NGROUPS) + return EINVAL; + + gp = (*cr)->cr_groups; + if (ngroups < NGROUPS) + gp[ngroups] = (gid_t) NOGROUP; + + for (i = ngroups; i > 0; i--) { + *gp++ = *gidset++; + } + + (*cr)->cr_ngroups = ngroups; + crset(*cr); + return (0); +} +#endif + +#if defined(AFS_LINUX26_ENV) +static struct group_info * +afs_getgroups(cred_t * cr) +{ + AFS_STATCNT(afs_getgroups); + + get_group_info(cr->cr_group_info); + return cr->cr_group_info; +} +#else +/* Returns number of groups. And we trust groups to be large enough to + * hold all the groups. + */ +static int +afs_getgroups(cred_t *cr, gid_t *groups) +{ + int i; + AFS_STATCNT(afs_getgroups); + + gid_t *gp = cr->cr_groups; + int n = cr->cr_ngroups; + + for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++) + *groups++ = *gp++; + return i; +} +#endif + +#if !defined(AFS_LINUX26_ENV) /* Only propogate the PAG to the parent process. Unix's propogate to * all processes sharing the cred. */ @@ -37,21 +113,6 @@ int set_pag_in_parent(int pag, int g0, int g1) { int i; -#if defined(AFS_LINUX26_ENV) - struct group_info *old_info, *new_info; - - old_info = current->parent->group_info; - new_info = groups_alloc(old_info->ngroups + 2); - - for(i = 0; i < old_info->ngroups; ++i) - GROUP_AT(new_info, i) = GROUP_AT(old_info, i); - - GROUP_AT(new_info, i++) = g0; - GROUP_AT(new_info, i++) = g1; - - current->parent->group_info = new_info; - put_group_info(old_info); -#else #ifdef STRUCT_TASK_STRUCT_HAS_PARENT gid_t *gp = current->parent->groups; int ngroups = current->parent->ngroups; @@ -79,15 +140,48 @@ set_pag_in_parent(int pag, int g0, int g1) current->parent->ngroups = ngroups; #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; -} diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h index e740c5c8a4..6cd4eb9007 100644 --- a/src/afs/LINUX/osi_machdep.h +++ b/src/afs/LINUX/osi_machdep.h @@ -56,7 +56,19 @@ #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 diff --git a/src/afs/LINUX/osi_misc.c b/src/afs/LINUX/osi_misc.c index 91fc0ce1c4..135429bb56 100644 --- a/src/afs/LINUX/osi_misc.c +++ b/src/afs/LINUX/osi_misc.c @@ -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); } diff --git a/src/afs/LINUX/osi_vfs.hin b/src/afs/LINUX/osi_vfs.hin index 4231a3d32f..87d58fe655 100644 --- a/src/afs/LINUX/osi_vfs.hin +++ b/src/afs/LINUX/osi_vfs.hin @@ -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 diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c index 046da305eb..14c12c441b 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -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 diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 6e3cb80fed..ebefdc89d5 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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; } diff --git a/src/afs/afs_osi.c b/src/afs/afs_osi.c index 6400ed7f76..04065e033a 100644 --- a/src/afs/afs_osi.c +++ b/src/afs/afs_osi.c @@ -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)); diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c index db1e7b45e8..3d8a8bb23a 100644 --- a/src/afs/afs_osi_pag.c +++ b/src/afs/afs_osi_pag.c @@ -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]; diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index b01641d80a..18137aa396 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -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