[PATCH] xfs: cleanup data end I/O handlers

Alex Elder aelder at sgi.com
Tue Nov 3 10:18:34 CST 2009


Christoph Hellwig wrote:
> Currently we have various different end I/O handler for read vs the different
> types of write I/O.  But they are all very similar so we could just use one
> with a few conditionals and reduce code size a lot.

When I was looking at the last patch I had the same
thought, so I'm glad you did this.

The patch is good--here are a few thoughts so you
can correct me if I'm misunderstanding something...

I note that you now call xfs_setfilesize() in the
IOMAP_UNWRITTEN case even if there was an I/O error
indicated, which is different from current code.
But that's OK because xfs_setfilesize() checks for
that condition, so the result is the same.

I also note that you no longer init the work queue
at the end of a non-extending direct I/O write.
But that too is OK, because it looks like the only
reason it was initialized there was so that the
work function pointer would change, for the benefit
of xfs_finish_ioend().  But you changed that to
make use of the io_type, which is a better way of
doing it anyway.

In summary...  Looks good, I like it.

> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Alex Elder <aelder at sgi.com>


> Index: linux-2.6/fs/xfs/linux-2.6/xfs_aops.c
> ===================================================================
> --- linux-2.6.orig/fs/xfs/linux-2.6/xfs_aops.c	2009-10-30 10:05:46.680256053 +0100
> +++ linux-2.6/fs/xfs/linux-2.6/xfs_aops.c	2009-10-30 10:08:54.235024030 +0100
> @@ -235,71 +235,36 @@ xfs_setfilesize(
>  }
> 
>  /*
> - * Buffered IO write completion for delayed allocate extents.
> + * IO write completion.
>   */
>  STATIC void
> -xfs_end_bio_delalloc(
> -	struct work_struct	*work)
> -{
> -	xfs_ioend_t		*ioend =
> -		container_of(work, xfs_ioend_t, io_work);
> -
> -	xfs_setfilesize(ioend);
> -	xfs_destroy_ioend(ioend);
> -}
> -
> -/*
> - * Buffered IO write completion for regular, written extents.
> - */
> -STATIC void
> -xfs_end_bio_written(
> -	struct work_struct	*work)
> -{
> -	xfs_ioend_t		*ioend =
> -		container_of(work, xfs_ioend_t, io_work);
> -
> -	xfs_setfilesize(ioend);
> -	xfs_destroy_ioend(ioend);
> -}
> -
> -/*
> - * IO write completion for unwritten extents.
> - *
> - * Issue transactions to convert a buffer range from unwritten
> - * to written extents.
> - */
> -STATIC void
> -xfs_end_bio_unwritten(
> +xfs_end_io(
>  	struct work_struct	*work)
>  {
>  	xfs_ioend_t		*ioend =
>  		container_of(work, xfs_ioend_t, io_work);
>  	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
> -	xfs_off_t		offset = ioend->io_offset;
> -	size_t			size = ioend->io_size;
> 
> -	if (likely(!ioend->io_error)) {
> -		if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
> -			int error;
> -			error = xfs_iomap_write_unwritten(ip, offset, size);
> -			if (error)
> -				ioend->io_error = error;
> -		}
> -		xfs_setfilesize(ioend);
> +	/*
> +	 * For unwritten extents we need to issue transactions to convert a
> +	 * range to normal written extens after the data I/O has finished.
> +	 */
> +	if (ioend->io_type == IOMAP_UNWRITTEN &&
> +	    likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
> +		int error;
> +
> +		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
> +						 ioend->io_size);
> +		if (error)
> +			ioend->io_error = error;
>  	}
> -	xfs_destroy_ioend(ioend);
> -}
> -
> -/*
> - * IO read completion for regular, written extents.
> - */
> -STATIC void
> -xfs_end_bio_read(
> -	struct work_struct	*work)
> -{
> -	xfs_ioend_t		*ioend =
> -		container_of(work, xfs_ioend_t, io_work);
> 
> +	/*
> +	 * We might have to update the on-disk file size after extending
> +	 * writes.
> +	 */
> +	if (ioend->io_type != IOMAP_READ)
> +		xfs_setfilesize(ioend);
>  	xfs_destroy_ioend(ioend);
>  }
> 
> @@ -314,10 +279,10 @@ xfs_finish_ioend(
>  	int		wait)
>  {
>  	if (atomic_dec_and_test(&ioend->io_remaining)) {
> -		struct workqueue_struct *wq = xfsdatad_workqueue;
> -		if (ioend->io_work.func == xfs_end_bio_unwritten)
> -			wq = xfsconvertd_workqueue;
> +		struct workqueue_struct *wq;
> 
> +		wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
> +			xfsconvertd_workqueue : xfsdatad_workqueue;
>  		queue_work(wq, &ioend->io_work);
>  		if (wait)
>  			flush_workqueue(wq);
> @@ -355,15 +320,7 @@ xfs_alloc_ioend(
>  	ioend->io_offset = 0;
>  	ioend->io_size = 0;
> 
> -	if (type == IOMAP_UNWRITTEN)
> -		INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten);
> -	else if (type == IOMAP_DELAY)
> -		INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc);
> -	else if (type == IOMAP_READ)
> -		INIT_WORK(&ioend->io_work, xfs_end_bio_read);
> -	else
> -		INIT_WORK(&ioend->io_work, xfs_end_bio_written);
> -
> +	INIT_WORK(&ioend->io_work, xfs_end_io);
>  	return ioend;
>  }
> 
> @@ -1538,7 +1495,7 @@ xfs_end_io_direct(
>  		 * didn't map an unwritten extent so switch it's completion
>  		 * handler.
>  		 */
> -		INIT_WORK(&ioend->io_work, xfs_end_bio_written);
> +		ioend->io_type = IOMAP_NEW;
>  		xfs_finish_ioend(ioend, 0);
>  	}
> 
> 
> _______________________________________________
> xfs mailing list
> xfs at oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs




More information about the xfs mailing list