Commit 9ea2d32f40434589ea0e136373f7d1545afb411f

Authored by Mark Fasheh
1 parent 9f70968af3

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>

Showing 1 changed file with 25 additions and 1 deletions Side-by-side Diff

... ... @@ -1891,9 +1891,11 @@
1891 1891 ssize_t written = 0;
1892 1892 size_t ocount; /* original count */
1893 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 1896 struct file *file = iocb->ki_filp;
1896 1897 struct inode *inode = file->f_path.dentry->d_inode;
  1898 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1897 1899  
1898 1900 mlog_entry("(0x%p, %u, '%.*s')\n", file,
1899 1901 (unsigned int)nr_segs,
... ... @@ -1949,6 +1951,13 @@
1949 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 1961 /* communicate with ocfs2_dio_end_io */
1953 1962 ocfs2_iocb_set_rw_locked(iocb, rw_level);
1954 1963  
... ... @@ -1977,6 +1986,21 @@
1977 1986 out_dio:
1978 1987 /* buffered aio wouldn't have proper lock coverage today */
1979 1988 BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
  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 + }
1980 2004  
1981 2005 /*
1982 2006 * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io