Commit 6307daad authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2:
  ocfs2: Handle O_DIRECT when writing to a refcounted cluster.
parents f843b0fc 86470e98
...@@ -1772,7 +1772,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1772,7 +1772,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
loff_t *ppos, loff_t *ppos,
size_t count, size_t count,
int appending, int appending,
int *direct_io) int *direct_io,
int *has_refcount)
{ {
int ret = 0, meta_level = 0; int ret = 0, meta_level = 0;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
...@@ -1833,6 +1834,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1833,6 +1834,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
saved_pos, saved_pos,
count, count,
&meta_level); &meta_level);
if (has_refcount)
*has_refcount = 1;
} }
if (ret < 0) { if (ret < 0) {
...@@ -1856,6 +1859,10 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1856,6 +1859,10 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
break; break;
} }
if (has_refcount && *has_refcount == 1) {
*direct_io = 0;
break;
}
/* /*
* Allowing concurrent direct writes means * Allowing concurrent direct writes means
* i_size changes wouldn't be synchronized, so * i_size changes wouldn't be synchronized, so
...@@ -1899,7 +1906,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -1899,7 +1906,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
loff_t pos) loff_t pos)
{ {
int ret, direct_io, appending, rw_level, have_alloc_sem = 0; int ret, direct_io, appending, rw_level, have_alloc_sem = 0;
int can_do_direct; int can_do_direct, has_refcount = 0;
ssize_t written = 0; ssize_t written = 0;
size_t ocount; /* original count */ size_t ocount; /* original count */
size_t count; /* after file limit checks */ size_t count; /* after file limit checks */
...@@ -1942,7 +1949,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -1942,7 +1949,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
can_do_direct = direct_io; can_do_direct = direct_io;
ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos, ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos,
iocb->ki_left, appending, iocb->ki_left, appending,
&can_do_direct); &can_do_direct, &has_refcount);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -2006,14 +2013,16 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -2006,14 +2013,16 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
/* buffered aio wouldn't have proper lock coverage today */ /* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) { if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode) ||
(file->f_flags & O_DIRECT && has_refcount)) {
ret = filemap_fdatawrite_range(file->f_mapping, pos, ret = filemap_fdatawrite_range(file->f_mapping, pos,
pos + count - 1); pos + count - 1);
if (ret < 0) if (ret < 0)
written = ret; written = ret;
if (!ret && (old_size != i_size_read(inode) || if (!ret && (old_size != i_size_read(inode) ||
old_clusters != OCFS2_I(inode)->ip_clusters)) { old_clusters != OCFS2_I(inode)->ip_clusters ||
has_refcount)) {
ret = jbd2_journal_force_commit(osb->journal->j_journal); ret = jbd2_journal_force_commit(osb->journal->j_journal);
if (ret < 0) if (ret < 0)
written = ret; written = ret;
...@@ -2062,7 +2071,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe, ...@@ -2062,7 +2071,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
int ret; int ret;
ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos, ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos,
sd->total_len, 0, NULL); sd->total_len, 0, NULL, NULL);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
return ret; return ret;
......
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