Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1f973ff authored by Ryan Ding's avatar Ryan Ding Committed by Linus Torvalds
Browse files

ocfs2: code clean up for direct io



Clean up ocfs2_file_write_iter & ocfs2_prepare_inode_for_write:
 * remove append dio check: it will be checked in ocfs2_direct_IO()
 * remove file hole check: file hole is supported for now
 * remove inline data check: it will be checked in ocfs2_direct_IO()
 * remove the full_coherence check when append dio: we will get the
   inode_lock in ocfs2_dio_get_block, there is no need to fall back to
   buffer io to ensure the coherence semantics.

Now the drop dio procedure is gone.  :)

[akpm@linux-foundation.org: remove unused label]
Signed-off-by: default avatarRyan Ding <ryan.ding@oracle.com>
Reviewed-by: default avatarJunxiao Bi <junxiao.bi@oracle.com>
Cc: Joseph Qi <joseph.qi@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c15471f7
Loading
Loading
Loading
Loading
+6 −132
Original line number Original line Diff line number Diff line
@@ -1381,44 +1381,6 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
	return ret;
	return ret;
}
}


/*
 * Will look for holes and unwritten extents in the range starting at
 * pos for count bytes (inclusive).
 */
static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
				       size_t count)
{
	int ret = 0;
	unsigned int extent_flags;
	u32 cpos, clusters, extent_len, phys_cpos;
	struct super_block *sb = inode->i_sb;

	cpos = pos >> OCFS2_SB(sb)->s_clustersize_bits;
	clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;

	while (clusters) {
		ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
					 &extent_flags);
		if (ret < 0) {
			mlog_errno(ret);
			goto out;
		}

		if (phys_cpos == 0 || (extent_flags & OCFS2_EXT_UNWRITTEN)) {
			ret = 1;
			break;
		}

		if (extent_len > clusters)
			extent_len = clusters;

		clusters -= extent_len;
		cpos += extent_len;
	}
out:
	return ret;
}

static int ocfs2_write_remove_suid(struct inode *inode)
static int ocfs2_write_remove_suid(struct inode *inode)
{
{
	int ret;
	int ret;
@@ -2129,18 +2091,12 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode,


static int ocfs2_prepare_inode_for_write(struct file *file,
static int ocfs2_prepare_inode_for_write(struct file *file,
					 loff_t pos,
					 loff_t pos,
					 size_t count,
					 size_t count)
					 int appending,
					 int *direct_io,
					 int *has_refcount)
{
{
	int ret = 0, meta_level = 0;
	int ret = 0, meta_level = 0;
	struct dentry *dentry = file->f_path.dentry;
	struct dentry *dentry = file->f_path.dentry;
	struct inode *inode = d_inode(dentry);
	struct inode *inode = d_inode(dentry);
	loff_t end;
	loff_t end;
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	int full_coherency = !(osb->s_mount_opt &
		OCFS2_MOUNT_COHERENCY_BUFFERED);


	/*
	/*
	 * We start with a read level meta lock and only jump to an ex
	 * We start with a read level meta lock and only jump to an ex
@@ -2189,10 +2145,6 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
							       pos,
							       pos,
							       count,
							       count,
							       &meta_level);
							       &meta_level);
			if (has_refcount)
				*has_refcount = 1;
			if (direct_io)
				*direct_io = 0;
		}
		}


		if (ret < 0) {
		if (ret < 0) {
@@ -2200,67 +2152,12 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
			goto out_unlock;
			goto out_unlock;
		}
		}


		/*
		 * Skip the O_DIRECT checks if we don't need
		 * them.
		 */
		if (!direct_io || !(*direct_io))
			break;

		/*
		 * There's no sane way to do direct writes to an inode
		 * with inline data.
		 */
		if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
			*direct_io = 0;
			break;
		}

		/*
		 * Allowing concurrent direct writes means
		 * i_size changes wouldn't be synchronized, so
		 * one node could wind up truncating another
		 * nodes writes.
		 */
		if (end > i_size_read(inode) && !full_coherency) {
			*direct_io = 0;
			break;
		}

		/*
		 * Fallback to old way if the feature bit is not set.
		 */
		if (end > i_size_read(inode) &&
				!ocfs2_supports_append_dio(osb)) {
			*direct_io = 0;
			break;
		}

		/*
		 * We don't fill holes during direct io, so
		 * check for them here. If any are found, the
		 * caller will have to retake some cluster
		 * locks and initiate the io as buffered.
		 */
		ret = ocfs2_check_range_for_holes(inode, pos, count);
		if (ret == 1) {
			/*
			 * Fallback to old way if the feature bit is not set.
			 * Otherwise try dio first and then complete the rest
			 * request through buffer io.
			 */
			if (!ocfs2_supports_append_dio(osb))
				*direct_io = 0;
			ret = 0;
		} else if (ret < 0)
			mlog_errno(ret);
		break;
		break;
	}
	}


out_unlock:
out_unlock:
	trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno,
	trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno,
					    pos, appending, count,
					    pos, count);
					    direct_io, has_refcount);


	if (meta_level >= 0)
	if (meta_level >= 0)
		ocfs2_inode_unlock(inode, meta_level);
		ocfs2_inode_unlock(inode, meta_level);
