diff options
author | Sunil Mushran <sunil.musran@oracle.com> | 2007-08-06 18:11:56 -0400 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-08-09 20:27:10 -0400 |
commit | 480214d71f1972756473415d31953647952400fb (patch) | |
tree | 558ca94278953cc2c01e60a206954d059fda75b1 /fs/ocfs2 | |
parent | 6a18380e7ddd7d1a0493efe3be6475dd92323364 (diff) |
ocfs2: Fix rename/extend race
If one process is extending a file while another is renaming it, there
exists a window when rename could flush the old inode's stale i_size to
disk. This patch recognizes the fact that rename is only updating the old
inode's ctime, so it ensures only that value is flushed to disk.
Signed-off-by: Sunil Mushran <sunil.musran@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/namei.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index d430fdab16e9..701e6d04ed5d 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -1080,6 +1080,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1080 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, | 1080 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, |
1081 | // this is the 1st dirent bh | 1081 | // this is the 1st dirent bh |
1082 | nlink_t old_dir_nlink = old_dir->i_nlink; | 1082 | nlink_t old_dir_nlink = old_dir->i_nlink; |
1083 | struct ocfs2_dinode *old_di; | ||
1083 | 1084 | ||
1084 | /* At some point it might be nice to break this function up a | 1085 | /* At some point it might be nice to break this function up a |
1085 | * bit. */ | 1086 | * bit. */ |
@@ -1354,7 +1355,20 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1354 | 1355 | ||
1355 | old_inode->i_ctime = CURRENT_TIME; | 1356 | old_inode->i_ctime = CURRENT_TIME; |
1356 | mark_inode_dirty(old_inode); | 1357 | mark_inode_dirty(old_inode); |
1357 | ocfs2_mark_inode_dirty(handle, old_inode, old_inode_bh); | 1358 | |
1359 | status = ocfs2_journal_access(handle, old_inode, old_inode_bh, | ||
1360 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1361 | if (status >= 0) { | ||
1362 | old_di = (struct ocfs2_dinode *) old_inode_bh->b_data; | ||
1363 | |||
1364 | old_di->i_ctime = cpu_to_le64(old_inode->i_ctime.tv_sec); | ||
1365 | old_di->i_ctime_nsec = cpu_to_le32(old_inode->i_ctime.tv_nsec); | ||
1366 | |||
1367 | status = ocfs2_journal_dirty(handle, old_inode_bh); | ||
1368 | if (status < 0) | ||
1369 | mlog_errno(status); | ||
1370 | } else | ||
1371 | mlog_errno(status); | ||
1358 | 1372 | ||
1359 | /* now that the name has been added to new_dir, remove the old name */ | 1373 | /* now that the name has been added to new_dir, remove the old name */ |
1360 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); | 1374 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); |