[1649] in SIPB_Linux_Development

home help back first fref pref prev next nref lref last post

revised patch to (hopefully) fix and/or find afs cache corruption

daemon@ATHENA.MIT.EDU (Erik Nygren)
Wed Apr 9 21:15:19 1997

To: linux-dev@MIT.EDU, linux-afs-bugs@MIT.EDU
Date: Wed, 09 Apr 1997 21:13:33 EDT
From: Erik Nygren <nygren@MIT.EDU>


Here's a revised version of Ted's patch.  It fixes one case not
covered by Ted's patch and it also logs debugging messages
when corruption could have occurred.  This patch should be applied
to a 2.0.29 kernel.  Make sure your cache is on a partition with enough
space!  As soon as Ted and Derek look this over and say it looks
sane, people should start trying this out (and we should put it
on cutter and lola).  Any syslog messages containing the
string "inode" should be mailed to linux-afs-bugs and/or linux-dev.

	Erik

--- fs/inode.c.2.0.29	Wed Apr  9 19:51:26 1997
+++ fs/inode.c	Wed Apr  9 20:42:05 1997
@@ -13,6 +13,7 @@
 #include <asm/system.h>
 
 #define NR_IHASH 512
+#define AFS_CACHE_CORRUPTION_DEBUG
 
 /*
  * Be VERY careful when you access the inode hash table. There
@@ -147,7 +148,17 @@
 
 static inline void lock_inode(struct inode * inode)
 {
-	wait_on_inode(inode);
+#ifdef AFS_CACHE_CORRUPTION_DEBUG
+  if (inode->i_lock) 
+    {
+      wait_on_inode(inode);
+      if (inode->i_lock)
+	printk("VFS: would have had consistency problem in lock_inode dev %s nr %lu\n",
+	       kdevname(inode->i_dev), inode->i_ino);
+    }
+#endif
+	while (inode->i_lock)  /* I'm pretty sure this while isn't needed */
+		wait_on_inode(inode);
 	inode->i_lock = 1;
 }
 
@@ -173,8 +184,13 @@
 {
 	struct wait_queue * wait;
 
+#ifdef AFS_CACHE_CORRUPTION_DEBUG
+	if (inode->i_lock)
+	  printk("VFS: inode already locked in clear_inode with dev %s nr %lu\n",
+		 kdevname(inode->i_dev), inode->i_ino);
+#endif
+	lock_inode(inode);
 	truncate_inode_pages(inode, 0);
-	wait_on_inode(inode);
 	if (IS_WRITABLE(inode)) {
 		if (inode->i_sb && inode->i_sb->dq_op)
 			inode->i_sb->dq_op->drop(inode);
@@ -186,6 +202,7 @@
 		nr_free_inodes++;
 	memset(inode,0,sizeof(*inode));
 	((volatile struct inode *) inode)->i_wait = wait;
+	wake_up(&inode->i_wait);  /* The memset clears the lock (???) */
 	insert_inode_free(inode);
 }
 
@@ -251,7 +268,12 @@
 		inode->i_dirt = 0;
 		return;
 	}
-	inode->i_lock = 1;	
+#ifdef AFS_CACHE_CORRUPTION_DEBUG
+	if (inode->i_lock)
+	  printk("VFS: inode already locked in write_inode dev %s nr %lu\n",
+	       kdevname(inode->i_dev), inode->i_ino);
+#endif
+	inode->i_lock = 1;/* lock_inode would be cleaner but not needed here */
 	inode->i_sb->s_op->write_inode(inode);
 	unlock_inode(inode);
 }
@@ -457,7 +479,12 @@
 			/* Here we can sleep also. Let's do it again
 			 * Dmitry Gorodchanin 02/11/96 
 			 */
-			inode->i_lock = 1;
+#ifdef AFS_CACHE_CORRUPTION_DEBUG
+		        if (inode->i_lock)
+			  printk("VFS: inode already locked in iput dev %s nr %lu\n",
+				 kdevname(inode->i_dev), inode->i_ino);
+#endif
+			lock_inode(inode);  /* I bet the problem was here */
 			inode->i_sb->dq_op->drop(inode);
 			unlock_inode(inode);
 			goto repeat;
@@ -512,6 +539,13 @@
 		sleep_on(&inode_wait);
 		goto repeat;
 	}
+found_good:  /* The poor location of this could also have caused problems */
+#ifdef AFS_CACHE_CORRUPTION_DEBUG
+	if (best->i_lock)
+	  printk("VFS: inode locked in get_empty_inode dev %s nr %lu\n",
+		 kdevname(inode->i_dev), inode->i_ino);
+#endif
+
 	if (best->i_lock) {
 		wait_on_inode(best);
 		goto repeat;
@@ -522,7 +556,7 @@
 	}
 	if (best->i_count)
 		goto repeat;
-found_good:
+	
 	clear_inode(best);
 	best->i_count = 1;
 	best->i_nlink = 1;


home help back first fref pref prev next nref lref last post