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
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
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
#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);
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;
afile->inum = ainode; /* for hint validity checking */
return (void *)afile;
}
-#endif
-
-#if !defined(HAS_UFSOPEN)
+#else
void *
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);
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);
}
}
#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.
/* 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)
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;
#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;
init_module(void)
#endif
{
- int e;
+ int err;
RWLOCK_INIT(&afs_xosi, "afs_xosi");
#if !defined(AFS_LINUX24_ENV)
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
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
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);
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_ */
/*
* 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
#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
#define VSUID S_ISUID
#define VSGID S_ISGID
-
#define vfs super_block
typedef struct vattr {
#define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
-
-#define vnodeops inode_operations
-
#endif /* OSI_VFS_H_ */
/* 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);
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
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. */
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);
}
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
}
}
-/* 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.
*/
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);
-}
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)
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);
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 */
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
}
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
}
#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;
{
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;
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;
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;
if (!vmap->vm_file)
return;
- vcp = ITOAFS(FILE_INODE(vmap->vm_file));
+ vcp = VTOAFS(FILE_INODE(vmap->vm_file));
if (!vcp)
return;
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;
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();
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;
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
{
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();
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. */
* 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;
* 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();
}
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
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
* 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;
#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
* 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:
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;
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
};
/**********************************************************************
*
* 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
/* 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();
#endif
}
-int
+static int
afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
{
int code;
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();
} 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);
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);
}
AFS_GLOCK();
- code = afs_remove(ITOAFS(dip), name, credp);
+ code = afs_remove(VTOAFS(dip), name, credp);
AFS_GUNLOCK();
if (!code)
d_drop(dp);
}
-int
+static int
afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
{
int code;
*/
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;
#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();
return -code;
}
-int
+static int
afs_linux_rmdir(struct inode *dip, struct dentry *dp)
{
int code;
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
}
-
-int
+static int
afs_linux_rename(struct inode *oldip, struct dentry *olddp,
struct inode *newip, struct dentry *newdp)
{
#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)
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)
/* 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;
/* 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)
{
/* 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;
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)
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;
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 >
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;
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,
}
#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,
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,
};
#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,
* 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
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)
.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) */
+}
#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;
}
* 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) {
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;
* 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
#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;
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
#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;
* 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) : \
#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
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
/*
* 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
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))
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);
#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 */
/* 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;
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);
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:
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
* 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;
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) {
}
}
+#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 ???? */
tvc = nvc;
tvc->nextfree = NULL;
+#endif
afs_vcount++;
#else /* AFS_OSF_ENV */
/* pull out a free cache entry */
} 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)
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;
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 */
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 */
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 */
ObtainWriteLock(&tvc->lock, 54);
if (tvc->states & CStatd) {
-#ifdef AFS_LINUX22_ENV
- vcache2inode(tvc);
-#endif
ReleaseWriteLock(&tvc->lock);
return tvc;
}
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 */
{
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 */
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);
pin((char *)tvp, astatSize * sizeof(struct vcache)); /* XXX */
#endif
#endif
-#endif
#if defined(AFS_SGI_ENV)
for (i = 0; i < astatSize; i++) {
}
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");
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
])
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"])
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