]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] handle bad inodes in put_inode
authorAndrew Morton <akpm@digeo.com>
Thu, 3 Apr 2003 00:26:20 +0000 (16:26 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 3 Apr 2003 00:26:20 +0000 (16:26 -0800)
From: "J. Bruce Fields" <bfields@fieldses.org>

If the NFS daemon is presented with a filehandle for a file that has
been deleted, it does an iget() in fs/exportfs/expfs.c:export_iget() and
gets a bad inode back.  When it subsequently iput()s the inode, the
result is:

Mar 27 12:53:40 snoopy kernel: EXT2-fs error (device ide0(3,3)): ext2_free_blocks: Freeing blocks not in datazone - block = 1802201963, count = 27499
Mar 27 12:53:40 snoopy kernel: Remounting filesystem read-only

The same can happen if ext2_get_inode() returns an error - ext2_read_inode()
will return an uninitialised inode and ext2_put_inode() is not allowed to go
looking inside the bad inode.

fs/ext2/inode.c
fs/ext3/inode.c

index c2fbefdd361323705446d24f4979e5174d000726..cd441a4841ae69b44ad17028fecc3330a19aabf3 100644 (file)
@@ -52,11 +52,16 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
 }
 
 /*
- * Called at each iput()
+ * Called at each iput().
+ *
+ * The inode may be "bad" if ext2_read_inode() saw an error from
+ * ext2_get_inode(), so we need to check that to avoid freeing random disk
+ * blocks.
  */
-void ext2_put_inode (struct inode * inode)
+void ext2_put_inode(struct inode *inode)
 {
-       ext2_discard_prealloc (inode);
+       if (!is_bad_inode(inode))
+               ext2_discard_prealloc(inode);
 }
 
 /*
index e8449407cb607cabf32c46987f9027d057d080a7..c650328fe09f71094aa91e7acb834a8d43c1f4ca 100644 (file)
@@ -178,10 +178,15 @@ static int ext3_journal_test_restart(handle_t *handle, struct inode *inode)
 
 /*
  * Called at each iput()
+ *
+ * The inode may be "bad" if ext3_read_inode() saw an error from
+ * ext3_get_inode(), so we need to check that to avoid freeing random disk
+ * blocks.
  */
-void ext3_put_inode (struct inode * inode)
+void ext3_put_inode(struct inode *inode)
 {
-       ext3_discard_prealloc (inode);
+       if (!is_bad_inode(inode))
+               ext3_discard_prealloc(inode);
 }
 
 /*