ext3: make sure inode is deleted from orphan list after truncate

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Thursday, June 18, 2009 - 2:59 pm

Gitweb:     http://git.kernel.org/linus/ef43618a47179b41e7203a624f2c7445e7da488c
Commit:     ef43618a47179b41e7203a624f2c7445e7da488c
Parent:     6f3f1cb21f08fbf757bbbbb0709ee515a7a7c6ad
Author:     Jan Kara <jack@suse.cz>
AuthorDate: Wed Jun 17 16:26:24 2009 -0700
Committer:  Linus Torvalds <torvalds@linux-foundation.org>
CommitDate: Thu Jun 18 13:03:45 2009 -0700

    ext3: make sure inode is deleted from orphan list after truncate
    
    As Ted pointed out, it can happen that ext3_truncate() returns without
    removing inode from orphan list.  This way we could in some rare cases
    (like when we get ENOMEM from an allocation in ext3_truncate called
    because of failed ext3_write_begin) leave the inode on orphan list and
    that triggers assertion failure on umount.
    
    So make ext3_truncate() always remove inode from in-memory orphan list.
    
    Cc: Theodore Ts'o <tytso@mit.edu>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 fs/ext3/inode.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 253c2cd..05dea81 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2374,7 +2374,7 @@ void ext3_truncate(struct inode *inode)
 	struct page *page;
 
 	if (!ext3_can_truncate(inode))
-		return;
+		goto out_notrans;
 
 	if (inode->i_size == 0 && ext3_should_writeback_data(inode))
 		ei->i_state |= EXT3_STATE_FLUSH_ON_CLOSE;
@@ -2390,7 +2390,7 @@ void ext3_truncate(struct inode *inode)
 		page = grab_cache_page(mapping,
 				inode->i_size >> PAGE_CACHE_SHIFT);
 		if (!page)
-			return;
+			goto out_notrans;
 	}
 
 	handle = start_transaction(inode);
@@ -2401,7 +2401,7 @@ void ext3_truncate(struct inode *inode)
 			unlock_page(page);
 			page_cache_release(page);
 		}
-		return;		/* AKPM: return what? */
+		goto out_notrans;
 	}
 
 	last_block = (inode->i_size + blocksize-1)
@@ -2525,6 +2525,14 @@ out_stop:
 		ext3_orphan_del(handle, inode);
 
 	ext3_journal_stop(handle);
+	return;
+out_notrans:
+	/*
+	 * Delete the inode from orphan list so that it doesn't stay there
+	 * forever and trigger assertion on umount.
+	 */
+	if (inode->i_nlink)
+		ext3_orphan_del(NULL, inode);
 }
 
 static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
@@ -3122,12 +3130,6 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 
 	rc = inode_setattr(inode, attr);
 
-	/* If inode_setattr's call to ext3_truncate failed to get a
-	 * transaction handle at all, we need to clean up the in-core
-	 * orphan list manually. */
-	if (inode->i_nlink)
-		ext3_orphan_del(NULL, inode);
-
 	if (!rc && (ia_valid & ATTR_MODE))
 		rc = ext3_acl_chmod(inode);
 
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
ext3: make sure inode is deleted from orphan list after tr ..., Linux Kernel Mailing ..., (Thu Jun 18, 2:59 pm)