All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Liu <jeff.liu@oracle.com>
To: jeff.liu@oracle.com
Cc: Christoph Hellwig <hch@infradead.org>,
	aelder@sgi.com, Chris Mason <chris.mason@oracle.com>,
	xfs@oss.sgi.com
Subject: Re: XFS SEEK_DATA/SEEK_HOLE support V1
Date: Sat, 19 Nov 2011 16:34:50 +0800	[thread overview]
Message-ID: <4EC76A2A.3060709@oracle.com> (raw)
In-Reply-To: <4EC768F5.4050904@oracle.com>

Sorry!! I forgot to write the subject beginning with "[PATCH]", will
re-sent it again.

Thanks,
-Jeff

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

> Hello,
> 
> Sorry for the delay! I have worked on another high priority task these days.
> 
> So the below patch is the first try to add SEEK_DATA/SEEK_HOLE to XFS, I have tested it through seek_test.c from Sunil, looks all works to me.
> http://oss.oracle.com/~smushran/seek_data/seek_test.c
> 
> Any feedback are welcome, thank you!
> 
> Signed-off-by: Jie Liu <jeff.liu@oracle.com>
> 
> ---
>  fs/xfs/xfs_bmap.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_bmap.h |    1 +
>  fs/xfs/xfs_file.c |   51 ++++++++++++++++++++++++++++++++-
>  fs/xfs/xfs_iops.c |   64 +++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_iops.h |    3 ++
>  5 files changed, 199 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
> index c68baeb..04c3930 100644
> --- a/fs/xfs/xfs_bmap.c
> +++ b/fs/xfs/xfs_bmap.c
> @@ -6133,3 +6133,84 @@ next_block:
>  
>  	return error;
>  }
> +
> +
> +int
> +xfs_seek_data_hole(
> +	struct xfs_inode	*ip,
> +	loff_t			*start,
> +	u32			type)
> +{
> +	xfs_mount_t		*mp = ip->i_mount;
> +	xfs_fileoff_t		seekoff = *start;
> +	xfs_fileoff_t		filelen;
> +	xfs_extnum_t		lastx;
> +	xfs_ifork_t		*ifp;
> +	struct xfs_bmbt_irec	got;
> +	struct xfs_bmbt_irec	prev;
> +	u64			extoff;
> +	u64			extlen;
> +	int			eof;
> +
> +	if (xfs_get_extsz_hint(ip) ||
> +	    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) {
> +		filelen = XFS_MAXIOFFSET(mp);
> +	} else {
> +		filelen = ip->i_size;
> +	}
> +
> +	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
> +	xfs_bmap_search_extents(ip, XFS_BB_TO_FSBT(mp, BTOBB(*start)),
> +				XFS_DATA_FORK, &eof, &lastx, &got, &prev);
> +
> +	if (type == SEEK_DATA) {
> +		extoff = BBTOB(XFS_FSB_TO_BB(mp, got.br_startoff));
> +		extlen = BBTOB(XFS_FSB_TO_BB(mp, got.br_blockcount));
> +
> +		if (eof) {
> +			if (seekoff < extoff + extlen)
> +				*start = seekoff;
> +			else {
> +				/*
> +				 * There is no more data region past the
> +				 * supplied offset.
> +				 */
> +				return XFS_ERROR(ENXIO);
> +			}
> +		}
> +
> +		*start = seekoff < extoff ? extoff : seekoff;
> +	} else {
> +		for (;;) {
> +			extoff = BBTOB(XFS_FSB_TO_BB(mp, got.br_startoff));
> +			extlen = BBTOB(XFS_FSB_TO_BB(mp, got.br_blockcount));
> +			if (eof) {
> +				/*
> +				 * There might be a hole at the end of the
> +				 * file, adjust to the file size.
> +				 */
> +				if (seekoff >= extoff) {
> +					*start = min_t(xfs_fileoff_t, filelen,
> +							(extoff + extlen));
> +				}
> +				break;
> +			}
> +
> +			/* A hole found */
> +			if (seekoff < extoff) {
> +				*start = seekoff;
> +				break;
> +			}
> +
> +			/* Fetch the next extent */
> +			seekoff = extoff + extlen;
> +			if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
> +				xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx),
> +						 &got);
> +			else
> +				eof = 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
> index 89ee672..964e29b 100644
> --- a/fs/xfs/xfs_bmap.h
> +++ b/fs/xfs/xfs_bmap.h
> @@ -196,6 +196,7 @@ int	xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
>  int	xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
>  		xfs_extnum_t num);
>  uint	xfs_default_attroffset(struct xfs_inode *ip);
> +int	xfs_seek_data_hole(struct xfs_inode *ip, loff_t *start, u32 type);
>  
>  #ifdef __KERNEL__
>  /* bmap to userspace formatter - copy to user & advance pointer */
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 753ed9b..bf5471b 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1141,8 +1141,57 @@ xfs_vm_page_mkwrite(
>  	return block_page_mkwrite(vma, vmf, xfs_get_blocks);
>  }
>  
> +STATIC loff_t
> +xfs_file_llseek(
> +	struct file *file,
> +	loff_t offset,
> +	int origin)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	int ret;
> +
> +	if (origin != SEEK_DATA && origin != SEEK_HOLE)
> +		return generic_file_llseek(file, offset, origin);
> +
> +	mutex_lock(&inode->i_mutex);
> +	switch (origin) {
> +	case SEEK_DATA:
> +	case SEEK_HOLE:
> +		if (offset >= i_size_read(inode)) {
> +			ret = -ENXIO;
> +			goto error;
> +		}
> +
> +		ret = xfs_find_desired_extent(inode, &offset, origin);
> +		if (ret)
> +			goto error;
> +	}
> +
> +	if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) {
> +		ret = -EINVAL;
> +		goto error;
> +	}
> +
> +	if (offset > inode->i_sb->s_maxbytes) {
> +		ret = -EINVAL;
> +		goto error;
> +	}
> +
> +	if (offset != file->f_pos) {
> +		file->f_pos = offset;
> +		file->f_version = 0;
> +	}
> +
> +	mutex_unlock(&inode->i_mutex);
> +	return offset;
> +
> +error:
> +	mutex_unlock(&inode->i_mutex);
> +	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,
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 23ce927..482c1ff 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -1030,6 +1030,70 @@ xfs_vn_fiemap(
>  	return 0;
>  }
>  
> +int
> +xfs_find_desired_extent(
> +	struct inode		*inode,
> +	loff_t			*start,
> +	u32			type)
> +{
> +	xfs_inode_t		*ip = XFS_I(inode);
> +	xfs_mount_t		*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp;
> +	int			lock;
> +	int			error;
> +
> +	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);
> +
> +	xfs_ilock(ip, XFS_IOLOCK_SHARED);
> +
> +	/*
> +	 * Flush the delay alloc blocks. Even after flushing the inode,
> +	 * there can still be delalloc blocks on the inode beyond EOF
> +	 * due to speculative preallocation. These are not removed until
> +	 * the release function is called or the inode is inactivated.
> +	 * Hence we cannot assert here that ip->i_delayed_blks == 0.
> +	 */
> +	if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) {
> +		error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
> +		if (error)
> +			goto out_unlock_iolock;
> +	}
> +
> +	lock = xfs_ilock_map_shared(ip);
> +
> +	if (XFS_FORCED_SHUTDOWN(mp)) {
> +		error = EIO;
> +		goto out_unlock_ilock;
> +	}
> +
> +	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_unlock_ilock;
> +	}
> +
> +	error = xfs_seek_data_hole(ip, start, type);
> +
> +out_unlock_ilock:
> +	xfs_iunlock_map_shared(ip, lock);
> +out_unlock_iolock:
> +	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
> +
> +	if (error)
> +		return -error;
> +
> +	return 0;
> +}
> +
>  static const struct inode_operations xfs_inode_operations = {
>  	.get_acl		= xfs_get_acl,
>  	.getattr		= xfs_vn_getattr,
> diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
> index ef41c92..ea47abd 100644
> --- a/fs/xfs/xfs_iops.h
> +++ b/fs/xfs/xfs_iops.h
> @@ -27,4 +27,7 @@ extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
>  
>  extern void xfs_setup_inode(struct xfs_inode *);
>  
> +extern int xfs_find_desired_extent(struct inode *inode, loff_t *start,
> +				   u32 type);
> +
>  #endif /* __XFS_IOPS_H__ */


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

  reply	other threads:[~2011-11-19  8:35 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-02 15:04 SEEK_DATA/SEEK_HOLE support Jeff Liu
2011-10-02 15:42 ` Christoph Hellwig
2011-10-02 16:06   ` Jeff Liu
2011-10-02 17:59     ` Christoph Hellwig
2011-10-02 19:11       ` Andi Kleen
2011-10-03  4:04       ` Jeff Liu
2011-10-03 23:43         ` Dave Chinner
2011-10-04 13:02           ` Christoph Hellwig
2011-10-05  4:36             ` Dave Chinner
2011-10-05  5:32               ` Jeff Liu
2011-10-05  9:23                 ` Dave Chinner
2011-10-05 13:56                   ` Jeff Liu
2011-10-05  7:34               ` Michael Monnerie
2011-10-05  9:36                 ` Dave Chinner
2011-10-05 18:22                   ` Michael Monnerie
2011-10-06  0:32                     ` Dave Chinner
2011-11-14 10:24 ` Christoph Hellwig
2011-11-14 12:47   ` Jeff Liu
2011-11-14 12:50     ` Christoph Hellwig
2011-11-19  8:29       ` XFS SEEK_DATA/SEEK_HOLE support V1 Jeff Liu
2011-11-19  8:34         ` Jeff Liu [this message]
2011-11-19  8:37         ` [PATCH] Introduce SEEK_DATA/SEEK_HOLE support to XFS V1 Jeff Liu
2011-11-19 19:11           ` Christoph Hellwig
2011-11-20 13:15             ` Jeff Liu
2011-11-20  0:30           ` Dave Chinner
2011-11-20 13:59             ` Jeff Liu
2011-11-20 15:30               ` Christoph Hellwig
2011-11-20 22:34                 ` Dave Chinner

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=4EC76A2A.3060709@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.