All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xfs: don't allocate an ioend for direct I/O completions
@ 2015-01-28 22:54 Christoph Hellwig
  2015-01-30 14:42 ` Brian Foster
  0 siblings, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2015-01-28 22:54 UTC (permalink / raw)
  To: xfs

Back in the days when the direct I/O ->end_io callback could be called
from interrupt context for AIO we needed a structure to hand off to the
workqueue, and reused the ioend structure for this purpose.  These days
->end_io is always called from user or workqueue context, which allows us
to avoid this memory allocation and simplify the code significantly.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_aops.c | 133 ++++++++++++++++++++++++------------------------------
 fs/xfs/xfs_aops.h |   3 --
 2 files changed, 59 insertions(+), 77 deletions(-)

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 18e2f3b..31d3d7d 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -135,30 +135,22 @@ xfs_setfilesize_trans_alloc(
  */
 STATIC int
 xfs_setfilesize(
-	struct xfs_ioend	*ioend)
+	struct xfs_inode	*ip,
+	struct xfs_trans	*tp,
+	xfs_off_t		offset,
+	size_t			size)
 {
-	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
-	struct xfs_trans	*tp = ioend->io_append_trans;
 	xfs_fsize_t		isize;
 
-	/*
-	 * The transaction may have been allocated in the I/O submission thread,
-	 * thus we need to mark ourselves as beeing in a transaction manually.
-	 * Similarly for freeze protection.
-	 */
-	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
-	rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
-			   0, 1, _THIS_IP_);
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	isize = xfs_new_eof(ip, ioend->io_offset + ioend->io_size);
+	isize = xfs_new_eof(ip, offset + size);
 	if (!isize) {
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		xfs_trans_cancel(tp, 0);
 		return 0;
 	}
 
-	trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
+	trace_xfs_setfilesize(ip, offset, size);
 
 	ip->i_d.di_size = isize;
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -167,6 +159,25 @@ xfs_setfilesize(
 	return xfs_trans_commit(tp, 0);
 }
 
+STATIC int
+xfs_setfilesize_ioend(
+	struct xfs_ioend	*ioend)
+{
+	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
+	struct xfs_trans	*tp = ioend->io_append_trans;
+
+	/*
+	 * The transaction may have been allocated in the I/O submission thread,
+	 * thus we need to mark ourselves as beeing in a transaction manually.
+	 * Similarly for freeze protection.
+	 */
+	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
+	rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
+			   0, 1, _THIS_IP_);
+
+	return xfs_setfilesize(ip, tp, ioend->io_offset, ioend->io_size);
+}
+
 /*
  * Schedule IO completion handling on the final put of an ioend.
  *
@@ -182,8 +193,7 @@ xfs_finish_ioend(
 
 		if (ioend->io_type == XFS_IO_UNWRITTEN)
 			queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
-		else if (ioend->io_append_trans ||
-			 (ioend->io_isdirect && xfs_ioend_is_append(ioend)))
+		else if (ioend->io_append_trans)
 			queue_work(mp->m_data_workqueue, &ioend->io_work);
 		else
 			xfs_destroy_ioend(ioend);
@@ -215,22 +225,8 @@ xfs_end_io(
 	if (ioend->io_type == XFS_IO_UNWRITTEN) {
 		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
 						  ioend->io_size);
-	} else if (ioend->io_isdirect && xfs_ioend_is_append(ioend)) {
-		/*
-		 * For direct I/O we do not know if we need to allocate blocks
-		 * or not so we can't preallocate an append transaction as that
-		 * results in nested reservations and log space deadlocks. Hence
-		 * allocate the transaction here. While this is sub-optimal and
-		 * can block IO completion for some time, we're stuck with doing
-		 * it this way until we can pass the ioend to the direct IO
-		 * allocation callbacks and avoid nesting that way.
-		 */
-		error = xfs_setfilesize_trans_alloc(ioend);
-		if (error)
-			goto done;
-		error = xfs_setfilesize(ioend);
 	} else if (ioend->io_append_trans) {
-		error = xfs_setfilesize(ioend);
+		error = xfs_setfilesize_ioend(ioend);
 	} else {
 		ASSERT(!xfs_ioend_is_append(ioend));
 	}
@@ -273,7 +269,6 @@ xfs_alloc_ioend(
 	 * all the I/O from calling the completion routine too early.
 	 */
 	atomic_set(&ioend->io_remaining, 1);
-	ioend->io_isdirect = 0;
 	ioend->io_error = 0;
 	ioend->io_list = NULL;
 	ioend->io_type = type;
@@ -1459,11 +1454,7 @@ xfs_get_blocks_direct(
  *
  * If the private argument is non-NULL __xfs_get_blocks signals us that we
  * need to issue a transaction to convert the range from unwritten to written
- * extents.  In case this is regular synchronous I/O we just call xfs_end_io
- * to do this and we are done.  But in case this was a successful AIO
- * request this handler is called from interrupt context, from which we
- * can't start transactions.  In that case offload the I/O completion to
- * the workqueues we also use for buffered I/O completion.
+ * extents.
  */
 STATIC void
 xfs_end_io_direct_write(
@@ -1472,7 +1463,12 @@ xfs_end_io_direct_write(
 	ssize_t			size,
 	void			*private)
 {
-	struct xfs_ioend	*ioend = iocb->private;
+	struct inode		*inode = file_inode(iocb->ki_filp);
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return;
 
 	/*
 	 * While the generic direct I/O code updates the inode size, it does
@@ -1480,22 +1476,33 @@ xfs_end_io_direct_write(
 	 * end_io handler thinks the on-disk size is outside the in-core
 	 * size.  To prevent this just update it a little bit earlier here.
 	 */
-	if (offset + size > i_size_read(ioend->io_inode))
-		i_size_write(ioend->io_inode, offset + size);
+	if (offset + size > i_size_read(inode))
+		i_size_write(inode, offset + size);
 
 	/*
-	 * blockdev_direct_IO can return an error even after the I/O
-	 * completion handler was called.  Thus we need to protect
-	 * against double-freeing.
+	 * For direct I/O we do not know if we need to allocate blocks or not,
+	 * so we can't preallocate an append transaction, as that results in
+	 * nested reservations and log space deadlocks. Hence allocate the
+	 * transaction here. While this is sub-optimal and can block IO
+	 * completion for some time, we're stuck with doing it this way until
+	 * we can pass the ioend to the direct IO allocation callbacks and
+	 * avoid nesting that way.
 	 */
-	iocb->private = NULL;
-
-	ioend->io_offset = offset;
-	ioend->io_size = size;
-	if (private && size > 0)
-		ioend->io_type = XFS_IO_UNWRITTEN;
+	if (private && size > 0) {
+		xfs_iomap_write_unwritten(ip, offset, size);
+	} else if (offset + size > ip->i_d.di_size) {
+		struct xfs_trans	*tp;
+		int			error;
+
+		tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
+		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
+		if (error) {
+			xfs_trans_cancel(tp, 0);
+			return;
+		}
 
-	xfs_finish_ioend_sync(ioend);
+		xfs_setfilesize(ip, tp, offset, size);
+	}
 }
 
 STATIC ssize_t
@@ -1507,39 +1514,17 @@ xfs_vm_direct_IO(
 {
 	struct inode		*inode = iocb->ki_filp->f_mapping->host;
 	struct block_device	*bdev = xfs_find_bdev_for_inode(inode);
-	struct xfs_ioend	*ioend = NULL;
-	ssize_t			ret;
 
 	if (rw & WRITE) {
-		size_t size = iov_iter_count(iter);
-
-		/*
-		 * We cannot preallocate a size update transaction here as we
-		 * don't know whether allocation is necessary or not. Hence we
-		 * can only tell IO completion that one is necessary if we are
-		 * not doing unwritten extent conversion.
-		 */
-		iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT);
-		if (offset + size > XFS_I(inode)->i_d.di_size)
-			ioend->io_isdirect = 1;
-
-		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
+		return __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
 					    offset, xfs_get_blocks_direct,
 					    xfs_end_io_direct_write, NULL,
 					    DIO_ASYNC_EXTEND);
-		if (ret != -EIOCBQUEUED && iocb->private)
-			goto out_destroy_ioend;
 	} else {
-		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
+		return __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
 					    offset, xfs_get_blocks_direct,
 					    NULL, NULL, 0);
 	}
-
-	return ret;
-
-out_destroy_ioend:
-	xfs_destroy_ioend(ioend);
-	return ret;
 }
 
 /*
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
index f94dd45..ac644e0 100644
--- a/fs/xfs/xfs_aops.h
+++ b/fs/xfs/xfs_aops.h
@@ -24,14 +24,12 @@ extern mempool_t *xfs_ioend_pool;
  * Types of I/O for bmap clustering and I/O completion tracking.
  */
 enum {
-	XFS_IO_DIRECT = 0,	/* special case for direct I/O ioends */
 	XFS_IO_DELALLOC,	/* covers delalloc region */
 	XFS_IO_UNWRITTEN,	/* covers allocated but uninitialized data */
 	XFS_IO_OVERWRITE,	/* covers already allocated extent */
 };
 
 #define XFS_IO_TYPES \
-	{ 0,			"" }, \
 	{ XFS_IO_DELALLOC,		"delalloc" }, \
 	{ XFS_IO_UNWRITTEN,		"unwritten" }, \
 	{ XFS_IO_OVERWRITE,		"overwrite" }
@@ -45,7 +43,6 @@ typedef struct xfs_ioend {
 	unsigned int		io_type;	/* delalloc / unwritten */
 	int			io_error;	/* I/O error code */
 	atomic_t		io_remaining;	/* hold count */
-	unsigned int		io_isdirect : 1;/* direct I/O */
 	struct inode		*io_inode;	/* file being written to */
 	struct buffer_head	*io_buffer_head;/* buffer linked list head */
 	struct buffer_head	*io_buffer_tail;/* buffer linked list tail */
-- 
1.9.1

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] xfs: don't allocate an ioend for direct I/O completions
  2015-01-28 22:54 [PATCH] xfs: don't allocate an ioend for direct I/O completions Christoph Hellwig
@ 2015-01-30 14:42 ` Brian Foster
  2015-02-01 23:04   ` Dave Chinner
  0 siblings, 1 reply; 4+ messages in thread
From: Brian Foster @ 2015-01-30 14:42 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Wed, Jan 28, 2015 at 11:54:21PM +0100, Christoph Hellwig wrote:
> Back in the days when the direct I/O ->end_io callback could be called
> from interrupt context for AIO we needed a structure to hand off to the
> workqueue, and reused the ioend structure for this purpose.  These days
> ->end_io is always called from user or workqueue context, which allows us
> to avoid this memory allocation and simplify the code significantly.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Looks mostly Ok to me. In fact, with xfs_finish_ioend_sync() calling
xfs_end_io() directly, I don't see how we currently get into the wq at
all. Anyways, a few notes...

>  fs/xfs/xfs_aops.c | 133 ++++++++++++++++++++++++------------------------------
>  fs/xfs/xfs_aops.h |   3 --
>  2 files changed, 59 insertions(+), 77 deletions(-)
> 
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 18e2f3b..31d3d7d 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -135,30 +135,22 @@ xfs_setfilesize_trans_alloc(
>   */
>  STATIC int
>  xfs_setfilesize(
> -	struct xfs_ioend	*ioend)
> +	struct xfs_inode	*ip,
> +	struct xfs_trans	*tp,
> +	xfs_off_t		offset,
> +	size_t			size)
>  {
> -	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
> -	struct xfs_trans	*tp = ioend->io_append_trans;
>  	xfs_fsize_t		isize;
>  
> -	/*
> -	 * The transaction may have been allocated in the I/O submission thread,
> -	 * thus we need to mark ourselves as beeing in a transaction manually.
> -	 * Similarly for freeze protection.
> -	 */
> -	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
> -	rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
> -			   0, 1, _THIS_IP_);
> -
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -	isize = xfs_new_eof(ip, ioend->io_offset + ioend->io_size);
> +	isize = xfs_new_eof(ip, offset + size);
>  	if (!isize) {
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  		xfs_trans_cancel(tp, 0);
>  		return 0;
>  	}
>  
> -	trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
> +	trace_xfs_setfilesize(ip, offset, size);
>  
>  	ip->i_d.di_size = isize;
>  	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
> @@ -167,6 +159,25 @@ xfs_setfilesize(
>  	return xfs_trans_commit(tp, 0);
>  }
>  
> +STATIC int
> +xfs_setfilesize_ioend(
> +	struct xfs_ioend	*ioend)
> +{
> +	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
> +	struct xfs_trans	*tp = ioend->io_append_trans;
> +
> +	/*
> +	 * The transaction may have been allocated in the I/O submission thread,
> +	 * thus we need to mark ourselves as beeing in a transaction manually.

Copied from the the original, but since we're here: "being."

> +	 * Similarly for freeze protection.
> +	 */
> +	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
> +	rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
> +			   0, 1, _THIS_IP_);
> +
> +	return xfs_setfilesize(ip, tp, ioend->io_offset, ioend->io_size);
> +}
> +
>  /*
>   * Schedule IO completion handling on the final put of an ioend.
>   *
> @@ -182,8 +193,7 @@ xfs_finish_ioend(
>  
>  		if (ioend->io_type == XFS_IO_UNWRITTEN)
>  			queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
> -		else if (ioend->io_append_trans ||
> -			 (ioend->io_isdirect && xfs_ioend_is_append(ioend)))
> +		else if (ioend->io_append_trans)
>  			queue_work(mp->m_data_workqueue, &ioend->io_work);
>  		else
>  			xfs_destroy_ioend(ioend);
> @@ -215,22 +225,8 @@ xfs_end_io(
>  	if (ioend->io_type == XFS_IO_UNWRITTEN) {
>  		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
>  						  ioend->io_size);
> -	} else if (ioend->io_isdirect && xfs_ioend_is_append(ioend)) {
> -		/*
> -		 * For direct I/O we do not know if we need to allocate blocks
> -		 * or not so we can't preallocate an append transaction as that
> -		 * results in nested reservations and log space deadlocks. Hence
> -		 * allocate the transaction here. While this is sub-optimal and
> -		 * can block IO completion for some time, we're stuck with doing
> -		 * it this way until we can pass the ioend to the direct IO
> -		 * allocation callbacks and avoid nesting that way.
> -		 */
> -		error = xfs_setfilesize_trans_alloc(ioend);
> -		if (error)
> -			goto done;
> -		error = xfs_setfilesize(ioend);
>  	} else if (ioend->io_append_trans) {
> -		error = xfs_setfilesize(ioend);
> +		error = xfs_setfilesize_ioend(ioend);
>  	} else {
>  		ASSERT(!xfs_ioend_is_append(ioend));
>  	}
> @@ -273,7 +269,6 @@ xfs_alloc_ioend(
>  	 * all the I/O from calling the completion routine too early.
>  	 */
>  	atomic_set(&ioend->io_remaining, 1);
> -	ioend->io_isdirect = 0;
>  	ioend->io_error = 0;
>  	ioend->io_list = NULL;
>  	ioend->io_type = type;
> @@ -1459,11 +1454,7 @@ xfs_get_blocks_direct(
>   *
>   * If the private argument is non-NULL __xfs_get_blocks signals us that we
>   * need to issue a transaction to convert the range from unwritten to written
> - * extents.  In case this is regular synchronous I/O we just call xfs_end_io
> - * to do this and we are done.  But in case this was a successful AIO
> - * request this handler is called from interrupt context, from which we
> - * can't start transactions.  In that case offload the I/O completion to
> - * the workqueues we also use for buffered I/O completion.
> + * extents.
>   */
>  STATIC void
>  xfs_end_io_direct_write(
> @@ -1472,7 +1463,12 @@ xfs_end_io_direct_write(
>  	ssize_t			size,
>  	void			*private)
>  {
> -	struct xfs_ioend	*ioend = iocb->private;
> +	struct inode		*inode = file_inode(iocb->ki_filp);
> +	struct xfs_inode	*ip = XFS_I(inode);
> +	struct xfs_mount	*mp = ip->i_mount;
> +
> +	if (XFS_FORCED_SHUTDOWN(mp))
> +		return;
>  
>  	/*
>  	 * While the generic direct I/O code updates the inode size, it does
> @@ -1480,22 +1476,33 @@ xfs_end_io_direct_write(
>  	 * end_io handler thinks the on-disk size is outside the in-core
>  	 * size.  To prevent this just update it a little bit earlier here.
>  	 */
> -	if (offset + size > i_size_read(ioend->io_inode))
> -		i_size_write(ioend->io_inode, offset + size);
> +	if (offset + size > i_size_read(inode))
> +		i_size_write(inode, offset + size);
>  
>  	/*
> -	 * blockdev_direct_IO can return an error even after the I/O
> -	 * completion handler was called.  Thus we need to protect
> -	 * against double-freeing.
> +	 * For direct I/O we do not know if we need to allocate blocks or not,
> +	 * so we can't preallocate an append transaction, as that results in
> +	 * nested reservations and log space deadlocks. Hence allocate the
> +	 * transaction here. While this is sub-optimal and can block IO
> +	 * completion for some time, we're stuck with doing it this way until
> +	 * we can pass the ioend to the direct IO allocation callbacks and
> +	 * avoid nesting that way.
>  	 */
> -	iocb->private = NULL;
> -
> -	ioend->io_offset = offset;
> -	ioend->io_size = size;
> -	if (private && size > 0)
> -		ioend->io_type = XFS_IO_UNWRITTEN;
> +	if (private && size > 0) {
> +		xfs_iomap_write_unwritten(ip, offset, size);
> +	} else if (offset + size > ip->i_d.di_size) {
> +		struct xfs_trans	*tp;
> +		int			error;
> +
> +		tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
> +		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
> +		if (error) {
> +			xfs_trans_cancel(tp, 0);
> +			return;
> +		}
>  
> -	xfs_finish_ioend_sync(ioend);

I get an unused function warning for xfs_finish_ioend_sync() now, so I
guess we should kill that.

> +		xfs_setfilesize(ip, tp, offset, size);
> +	}
>  }
>  
>  STATIC ssize_t
> @@ -1507,39 +1514,17 @@ xfs_vm_direct_IO(
>  {
>  	struct inode		*inode = iocb->ki_filp->f_mapping->host;
>  	struct block_device	*bdev = xfs_find_bdev_for_inode(inode);
> -	struct xfs_ioend	*ioend = NULL;
> -	ssize_t			ret;
>  
>  	if (rw & WRITE) {

A nit, but I guess you could kill the braces here now too.

Brian

> -		size_t size = iov_iter_count(iter);
> -
> -		/*
> -		 * We cannot preallocate a size update transaction here as we
> -		 * don't know whether allocation is necessary or not. Hence we
> -		 * can only tell IO completion that one is necessary if we are
> -		 * not doing unwritten extent conversion.
> -		 */
> -		iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT);
> -		if (offset + size > XFS_I(inode)->i_d.di_size)
> -			ioend->io_isdirect = 1;
> -
> -		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
> +		return __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
>  					    offset, xfs_get_blocks_direct,
>  					    xfs_end_io_direct_write, NULL,
>  					    DIO_ASYNC_EXTEND);
> -		if (ret != -EIOCBQUEUED && iocb->private)
> -			goto out_destroy_ioend;
>  	} else {
> -		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
> +		return __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
>  					    offset, xfs_get_blocks_direct,
>  					    NULL, NULL, 0);
>  	}
> -
> -	return ret;
> -
> -out_destroy_ioend:
> -	xfs_destroy_ioend(ioend);
> -	return ret;
>  }
>  
>  /*
> diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
> index f94dd45..ac644e0 100644
> --- a/fs/xfs/xfs_aops.h
> +++ b/fs/xfs/xfs_aops.h
> @@ -24,14 +24,12 @@ extern mempool_t *xfs_ioend_pool;
>   * Types of I/O for bmap clustering and I/O completion tracking.
>   */
>  enum {
> -	XFS_IO_DIRECT = 0,	/* special case for direct I/O ioends */
>  	XFS_IO_DELALLOC,	/* covers delalloc region */
>  	XFS_IO_UNWRITTEN,	/* covers allocated but uninitialized data */
>  	XFS_IO_OVERWRITE,	/* covers already allocated extent */
>  };
>  
>  #define XFS_IO_TYPES \
> -	{ 0,			"" }, \
>  	{ XFS_IO_DELALLOC,		"delalloc" }, \
>  	{ XFS_IO_UNWRITTEN,		"unwritten" }, \
>  	{ XFS_IO_OVERWRITE,		"overwrite" }
> @@ -45,7 +43,6 @@ typedef struct xfs_ioend {
>  	unsigned int		io_type;	/* delalloc / unwritten */
>  	int			io_error;	/* I/O error code */
>  	atomic_t		io_remaining;	/* hold count */
> -	unsigned int		io_isdirect : 1;/* direct I/O */
>  	struct inode		*io_inode;	/* file being written to */
>  	struct buffer_head	*io_buffer_head;/* buffer linked list head */
>  	struct buffer_head	*io_buffer_tail;/* buffer linked list tail */
> -- 
> 1.9.1
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] xfs: don't allocate an ioend for direct I/O completions
  2015-01-30 14:42 ` Brian Foster
@ 2015-02-01 23:04   ` Dave Chinner
  2015-02-02  7:27     ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Dave Chinner @ 2015-02-01 23:04 UTC (permalink / raw)
  To: Brian Foster; +Cc: Christoph Hellwig, xfs

On Fri, Jan 30, 2015 at 09:42:23AM -0500, Brian Foster wrote:
> On Wed, Jan 28, 2015 at 11:54:21PM +0100, Christoph Hellwig wrote:
> > Back in the days when the direct I/O ->end_io callback could be called
> > from interrupt context for AIO we needed a structure to hand off to the
> > workqueue, and reused the ioend structure for this purpose.  These days
> > ->end_io is always called from user or workqueue context, which allows us
> > to avoid this memory allocation and simplify the code significantly.
> > 
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> 
> Looks mostly Ok to me. In fact, with xfs_finish_ioend_sync() calling
> xfs_end_io() directly, I don't see how we currently get into the wq at
> all. Anyways, a few notes...

I've pulled this in after making the couple of minor changes that
Brian suggested....

> > @@ -1507,39 +1514,17 @@ xfs_vm_direct_IO(
> >  {
> >  	struct inode		*inode = iocb->ki_filp->f_mapping->host;
> >  	struct block_device	*bdev = xfs_find_bdev_for_inode(inode);
> > -	struct xfs_ioend	*ioend = NULL;
> > -	ssize_t			ret;
> >  
> >  	if (rw & WRITE) {
> 
> A nit, but I guess you could kill the braces here now too.

Given it's a multi-line return statement, the braces are fine. FWIW,
when we have a if () { return ...} else { return ... } we normally
kill the else. i.e:

	if (rw & WRITE) {
		return foo(
			bar,
			baz);
	}
	return .....;

So I modified it like this.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] xfs: don't allocate an ioend for direct I/O completions
  2015-02-01 23:04   ` Dave Chinner
@ 2015-02-02  7:27     ` Christoph Hellwig
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2015-02-02  7:27 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Brian Foster, Christoph Hellwig, xfs

On Mon, Feb 02, 2015 at 10:04:03AM +1100, Dave Chinner wrote:
> > A nit, but I guess you could kill the braces here now too.
> 
> Given it's a multi-line return statement, the braces are fine. FWIW,
> when we have a if () { return ...} else { return ... } we normally
> kill the else. i.e:
> 
> 	if (rw & WRITE) {
> 		return foo(
> 			bar,
> 			baz);
> 	}
> 	return .....;
> 
> So I modified it like this.

For an if/else that is 100% symmetric like read vs write I prefer
to keep the else, otherwise I agree.  But in the end it's a very
minor point, so it doesn't really matter.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-02-02  7:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-28 22:54 [PATCH] xfs: don't allocate an ioend for direct I/O completions Christoph Hellwig
2015-01-30 14:42 ` Brian Foster
2015-02-01 23:04   ` Dave Chinner
2015-02-02  7:27     ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.