From 5293aa35617a6ad35980ce16fdf492ea960cc18a Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Wed, 31 Jan 2001 02:28:11 +0000 Subject: [PATCH] linux-iput-and-glock-changes-20010130 ". afs_dentry_iput is essentially osi_iput, so it now calls osi_iput it wasnt locking before checking i_count (and osi_iput didnt either) osi_iput now AFS_GLOCK's. to do this afs_delete_inode was split into afs_delete_inode (which does the locking) and osi_clear_inode before osi_iput called afs_delete_inode, which since it wanted to hold AFS_GLOCK, osi_iput couldnt call AFS_GLOCK. this seems to have cured the problem i saw (running multiple 'ls -R &' would cause a bad iput w/o fail) and i hope it fixes it otherwise. its possible vc->lock should be held inside osi_clear_inode. . removed osi_notify_change (i added during 2.4.0 development) and now i just call inode_change_ok/inode_setattr. the 2.4.0 notify_change checks the dentry parent (which doenst exist for the cache inodes) . moved the locks around inside writepage, writepage_sync, commit_write. the guy next door complained about pauses while running afs. i think this addresses those issues. apparently you only need to lock_kernel() during commit_write(). in order to get lock_kernel() inside AFS_GLOCK() the AFS_GLOCK() was moved out of writepage_sync and into writepage and commit_write" --- src/afs/LINUX/osi_file.c | 42 +++++++++-------------------------- src/afs/LINUX/osi_misc.c | 32 ++++++++++++++++++++++++--- src/afs/LINUX/osi_vfsops.c | 24 +++----------------- src/afs/LINUX/osi_vnodeops.c | 43 +++++++++++------------------------- 4 files changed, 55 insertions(+), 86 deletions(-) diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c index 7f3ed0ffc..8571795cc 100644 --- a/src/afs/LINUX/osi_file.c +++ b/src/afs/LINUX/osi_file.c @@ -104,33 +104,6 @@ osi_UFSClose(afile) return 0; } -#if defined(AFS_LINUX24_ENV) -int osi_notify_change(struct dentry * dentry, struct iattr * attr) -{ - struct inode *inode = dentry->d_inode; - int error; - time_t now = CURRENT_TIME; - unsigned int ia_valid = attr->ia_valid; - - attr->ia_ctime = now; - if (!(ia_valid & ATTR_ATIME_SET)) - attr->ia_atime = now; - if (!(ia_valid & ATTR_MTIME_SET)) - attr->ia_mtime = now; - - lock_kernel(); - if (inode && inode->i_op && inode->i_op->setattr) - error = inode->i_op->setattr(dentry, attr); - else { - error = inode_change_ok(inode, attr); - if (!error) - inode_setattr(inode, attr); - } - unlock_kernel(); - return error; -} -#endif - osi_UFSTruncate(afile, asize) register struct osi_file *afile; afs_int32 asize; { @@ -150,13 +123,18 @@ osi_UFSTruncate(afile, asize) MObtainWriteLock(&afs_xosi,321); AFS_GUNLOCK(); down(&inode->i_sem); -#if defined(AFS_LINUX24_ENV) - newattrs.ia_size = asize; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - code = osi_notify_change(&afile->dentry, &newattrs); -#else inode->i_size = newattrs.ia_size = asize; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; +#if defined(AFS_LINUX24_ENV) + newattrs.ia_ctime = CURRENT_TIME; + + /* avoid notify_change() since it wants to update dentry->d_parent */ + lock_kernel(); + code = inode_change_ok(inode, &newattrs); + if (!code) + inode_setattr(inode, &newattrs); + unlock_kernel(); +#else if (inode->i_sb->s_op && inode->i_sb->s_op->notify_change) { code = inode->i_sb->s_op->notify_change(&afile->dentry, &newattrs); } diff --git a/src/afs/LINUX/osi_misc.c b/src/afs/LINUX/osi_misc.c index 1478be6a9..e40af34af 100644 --- a/src/afs/LINUX/osi_misc.c +++ b/src/afs/LINUX/osi_misc.c @@ -15,6 +15,9 @@ #include "../afs/sysincludes.h" #include "../afs/afsincludes.h" #include "../afs/afs_stats.h" +#if defined(AFS_LINUX24_ENV) +#include "../h/smp_lock.h" +#endif char *crash_addr = 0; /* Induce an oops by writing here. */ @@ -313,16 +316,37 @@ void osi_linux_free_inode_pages(void) } } +void osi_clear_inode(struct inode *ip) +{ + cred_t *credp = crref(); + struct vcache *vc = (struct vcache*)ip; + +#if defined(AFS_LINUX24_ENV) + if (atomic_read(&ip->i_count) > 1) +#else + if (ip->i_count > 1) +#endif + printf("afs_put_inode: ino %d (0x%x) has count %d\n", ip->i_ino, ip); + + afs_InactiveVCache(vc, credp); +#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. */ + 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 void afs_delete_inode(struct inode *ip); extern struct vfs *afs_globalVFS; - + AFS_GLOCK(); #if defined(AFS_LINUX24_ENV) if (atomic_read(&ip->i_count) == 0 || atomic_read(&ip->i_count) & 0xffff0000) { #else @@ -343,9 +367,11 @@ void osi_iput(struct inode *ip) ip->i_count --; if (!ip->i_count) #endif - afs_delete_inode(ip); + osi_clear_inode(ip); + AFS_GUNLOCK(); } else { + AFS_GUNLOCK(); iput(ip); } } diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c index d1939581a..f471d0819 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -231,37 +231,19 @@ void afs_write_inode(struct inode *ip) * 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_delete_inode(struct inode *ip) { - cred_t *credp = crref(); struct vcache *vc = (struct vcache*)ip; AFS_GLOCK(); -#if defined(AFS_LINUX24_ENV) - lock_kernel(); - if (atomic_read(&ip->i_count) > 1) -#else - if (ip->i_count > 1) -#endif - printf("afs_put_inode: ino %d (0x%x) has count %d\n", ip->i_ino, ip); - ObtainWriteLock(&vc->lock, 504); - afs_InactiveVCache(vc, credp); -#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. */ + osi_clear_inode(ip); ReleaseWriteLock(&vc->lock); - -#ifdef AFS_LINUX24_ENV - unlock_kernel(); -#endif AFS_GUNLOCK(); - crfree(credp); } + /* afs_put_super * Called from unmount to release super_block. */ void afs_put_super(struct super_block *sbp) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index e322a9f06..960d54c36 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -715,27 +715,7 @@ static int afs_linux_dentry_revalidate(struct dentry *dp) /* afs_dentry_iput */ static void afs_dentry_iput(struct dentry *dp, struct inode *ip) { -#if defined(AFS_LINUX24_ENV) - if (atomic_read(&ip->i_count) == 0 || atomic_read(&ip->i_count) & 0xffff0000) { -#else - if (ip->i_count == 0 || ip->i_count & 0xffff0000) { -#endif - osi_Panic("Bad refCount %d on inode 0x%x\n", -#if defined(AFS_LINUX24_ENV) - atomic_read(&ip->i_count), ip); -#else - ip->i_count, ip); -#endif - } -#if defined(AFS_LINUX24_ENV) - atomic_dec(&ip->i_count); - if (!atomic_read(&ip->i_count)) { -#else - ip->i_count --; - if (!ip->i_count) { -#endif - afs_delete_inode(ip); - } + osi_iput(ip); } #if defined(AFS_LINUX24_ENV) @@ -1146,11 +1126,11 @@ int afs_linux_readpage(struct file *fp, struct page *pp) setup_uio(&tuio, &iovec, (char*)address, pageoff(pp), PAGESIZE, UIO_READ, AFS_UIOSYS); #endif -#ifdef AFS_LINUX24_ENV +#if defined(AFS_LINUX24_ENV) lock_kernel(); #endif code = afs_rdwr((struct vcache*)ip, &tuio, UIO_READ, 0, credp); -#ifdef AFS_LINUX24_ENV +#if defined(AFS_LINUX24_ENV) unlock_kernel(); #endif @@ -1159,6 +1139,9 @@ int afs_linux_readpage(struct file *fp, struct page *pp) memset((void*)(address+(PAGESIZE-tuio.uio_resid)), 0, tuio.uio_resid); #if defined(AFS_LINUX24_ENV) +#ifndef __powerpc__ + flush_dcache_page(pp); +#endif SetPageUptodate(pp); #else set_bit(PG_uptodate, &pp->flags); @@ -1169,8 +1152,8 @@ int afs_linux_readpage(struct file *fp, struct page *pp) UnlockPage(pp); #else clear_bit(PG_locked, &pp->flags); -#endif wake_up(&pp->wait); +#endif free_page(address); crfree(credp); @@ -1204,7 +1187,9 @@ int afs_linux_writepage(struct page *pp) if (pp->index >= end_index+1 || !offset) return -EIO; do_it: + AFS_GLOCK(); status = afs_linux_writepage_sync(inode, pp, 0, offset); + AFS_GUNLOCK(); SetPageUptodate(pp); UnlockPage(pp); /* kunmap(pp); */ @@ -1268,8 +1253,6 @@ int afs_linux_writepage_sync(struct inode *ip, struct page *pp, int f_flags = 0; credp = crref(); - AFS_GLOCK(); - lock_kernel(); afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, atomic_read(&pp->count), @@ -1288,8 +1271,6 @@ int afs_linux_writepage_sync(struct inode *ip, struct page *pp, ICL_TYPE_INT32, atomic_read(&pp->count), ICL_TYPE_INT32, code); - unlock_kernel(); - AFS_GUNLOCK(); crfree(credp); return code; @@ -1354,9 +1335,11 @@ static int afs_linux_commit_write(struct file *file, struct page *page, unsigned { long status; - /* lock_kernel(); */ + AFS_GLOCK(); + lock_kernel(); status = afs_linux_updatepage(file, page, offset, to-offset); - /* unlock_kernel(); */ + unlock_kernel(); + AFS_GUNLOCK(); kunmap(page); return status; -- 2.39.5