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: (31 commits) ocfs2: avoid unaligned access to dqc_bitmap ocfs2: Use filemap_write_and_wait() instead of write_inode_now() ocfs2: honor O_(D)SYNC flag in fallocate ocfs2: Add a missing journal credit in ocfs2_link_credits() -v2 ocfs2: send correct UUID to cleancache initialization ocfs2: Commit transactions in error cases -v2 ocfs2: make direntry invalid when deleting it fs/ocfs2/dlm/dlmlock.c: free kmem_cache_zalloc'd data using kmem_cache_free ocfs2: Avoid livelock in ocfs2_readpage() ocfs2: serialize unaligned aio ocfs2: Implement llseek() ocfs2: Fix ocfs2_page_mkwrite() ocfs2: Add comment about orphan scanning ocfs2: Clean up messages in the fs ocfs2/cluster: Cluster up now includes network connections too ocfs2/cluster: Add new function o2net_fill_node_map() ocfs2/cluster: Fix output in file elapsed_time_in_ms ocfs2/dlm: dlmlock_remote() needs to account for remastery ocfs2/dlm: Take inflight reference count for remotely mastered resources too ocfs2/dlm: Cleanup dlm_wait_for_node_death() and dlm_wait_for_node_recovery() ...
This commit is contained in:
@@ -1950,6 +1950,9 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
|
||||
if (file->f_flags & O_SYNC)
|
||||
handle->h_sync = 1;
|
||||
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
out_inode_unlock:
|
||||
@@ -2052,6 +2055,23 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ocfs2_aiodio_wait(struct inode *inode)
|
||||
{
|
||||
wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
|
||||
|
||||
wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0));
|
||||
}
|
||||
|
||||
static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
|
||||
{
|
||||
int blockmask = inode->i_sb->s_blocksize - 1;
|
||||
loff_t final_size = pos + count;
|
||||
|
||||
if ((pos & blockmask) || (final_size & blockmask))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
|
||||
struct file *file,
|
||||
loff_t pos, size_t count,
|
||||
@@ -2230,6 +2250,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
int full_coherency = !(osb->s_mount_opt &
|
||||
OCFS2_MOUNT_COHERENCY_BUFFERED);
|
||||
int unaligned_dio = 0;
|
||||
|
||||
trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
@@ -2297,6 +2318,10 @@ relock:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (direct_io && !is_sync_kiocb(iocb))
|
||||
unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left,
|
||||
*ppos);
|
||||
|
||||
/*
|
||||
* We can't complete the direct I/O as requested, fall back to
|
||||
* buffered I/O.
|
||||
@@ -2311,6 +2336,18 @@ relock:
|
||||
goto relock;
|
||||
}
|
||||
|
||||
if (unaligned_dio) {
|
||||
/*
|
||||
* Wait on previous unaligned aio to complete before
|
||||
* proceeding.
|
||||
*/
|
||||
ocfs2_aiodio_wait(inode);
|
||||
|
||||
/* Mark the iocb as needing a decrement in ocfs2_dio_end_io */
|
||||
atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio);
|
||||
ocfs2_iocb_set_unaligned_aio(iocb);
|
||||
}
|
||||
|
||||
/*
|
||||
* To later detect whether a journal commit for sync writes is
|
||||
* necessary, we sample i_size, and cluster count here.
|
||||
@@ -2382,8 +2419,12 @@ out_dio:
|
||||
if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
|
||||
rw_level = -1;
|
||||
have_alloc_sem = 0;
|
||||
unaligned_dio = 0;
|
||||
}
|
||||
|
||||
if (unaligned_dio)
|
||||
atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio);
|
||||
|
||||
out:
|
||||
if (rw_level != -1)
|
||||
ocfs2_rw_unlock(inode, rw_level);
|
||||
@@ -2591,6 +2632,57 @@ bail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Refer generic_file_llseek_unlocked() */
|
||||
static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin)
|
||||
{
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
switch (origin) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += inode->i_size;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
if (offset == 0) {
|
||||
offset = file->f_pos;
|
||||
goto out;
|
||||
}
|
||||
offset += file->f_pos;
|
||||
break;
|
||||
case SEEK_DATA:
|
||||
case SEEK_HOLE:
|
||||
ret = ocfs2_seek_data_hole_offset(file, &offset, origin);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
|
||||
ret = -EINVAL;
|
||||
if (!ret && offset > inode->i_sb->s_maxbytes)
|
||||
ret = -EINVAL;
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (offset != file->f_pos) {
|
||||
file->f_pos = offset;
|
||||
file->f_version = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
return offset;
|
||||
}
|
||||
|
||||
const struct inode_operations ocfs2_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
@@ -2615,7 +2707,7 @@ const struct inode_operations ocfs2_special_file_iops = {
|
||||
* ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
|
||||
*/
|
||||
const struct file_operations ocfs2_fops = {
|
||||
.llseek = generic_file_llseek,
|
||||
.llseek = ocfs2_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.mmap = ocfs2_mmap,
|
||||
@@ -2663,7 +2755,7 @@ const struct file_operations ocfs2_dops = {
|
||||
* the cluster.
|
||||
*/
|
||||
const struct file_operations ocfs2_fops_no_plocks = {
|
||||
.llseek = generic_file_llseek,
|
||||
.llseek = ocfs2_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.mmap = ocfs2_mmap,
|
||||
|
Reference in New Issue
Block a user