linux-iput-and-glock-changes-20010130
authorChas Williams <chas@cmf.nrl.navy.mil>
Wed, 31 Jan 2001 02:28:11 +0000 (02:28 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 31 Jan 2001 02:28:11 +0000 (02:28 +0000)
". 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
src/afs/LINUX/osi_misc.c
src/afs/LINUX/osi_vfsops.c
src/afs/LINUX/osi_vnodeops.c

index 7f3ed0f..8571795 100644 (file)
@@ -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);
     }
index 1478be6..e40af34 100644 (file)
@@ -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);
     }
 }
index d193958..f471d08 100644 (file)
@@ -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)
index e322a9f..960d54c 100644 (file)
@@ -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;