--- /dev/null
+--- linux-2.6.18-128.7.1.orig/include/linux/ext3_fs.h 2006-09-19 23:42:06.000000000 -0400
++++ linux-2.6.18-128.7.1/include/linux/ext3_fs.h 2009-10-12 19:37:54.000000000 -0400
+@@ -809,6 +809,7 @@ extern void ext3_discard_reservation (st
+ extern void ext3_dirty_inode(struct inode *);
+ extern int ext3_change_inode_journal_flag(struct inode *, int);
+ extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
++extern int ext3_can_truncate(struct inode *inode);
+ extern void ext3_truncate (struct inode *);
+ extern void ext3_set_inode_flags(struct inode *);
+ extern void ext3_set_aops(struct inode *inode);
+--- linux-2.6.18-128.7.1.orig/fs/ext3/inode.c 2009-09-15 10:38:31.000000000 -0400
++++ linux-2.6.18-128.7.1/fs/ext3/inode.c 2009-10-12 18:49:01.000000000 -0400
+@@ -2194,6 +2194,19 @@ static void ext3_free_branches(handle_t
+ }
+ }
+
++int ext3_can_truncate(struct inode *inode)
++{
++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
++ return 0;
++ if (S_ISREG(inode->i_mode))
++ return 1;
++ if (S_ISDIR(inode->i_mode))
++ return 1;
++ if (S_ISLNK(inode->i_mode))
++ return !ext3_inode_is_fast_symlink(inode);
++ return 0;
++}
++
+ /*
+ * ext3_truncate()
+ *
+@@ -2238,12 +2251,7 @@ void ext3_truncate(struct inode *inode)
+ unsigned blocksize = inode->i_sb->s_blocksize;
+ struct page *page;
+
+- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+- S_ISLNK(inode->i_mode)))
+- return;
+- if (ext3_inode_is_fast_symlink(inode))
+- return;
+- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
++ if (!ext3_can_truncate(inode))
+ return;
+
+ /*
+--- linux-2.6.18-128.7.1.orig/fs/ext3/ialloc.c 2009-09-15 10:24:17.000000000 -0400
++++ linux-2.6.18-128.7.1/fs/ext3/ialloc.c 2009-10-14 15:36:27.000000000 -0400
+@@ -645,54 +645,71 @@ struct inode *ext3_orphan_get(struct sup
+ unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
+ unsigned long block_group;
+ int bit;
+- struct buffer_head *bitmap_bh = NULL;
++ struct buffer_head *bitmap_bh;
+ struct inode *inode = NULL;
+
+ /* Error cases - e2fsck has already cleaned up for us */
+ if (ino > max_ino) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "bad orphan ino %lu! e2fsck was run?", ino);
+- goto out;
++ goto error;
+ }
+
+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+ bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb);
+ bitmap_bh = read_inode_bitmap(sb, block_group);
+ if (!bitmap_bh) {
+- ext3_warning(sb, __FUNCTION__,
++ ext3_warning(sb, __func__,
+ "inode bitmap error for orphan %lu", ino);
+- goto out;
++ goto error;
+ }
+
+ /* Having the inode bit set should be a 100% indicator that this
+ * is a valid orphan (no e2fsck run on fs). Orphans also include
+ * inodes that were being truncated, so we can't check i_nlink==0.
+ */
+- if (!ext3_test_bit(bit, bitmap_bh->b_data) ||
+- !(inode = iget(sb, ino)) || is_bad_inode(inode) ||
+- NEXT_ORPHAN(inode) > max_ino) {
+- ext3_warning(sb, __FUNCTION__,
+- "bad orphan inode %lu! e2fsck was run?", ino);
+- printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
+- bit, (unsigned long long)bitmap_bh->b_blocknr,
+- ext3_test_bit(bit, bitmap_bh->b_data));
+- printk(KERN_NOTICE "inode=%p\n", inode);
+- if (inode) {
+- printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
+- is_bad_inode(inode));
+- printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
+- NEXT_ORPHAN(inode));
+- printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+- }
++ if (!ext3_test_bit(bit, bitmap_bh->b_data))
++ goto bad_orphan;
++
++ inode = iget(sb, ino);
++ if ((inode == NULL) || is_bad_inode(inode))
++ goto bad_orphan;
++
++ /*
++ * If the orphan has i_nlinks > 0 then it should be able to be
++ * truncated, otherwise it won't be removed from the orphan list
++ * during processing and an infinite loop will result.
++ */
++ if (inode->i_nlink && !ext3_can_truncate(inode))
++ goto bad_orphan;
++
++ if (NEXT_ORPHAN(inode) > max_ino)
++ goto bad_orphan;
++ brelse(bitmap_bh);
++ return inode;
++
++bad_orphan:
++ ext3_warning(sb, __func__,
++ "bad orphan inode %lu! e2fsck was run?", ino);
++ printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
++ bit, (unsigned long long)bitmap_bh->b_blocknr,
++ ext3_test_bit(bit, bitmap_bh->b_data));
++ printk(KERN_NOTICE "inode=%p\n", inode);
++ if (inode) {
++ printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
++ is_bad_inode(inode));
++ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
++ NEXT_ORPHAN(inode));
++ printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
++ printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
+ /* Avoid freeing blocks if we got a bad deleted inode */
+- if (inode && inode->i_nlink == 0)
++ if (inode->i_nlink == 0)
+ inode->i_blocks = 0;
+ iput(inode);
+- inode = NULL;
+ }
+-out:
+ brelse(bitmap_bh);
+- return inode;
++error:
++ return NULL;
+ }
+
+ unsigned long ext3_count_free_inodes (struct super_block * sb)