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

Commit 3b641407 authored by OGAWA Hirofumi's avatar OGAWA Hirofumi Committed by Linus Torvalds
Browse files

[PATCH] fat: Fix truncate() write ordering



The truncate() should write the file size before writing the new EOF entry.
This patch fixes it.

This bug was pointed out by Machida Hiroyuki.

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e60e5c50
Loading
Loading
Loading
Loading
+23 −27
Original line number Diff line number Diff line
@@ -210,10 +210,30 @@ static int fat_free(struct inode *inode, int skip)
	if (MSDOS_I(inode)->i_start == 0)
		return 0;

	/*
	 * Write a new EOF, and get the remaining cluster chain for freeing.
	 */
	fat_cache_inval_inode(inode);

	wait = IS_DIRSYNC(inode);
	i_start = free_start = MSDOS_I(inode)->i_start;
	i_logstart = MSDOS_I(inode)->i_logstart;

	/* First, we write the new file size. */
	if (!skip) {
		MSDOS_I(inode)->i_start = 0;
		MSDOS_I(inode)->i_logstart = 0;
	}
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
	if (wait) {
		err = fat_sync_inode(inode);
		if (err) {
			MSDOS_I(inode)->i_start = i_start;
			MSDOS_I(inode)->i_logstart = i_logstart;
			return err;
		}
	} else
		mark_inode_dirty(inode);

	/* Write a new EOF, and get the remaining cluster chain for freeing. */
	if (skip) {
		struct fat_entry fatent;
		int ret, fclus, dclus;
@@ -244,35 +264,11 @@ static int fat_free(struct inode *inode, int skip)
			return ret;

		free_start = ret;
		i_start = i_logstart = 0;
		fat_cache_inval_inode(inode);
	} else {
		fat_cache_inval_inode(inode);

		i_start = free_start = MSDOS_I(inode)->i_start;
		i_logstart = MSDOS_I(inode)->i_logstart;
		MSDOS_I(inode)->i_start = 0;
		MSDOS_I(inode)->i_logstart = 0;
	}
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
	if (wait) {
		err = fat_sync_inode(inode);
		if (err)
			goto error;
	} else
		mark_inode_dirty(inode);
	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);

	/* Freeing the remained cluster chain */
	return fat_free_clusters(inode, free_start);

error:
	if (i_start) {
		MSDOS_I(inode)->i_start = i_start;
		MSDOS_I(inode)->i_logstart = i_logstart;
	}
	return err;
}

void fat_truncate(struct inode *inode)