Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef43618a authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds
Browse files

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: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 6f3f1cb2
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -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);