mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	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: Ryan Ding <ryan.ding@oracle.com> Reviewed-by: Junxiao 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									c15471f795
								
							
						
					
					
						commit
						f1f973ffce
					
				
					 2 changed files with 10 additions and 144 deletions
				
			
		
							
								
								
									
										138
									
								
								fs/ocfs2/file.c
									
										
									
									
									
								
							
							
						
						
									
										138
									
								
								fs/ocfs2/file.c
									
										
									
									
									
								
							|  | @ -1381,44 +1381,6 @@ out: | |||
| 	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) | ||||
| { | ||||
| 	int ret; | ||||
|  | @ -2129,18 +2091,12 @@ out: | |||
| 
 | ||||
| static int ocfs2_prepare_inode_for_write(struct file *file, | ||||
| 					 loff_t pos, | ||||
| 					 size_t count, | ||||
| 					 int appending, | ||||
| 					 int *direct_io, | ||||
| 					 int *has_refcount) | ||||
| 					 size_t count) | ||||
| { | ||||
| 	int ret = 0, meta_level = 0; | ||||
| 	struct dentry *dentry = file->f_path.dentry; | ||||
| 	struct inode *inode = d_inode(dentry); | ||||
| 	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 | ||||
|  | @ -2189,10 +2145,6 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
| 							       pos, | ||||
| 							       count, | ||||
| 							       &meta_level); | ||||
| 			if (has_refcount) | ||||
| 				*has_refcount = 1; | ||||
| 			if (direct_io) | ||||
| 				*direct_io = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		if (ret < 0) { | ||||
|  | @ -2200,67 +2152,12 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
| 			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; | ||||
| 	} | ||||
| 
 | ||||
| out_unlock: | ||||
| 	trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, | ||||
| 					    pos, appending, count, | ||||
| 					    direct_io, has_refcount); | ||||
| 					    pos, count); | ||||
| 
 | ||||
| 	if (meta_level >= 0) | ||||
| 		ocfs2_inode_unlock(inode, meta_level); | ||||
|  | @ -2272,18 +2169,16 @@ out: | |||
| static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | ||||
| 				    struct iov_iter *from) | ||||
| { | ||||
| 	int direct_io, appending, rw_level; | ||||
| 	int can_do_direct, has_refcount = 0; | ||||
| 	int direct_io, rw_level; | ||||
| 	ssize_t written = 0; | ||||
| 	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 inode *inode = file_inode(file); | ||||
| 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||||
| 	int full_coherency = !(osb->s_mount_opt & | ||||
| 			       OCFS2_MOUNT_COHERENCY_BUFFERED); | ||||
| 	int unaligned_dio = 0; | ||||
| 	int dropped_dio = 0; | ||||
| 	int append_write = ((iocb->ki_pos + count) >= | ||||
| 			i_size_read(inode) ? 1 : 0); | ||||
| 
 | ||||
|  | @ -2296,12 +2191,10 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | |||
| 	if (count == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	appending = iocb->ki_flags & IOCB_APPEND ? 1 : 0; | ||||
| 	direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0; | ||||
| 
 | ||||
| 	inode_lock(inode); | ||||
| 
 | ||||
| relock: | ||||
| 	/*
 | ||||
| 	 * Concurrent O_DIRECT writes are allowed with | ||||
| 	 * mount_option "coherency=buffered". | ||||
|  | @ -2334,7 +2227,6 @@ relock: | |||
| 		ocfs2_inode_unlock(inode, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	orig_count = iov_iter_count(from); | ||||
| 	ret = generic_write_checks(iocb, from); | ||||
| 	if (ret <= 0) { | ||||
| 		if (ret) | ||||
|  | @ -2343,9 +2235,7 @@ relock: | |||
| 	} | ||||
| 	count = ret; | ||||
| 
 | ||||
| 	can_do_direct = direct_io; | ||||
| 	ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending, | ||||
| 					    &can_do_direct, &has_refcount); | ||||
| 	ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count); | ||||
| 	if (ret < 0) { | ||||
| 		mlog_errno(ret); | ||||
| 		goto out; | ||||
|  | @ -2354,22 +2244,6 @@ relock: | |||
| 	if (direct_io && !is_sync_kiocb(iocb)) | ||||
| 		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) { | ||||
| 		/*
 | ||||
| 		 * Wait on previous unaligned aio to complete before | ||||
|  | @ -2405,7 +2279,7 @@ relock: | |||
| 		goto no_sync; | ||||
| 
 | ||||
| 	if (((file->f_flags & O_DSYNC) && !direct_io) || | ||||
| 	    IS_SYNC(inode) || dropped_dio) { | ||||
| 	    IS_SYNC(inode)) { | ||||
| 		ret = filemap_fdatawrite_range(file->f_mapping, | ||||
| 					       iocb->ki_pos - written, | ||||
| 					       iocb->ki_pos - 1); | ||||
|  |  | |||
|  | @ -1450,28 +1450,20 @@ DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_remove_inode_range); | |||
| 
 | ||||
| TRACE_EVENT(ocfs2_prepare_inode_for_write, | ||||
| 	TP_PROTO(unsigned long long ino, unsigned long long saved_pos, | ||||
| 		 int appending, unsigned long count, | ||||
| 		 int *direct_io, int *has_refcount), | ||||
| 	TP_ARGS(ino, saved_pos, appending, count, direct_io, has_refcount), | ||||
| 		 unsigned long count), | ||||
| 	TP_ARGS(ino, saved_pos, count), | ||||
| 	TP_STRUCT__entry( | ||||
| 		__field(unsigned long long, ino) | ||||
| 		__field(unsigned long long, saved_pos) | ||||
| 		__field(int, appending) | ||||
| 		__field(unsigned long, count) | ||||
| 		__field(int, direct_io) | ||||
| 		__field(int, has_refcount) | ||||
| 	), | ||||
| 	TP_fast_assign( | ||||
| 		__entry->ino = ino; | ||||
| 		__entry->saved_pos = saved_pos; | ||||
| 		__entry->appending = appending; | ||||
| 		__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, | ||||
| 		  __entry->saved_pos, __entry->appending, __entry->count, | ||||
| 		  __entry->direct_io, __entry->has_refcount) | ||||
| 	TP_printk("%llu %llu %lu", __entry->ino, | ||||
| 		  __entry->saved_pos, __entry->count) | ||||
| ); | ||||
| 
 | ||||
| DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Ryan Ding
						Ryan Ding