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

[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
...@@ -210,10 +210,30 @@ static int fat_free(struct inode *inode, int skip) ...@@ -210,10 +210,30 @@ static int fat_free(struct inode *inode, int skip)
if (MSDOS_I(inode)->i_start == 0) if (MSDOS_I(inode)->i_start == 0)
return 0; return 0;
/* fat_cache_inval_inode(inode);
* Write a new EOF, and get the remaining cluster chain for freeing.
*/
wait = IS_DIRSYNC(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) { if (skip) {
struct fat_entry fatent; struct fat_entry fatent;
int ret, fclus, dclus; int ret, fclus, dclus;
...@@ -244,35 +264,11 @@ static int fat_free(struct inode *inode, int skip) ...@@ -244,35 +264,11 @@ static int fat_free(struct inode *inode, int skip)
return ret; return ret;
free_start = 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); inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
/* Freeing the remained cluster chain */ /* Freeing the remained cluster chain */
return fat_free_clusters(inode, free_start); 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) void fat_truncate(struct inode *inode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment