Re: 2.1.76 oops

Bill Hawes (whawes@star.net)
Thu, 01 Jan 1998 12:38:30 -0500


This is a multi-part message in MIME format.
--------------5D7ED10493BC861F5C53474B
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Ben Woodard wrote:
> I got a series of oopses while running an unpatched version of
> 2.1.76. They all seem to be in exactly the same place. The problem seemed to > arise after I unsuspened my computer.

I posted a patch a while back to try to track down these dcache errors
-- the problem is that the oops occurs long after whatever operation
caused the problem.

It would help if you could apply the attached patch and try to replicate
the problem. Then if one of the messages shows up, make a note of
whatever you were doing in the preceeding few seconds.

Regards,
Bill
--------------5D7ED10493BC861F5C53474B
Content-Type: text/plain; charset=us-ascii; name="dcheck-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="dcheck-patch"

--- fs/dcache.c.old Mon Dec 1 11:14:13 1997
+++ fs/dcache.c Sun Dec 14 19:32:27 1997
@@ -411,6 +411,63 @@
}

/*
+ * Check that the unused dentry list is valid.
+ */
+void verify_list(void)
+{
+ struct list_head *tmp, *next, *prev;
+ struct dentry *dentry;
+ struct inode *inode;
+ unsigned long memstart = PAGE_OFFSET;
+ unsigned long memmax = PAGE_OFFSET + (num_physpages << PAGE_SHIFT);
+ unsigned long align_mask = ~0x3;
+ unsigned long addr;
+
+ prev = &dentry_unused;
+ for (tmp = dentry_unused.next; tmp != &dentry_unused; tmp = next) {
+
+ addr = (unsigned long) tmp;
+ if (addr < memstart || addr > memmax)
+ goto bad;
+ if ((addr & align_mask) != addr)
+ goto bad;
+ if (prev != tmp->prev)
+ goto bad_prev;
+ next = tmp->next;
+ prev = tmp;
+ dentry = list_entry(tmp, struct dentry, d_lru);
+ inode = dentry->d_inode;
+ if (!inode)
+ continue;
+ addr = (unsigned long) inode;
+ if (addr < memstart || addr > memmax)
+ goto bad_inode;
+ if ((addr & align_mask) != addr)
+ goto bad_inode;
+ if (inode->i_sb != dentry->d_sb)
+ goto bad_sb;
+ if (!inode->i_count || inode->i_count > 50)
+ goto bad_count;
+ }
+ return;
+bad:
+ printk("VFS: dentry list corrupt, addr=%08lx\n", addr);
+ return;
+bad_prev:
+ printk("VFS: bad prev pointer in dentry list, prev=%p\n", prev);
+ return;
+bad_inode:
+ printk("VFS: dentry has bad inode pointer, addr=%08lx\n", addr);
+ return;
+bad_sb:
+ printk("VFS: dentry superblock mismatch\n");
+ return;
+bad_count:
+ printk("VFS: bad count for in-use inode, count=%d\n", inode->i_count);
+ return;
+}
+
+/*
* This is called from do_try_to_free_page() to indicate
* that we should reduce the dcache and inode cache memory.
*/
@@ -424,6 +481,13 @@
*/
void check_dcache_memory()
{
+ static unsigned long next_check = 0;
+
+ if (jiffies > next_check) {
+ next_check = jiffies + 2*HZ;
+ verify_list();
+ }
+
if (dentry_stat.want_pages) {
unsigned int count, goal = 0;
/*
@@ -679,6 +743,8 @@
{
if (!dentry->d_inode)
printk(KERN_WARNING "VFS: moving negative dcache entry\n");
+ if (list_empty(&target->d_hash))
+ printk(KERN_WARNING "VFS: unhashed target\n");

/* Move the dentry to the target hash queue */
list_del(&dentry->d_hash);

--------------5D7ED10493BC861F5C53474B--