@@ -2272,18 +2169,16 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
				    struct iov_iter *from)
				    struct iov_iter *from)
{
{
	int direct_io, appending, rw_level;
	int direct_io, rw_level;
	int can_do_direct, has_refcount = 0;
	ssize_t written = 0;
	ssize_t written = 0;
	ssize_t ret;
	ssize_t ret;
	size_t count = iov_iter_count(from), orig_count;
	size_t count = iov_iter_count(from);
	struct file *file = iocb->ki_filp;
	struct file *file = iocb->ki_filp;
	struct inode *inode = file_inode(file);
	struct inode *inode = file_inode(file);
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	int full_coherency = !(osb->s_mount_opt &
	int full_coherency = !(osb->s_mount_opt &
			       OCFS2_MOUNT_COHERENCY_BUFFERED);
			       OCFS2_MOUNT_COHERENCY_BUFFERED);
	int unaligned_dio = 0;
	int unaligned_dio = 0;
	int dropped_dio = 0;
	int append_write = ((iocb->ki_pos + count) >=
	int append_write = ((iocb->ki_pos + count) >=
			i_size_read(inode) ? 1 : 0);
			i_size_read(inode) ? 1 : 0);


@@ -2296,12 +2191,10 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
	if (count == 0)
	if (count == 0)
		return 0;
		return 0;


	appending = iocb->ki_flags & IOCB_APPEND ? 1 : 0;
	direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0;
	direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0;


	inode_lock(inode);
	inode_lock(inode);


relock:
	/*
	/*
	 * Concurrent O_DIRECT writes are allowed with
	 * Concurrent O_DIRECT writes are allowed with
	 * mount_option "coherency=buffered".
	 * mount_option "coherency=buffered".
@@ -2334,7 +2227,6 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
		ocfs2_inode_unlock(inode, 1);
		ocfs2_inode_unlock(inode, 1);
	}
	}


	orig_count = iov_iter_count(from);
	ret = generic_write_checks(iocb, from);
	ret = generic_write_checks(iocb, from);
	if (ret <= 0) {
	if (ret <= 0) {
		if (ret)
		if (ret)
@@ -2343,9 +2235,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
	}
	}
	count = ret;
	count = ret;


	can_do_direct = direct_io;
	ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count);
	ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending,
					    &can_do_direct, &has_refcount);
	if (ret < 0) {
	if (ret < 0) {
		mlog_errno(ret);
		mlog_errno(ret);
		goto out;
		goto out;
@@ -2354,22 +2244,6 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
	if (direct_io && !is_sync_kiocb(iocb))
	if (direct_io && !is_sync_kiocb(iocb))
		unaligned_dio = ocfs2_is_io_unaligned(inode, count, iocb->ki_pos);
		unaligned_dio = ocfs2_is_io_unaligned(inode, count, iocb->ki_pos);


	/*
	 * We can't complete the direct I/O as requested, fall back to
	 * buffered I/O.
	 */
	if (direct_io && !can_do_direct) {
		ocfs2_rw_unlock(inode, rw_level);

		rw_level = -1;

		direct_io = 0;
		iocb->ki_flags &= ~IOCB_DIRECT;
		iov_iter_reexpand(from, orig_count);
		dropped_dio = 1;
		goto relock;
	}

	if (unaligned_dio) {
	if (unaligned_dio) {
		/*
		/*
		 * Wait on previous unaligned aio to complete before
		 * Wait on previous unaligned aio to complete before
@@ -2405,7 +2279,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
		goto no_sync;
		goto no_sync;


	if (((file->f_flags & O_DSYNC) && !direct_io) ||
	if (((file->f_flags & O_DSYNC) && !direct_io) ||
	    IS_SYNC(inode) || dropped_dio) {
	    IS_SYNC(inode)) {
		ret = filemap_fdatawrite_range(file->f_mapping,
		ret = filemap_fdatawrite_range(file->f_mapping,
					       iocb->ki_pos - written,
					       iocb->ki_pos - written,
					       iocb->ki_pos - 1);
					       iocb->ki_pos - 1);
+4 −12
Original line number Original line Diff line number Diff line
@@ -1450,28 +1450,20 @@ DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_remove_inode_range);


TRACE_EVENT(ocfs2_prepare_inode_for_write,
TRACE_EVENT(ocfs2_prepare_inode_for_write,
	TP_PROTO(unsigned long long ino, unsigned long long saved_pos,
	TP_PROTO(unsigned long long ino, unsigned long long saved_pos,
		 int appending, unsigned long count,
		 unsigned long count),
		 int *direct_io, int *has_refcount),
	TP_ARGS(ino, saved_pos, count),
	TP_ARGS(ino, saved_pos, appending, count, direct_io, has_refcount),
	TP_STRUCT__entry(
	TP_STRUCT__entry(
		__field(unsigned long long, ino)
		__field(unsigned long long, ino)
		__field(unsigned long long, saved_pos)
		__field(unsigned long long, saved_pos)
		__field(int, appending)
		__field(unsigned long, count)
		__field(unsigned long, count)
		__field(int, direct_io)
		__field(int, has_refcount)
	),
	),
	TP_fast_assign(
	TP_fast_assign(
		__entry->ino = ino;
		__entry->ino = ino;
		__entry->saved_pos = saved_pos;
		__entry->saved_pos = saved_pos;
		__entry->appending = appending;
		__entry->count = count;
		__entry->count = count;
		__entry->direct_io = direct_io ? *direct_io : -1;
		__entry->has_refcount = has_refcount ? *has_refcount : -1;
	),
	),
	TP_printk("%llu %llu %d %lu %d %d", __entry->ino,
	TP_printk("%llu %llu %lu", __entry->ino,
		  __entry->saved_pos, __entry->appending, __entry->count,
		  __entry->saved_pos, __entry->count)
		  __entry->direct_io, __entry->has_refcount)
);
);


DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret);
DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret);