All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Liu <jeff.liu@oracle.com>
To: xfs@oss.sgi.com
Cc: Christoph Hellwig <hch@infradead.org>,
	Chris Mason <chris.mason@oracle.com>,
	aelder@sgi.com
Subject: Re: [PATCH] Introduce SEEK_DATA/SEEK_HOLE to XFS V2
Date: Tue, 22 Nov 2011 16:30:53 +0800	[thread overview]
Message-ID: <4ECB5DBD.30000@oracle.com> (raw)
In-Reply-To: <4ECB5B21.7080508@oracle.com>

CC to Dave.

Thanks,
-Jeff

On 11/22/2011 04:19 PM, Jeff Liu wrote:

> Hello,
> 
> This is the V2 attempt to add SEEK_DATA/SEEK_HOLE to XFS.
> 
> Changes:
> ========
> 1. Merge xfs_find_desired_extent() and xfs_seek_data_hole() into xfs_seek_extent(), and place it at xfs_file.c.
> 2. Using two different routines xfs_seek_data()/xfs_seek_hole() to handle SEEK_DATA/SEEK_HOLE requests respectively.
> 3. Remove some worthless result checking code from xfs_file_llseek().
> 4. s/xfs_mount_t/struct xfs_mount/g.
> 
> Tests:
> ======
> In addition to the seek_test.c I have used previously, I have also done a large sparse file copy tests, it works to me.
> 
> Hope I have not made obvious stupid mistakes this time. :-P.
> Any comments are appreciated!
> 
> 
> Signed-off-by: Jie Liu <jeff.liu@oracle.com>
> 
> ---
>  fs/xfs/xfs_file.c |  188 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 187 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 753ed9b..bb2be00 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1141,8 +1141,194 @@ xfs_vm_page_mkwrite(
>  	return block_page_mkwrite(vma, vmf, xfs_get_blocks);
>  }
>  
> +STATIC int
> +xfs_seek_data(
> +	struct xfs_inode *ip,
> +	loff_t *start)
> +{
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp;
> +	xfs_fileoff_t		fsbno;
> +	xfs_filblks_t		len;
> +	loff_t			startoff = *start;
> +	int			error = 0;
> +
> +	fsbno = XFS_B_TO_FSBT(mp, *start);
> +	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +	len = XFS_B_TO_FSB(mp, ip->i_size);
> +
> +	for (;;) {
> +		struct xfs_bmbt_irec	map[2];
> +		int			nmap = 2;
> +		loff_t			seekoff;
> +
> +		error = xfs_bmapi_read(ip, fsbno, len - fsbno, map, &nmap,
> +				       XFS_BMAPI_ENTIRE);
> +		if (error)
> +			break;
> +
> +		/* No extents at given offset, must be beyond EOF */
> +		if (!nmap) {
> +			error = ENXIO;
> +			break;
> +		}
> +
> +		seekoff = XFS_FSB_TO_B(mp, fsbno);
> +
> +		/*
> +		 * Hole handling for unwritten extents landed in a hole.
> +		 * If the next extent is a data  extent, then return the
> +		 * start of it, otherwise we need to move the start offset
> +		 * and map more blocks.
> +		 */
> +		if (map[0].br_startblock == HOLESTARTBLOCK) {
> +			if (map[1].br_startblock == HOLESTARTBLOCK) {
> +				fsbno = map[1].br_startoff +
> +					map[1].br_blockcount;
> +			} else {
> +				*start = max_t(loff_t, seekoff,
> +				       XFS_FSB_TO_B(mp, map[1].br_startoff));
> +				break;
> +			}
> +		}
> +
> +		/*
> +		 * Landed in an in-memory data extent or in an allocated
> +		 * extent.
> +		 */
> +		if (map[0].br_startoff == DELAYSTARTBLOCK ||
> +		    map[0].br_state == XFS_EXT_NORM) {
> +			*start = max_t(loff_t, seekoff,
> +				       XFS_FSB_TO_B(mp, map[0].br_startoff));
> +			break;
> +		}
> +
> +		/* return ENXIO if beyond eof */
> +		if (XFS_FSB_TO_B(mp, fsbno) > ip->i_size) {
> +			error = ENXIO;
> +			break;
> +		}
> +	}
> +
> +	if (*start < startoff)
> +		*start = startoff;
> +
> +	return error;
> +}
> +
> +STATIC int
> +xfs_seek_hole(
> +	struct xfs_inode *ip,
> +	loff_t *start)
> +{
> +	struct xfs_mount	*mp = ip->i_mount;
> +	int			error = 0;
> +	loff_t			seekoff = *start;
> +	loff_t			holeoff;
> +	xfs_fileoff_t		fsbno;
> +
> +	fsbno = XFS_B_TO_FSBT(mp, *start);
> +	error = xfs_bmap_first_unused(NULL, ip, 1, &fsbno, XFS_DATA_FORK);
> +	if (error)
> +		return error;
> +
> +	holeoff = XFS_FSB_TO_B(mp, fsbno);
> +	if (holeoff <= seekoff)
> +		*start = seekoff;
> +	else
> +		*start = min_t(loff_t, holeoff, ip->i_size);
> +
> +	return error;
> +}
> +
> +STATIC int
> +xfs_seek_extent(
> +	struct inode		*inode,
> +	loff_t			*start,
> +	u32			type)
> +{
> +	struct xfs_inode	*ip = XFS_I(inode);
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp;
> +	int			lock;
> +	int			error = 0;
> +
> +	if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
> +	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
> +	    ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
> +		return XFS_ERROR(EINVAL);
> +
> +	lock = xfs_ilock_map_shared(ip);
> +
> +	if (XFS_FORCED_SHUTDOWN(mp)) {
> +		error = EIO;
> +		goto out_lock;
> +	}
> +
> +	XFS_STATS_INC(xs_blk_mapr);
> +	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +
> +	ASSERT(ifp->if_ext_max ==
> +	      XFS_IFORK_SIZE(ip, XFS_DATA_FORK) / (uint)sizeof(xfs_bmbt_rec_t));
> +
> +	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
> +		error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
> +		if (error)
> +			goto out_lock;
> +	}
> +
> +	if (type == SEEK_HOLE)
> +		error = xfs_seek_hole(ip, start);
> +	else
> +		error = xfs_seek_data(ip, start);
> +
> +out_lock:
> +	xfs_iunlock_map_shared(ip, lock);
> +
> +	if (error)
> +		return -error;
> +
> +	return 0;
> +}
> +
> +STATIC loff_t
> +xfs_file_llseek(
> +	struct file *file,
> +	loff_t offset,
> +	int origin)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	int ret;
> +
> +	switch (origin) {
> +	case SEEK_END:
> +	case SEEK_CUR:
> +		offset = generic_file_llseek(file, offset, origin);
> +		goto out;
> +	case SEEK_DATA:
> +	case SEEK_HOLE:
> +		if (offset >= i_size_read(inode)) {
> +			ret = -ENXIO;
> +			goto error;
> +		}
> +
> +		ret = xfs_seek_extent(inode, &offset, origin);
> +		if (ret)
> +			goto error;
> +	}
> +
> +	if (offset != file->f_pos)
> +		file->f_pos = offset;
> +
> +out:
> +	return offset;
> +
> +error:
> +	return ret;
> +}
> +
>  const struct file_operations xfs_file_operations = {
> -	.llseek		= generic_file_llseek,
> +	.llseek		= xfs_file_llseek,
>  	.read		= do_sync_read,
>  	.write		= do_sync_write,
>  	.aio_read	= xfs_file_aio_read,


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

  reply	other threads:[~2011-11-22  8:31 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-22  8:19 [PATCH] Introduce SEEK_DATA/SEEK_HOLE to XFS V2 Jeff Liu
2011-11-22  8:30 ` Jeff Liu [this message]
2011-11-23  9:40 ` Christoph Hellwig
2011-11-23 14:00   ` Jeff Liu
2011-11-24  3:23   ` Dave Chinner
2011-11-24  9:02     ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4ECB5DBD.30000@oracle.com \
    --to=jeff.liu@oracle.com \
    --cc=aelder@sgi.com \
    --cc=chris.mason@oracle.com \
    --cc=hch@infradead.org \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.