diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-10-18 17:14:45 -0400 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-11-06 18:32:00 -0500 |
commit | 9ea2d32f40434589ea0e136373f7d1545afb411f (patch) | |
tree | 2bc258fcaae4769a7b41ae71725eb073de33aded | |
parent | 9f70968af3e6e21612e06e153aa71c62dee5a09b (diff) |
ocfs2: Commit journal on sync writes
We're missing a meta data commit for extending sync writes. In thoery, write
could return with the meta data required to read the data uncommitted to
disk. Fix that by detecting an allocating write and forcing a journal commit
in the sync case.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
-rw-r--r-- | fs/ocfs2/file.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f92fe91ff260..bbac7cd33e0b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1891,9 +1891,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
1891 | ssize_t written = 0; | 1891 | ssize_t written = 0; |
1892 | size_t ocount; /* original count */ | 1892 | size_t ocount; /* original count */ |
1893 | size_t count; /* after file limit checks */ | 1893 | size_t count; /* after file limit checks */ |
1894 | loff_t *ppos = &iocb->ki_pos; | 1894 | loff_t old_size, *ppos = &iocb->ki_pos; |
1895 | u32 old_clusters; | ||
1895 | struct file *file = iocb->ki_filp; | 1896 | struct file *file = iocb->ki_filp; |
1896 | struct inode *inode = file->f_path.dentry->d_inode; | 1897 | struct inode *inode = file->f_path.dentry->d_inode; |
1898 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1897 | 1899 | ||
1898 | mlog_entry("(0x%p, %u, '%.*s')\n", file, | 1900 | mlog_entry("(0x%p, %u, '%.*s')\n", file, |
1899 | (unsigned int)nr_segs, | 1901 | (unsigned int)nr_segs, |
@@ -1949,6 +1951,13 @@ relock: | |||
1949 | goto relock; | 1951 | goto relock; |
1950 | } | 1952 | } |
1951 | 1953 | ||
1954 | /* | ||
1955 | * To later detect whether a journal commit for sync writes is | ||
1956 | * necessary, we sample i_size, and cluster count here. | ||
1957 | */ | ||
1958 | old_size = i_size_read(inode); | ||
1959 | old_clusters = OCFS2_I(inode)->ip_clusters; | ||
1960 | |||
1952 | /* communicate with ocfs2_dio_end_io */ | 1961 | /* communicate with ocfs2_dio_end_io */ |
1953 | ocfs2_iocb_set_rw_locked(iocb, rw_level); | 1962 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
1954 | 1963 | ||
@@ -1978,6 +1987,21 @@ out_dio: | |||
1978 | /* buffered aio wouldn't have proper lock coverage today */ | 1987 | /* buffered aio wouldn't have proper lock coverage today */ |
1979 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); | 1988 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); |
1980 | 1989 | ||
1990 | if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { | ||
1991 | /* | ||
1992 | * The generic write paths have handled getting data | ||
1993 | * to disk, but since we don't make use of the dirty | ||
1994 | * inode list, a manual journal commit is necessary | ||
1995 | * here. | ||
1996 | */ | ||
1997 | if (old_size != i_size_read(inode) || | ||
1998 | old_clusters != OCFS2_I(inode)->ip_clusters) { | ||
1999 | ret = journal_force_commit(osb->journal->j_journal); | ||
2000 | if (ret < 0) | ||
2001 | written = ret; | ||
2002 | } | ||
2003 | } | ||
2004 | |||
1981 | /* | 2005 | /* |
1982 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2006 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
1983 | * function pointer which is called when o_direct io completes so that | 2007 | * function pointer which is called when o_direct io completes so that |