diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 9f1a40e7945c..8f0fd726c3f1 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -116,6 +116,7 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned); /* inode.c */ extern void ext2_read_inode (struct inode *); extern int ext2_write_inode (struct inode *, int); +extern void ext2_put_inode (struct inode *); extern void ext2_delete_inode (struct inode *); extern int ext2_sync_inode (struct inode *); extern void ext2_discard_prealloc (struct inode *); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index b890be022496..a50d9db4b6e4 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -52,6 +52,19 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode) inode->i_blocks - ea_blocks == 0); } +/* + * 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) +{ + if (!is_bad_inode(inode)) + ext2_discard_prealloc(inode); +} + /* * Called at the last iput() if i_nlink is zero. */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 37ca77a157ba..661c3d98d946 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -198,11 +198,8 @@ static void ext2_clear_inode(struct inode *inode) ei->i_default_acl = EXT2_ACL_NOT_CACHED; } #endif - if (!is_bad_inode(inode)) - ext2_discard_prealloc(inode); } - #ifdef CONFIG_QUOTA static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); @@ -213,6 +210,7 @@ static struct super_operations ext2_sops = { .destroy_inode = ext2_destroy_inode, .read_inode = ext2_read_inode, .write_inode = ext2_write_inode, + .put_inode = ext2_put_inode, .delete_inode = ext2_delete_inode, .put_super = ext2_put_super, .write_super = ext2_write_super,