Skip to content

Commit

Permalink
[PATCH] fat: Fix truncate() write ordering
Browse files Browse the repository at this point in the history
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: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
OGAWA Hirofumi authored and Linus Torvalds committed Feb 3, 2006
1 parent e60e5c5 commit 3b64140
Showing 1 changed file with 23 additions and 27 deletions.
50 changes: 23 additions & 27 deletions fs/fat/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 3b64140

Please sign in to comment.