diff mbox

[7/7] xfs: Switch to iomap for seeking in quota files

Message ID 1497624680-16685-8-git-send-email-agruenba@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andreas Gruenbacher June 16, 2017, 2:51 p.m. UTC
(This patch is largely untested.)

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/xfs/xfs_dquot.c |   5 +-
 fs/xfs/xfs_file.c  | 320 -----------------------------------------------------
 fs/xfs/xfs_inode.h |   2 -
 3 files changed, 3 insertions(+), 324 deletions(-)

Comments

Darrick J. Wong June 16, 2017, 3:30 p.m. UTC | #1
On Fri, Jun 16, 2017 at 04:51:20PM +0200, Andreas Gruenbacher wrote:
> (This patch is largely untested.)

In principle the XFS bits look ok, but I think you'd be better off with
a review from hch and, uh, while you wait, a run through the xfstests
'quota' group and probably 'auto' too?

I also think the two xfs patches would be better organized either as a
pair of patches where one patch gets rid of the __xfs_seek_hole_data
calls and the second removes the __xfs_seek_hole_data implementation;
or a single patch to refactor it out of xfs in a single blow.

--D

> 
> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
> ---
>  fs/xfs/xfs_dquot.c |   5 +-
>  fs/xfs/xfs_file.c  | 320 -----------------------------------------------------
>  fs/xfs/xfs_inode.h |   2 -
>  3 files changed, 3 insertions(+), 324 deletions(-)
> 
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index 9d06cc3..a10bd921 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -39,6 +39,7 @@
>  #include "xfs_trace.h"
>  #include "xfs_log.h"
>  #include "xfs_bmap_btree.h"
> +#include "xfs_iomap.h"
>  
>  /*
>   * Lock order:
> @@ -726,8 +727,8 @@ xfs_dq_get_next_id(
>  	quotip = xfs_quota_inode(mp, type);
>  	lock = xfs_ilock_data_map_shared(quotip);
>  
> -	offset = __xfs_seek_hole_data(VFS_I(quotip), XFS_FSB_TO_B(mp, start),
> -				      eof, SEEK_DATA);
> +	offset = __iomap_seek_hole_data(VFS_I(quotip), XFS_FSB_TO_B(mp, start), eof,
> +					SEEK_DATA, &xfs_iomap_ops);
>  	if (offset < 0)
>  		error = offset;
>  
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index b36dcd7..3acbbaf 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -953,326 +953,6 @@ xfs_file_readdir(
>  	return xfs_readdir(ip, ctx, bufsize);
>  }
>  
> -/*
> - * This type is designed to indicate the type of offset we would like
> - * to search from page cache for xfs_seek_hole_data().
> - */
> -enum {
> -	HOLE_OFF = 0,
> -	DATA_OFF,
> -};
> -
> -/*
> - * Lookup the desired type of offset from the given page.
> - *
> - * On success, return true and the offset argument will point to the
> - * start of the region that was found.  Otherwise this function will
> - * return false and keep the offset argument unchanged.
> - */
> -STATIC bool
> -xfs_lookup_buffer_offset(
> -	struct page		*page,
> -	loff_t			*offset,
> -	unsigned int		type)
> -{
> -	loff_t			lastoff = page_offset(page);
> -	bool			found = false;
> -	struct buffer_head	*bh, *head;
> -
> -	bh = head = page_buffers(page);
> -	do {
> -		/*
> -		 * Unwritten extents that have data in the page
> -		 * cache covering them can be identified by the
> -		 * BH_Unwritten state flag.  Pages with multiple
> -		 * buffers might have a mix of holes, data and
> -		 * unwritten extents - any buffer with valid
> -		 * data in it should have BH_Uptodate flag set
> -		 * on it.
> -		 */
> -		if (buffer_unwritten(bh) ||
> -		    buffer_uptodate(bh)) {
> -			if (type == DATA_OFF)
> -				found = true;
> -		} else {
> -			if (type == HOLE_OFF)
> -				found = true;
> -		}
> -
> -		if (found) {
> -			*offset = lastoff;
> -			break;
> -		}
> -		lastoff += bh->b_size;
> -	} while ((bh = bh->b_this_page) != head);
> -
> -	return found;
> -}
> -
> -/*
> - * This routine is called to find out and return a data or hole offset
> - * from the page cache for unwritten extents according to the desired
> - * type for xfs_seek_hole_data().
> - *
> - * The argument offset is used to tell where we start to search from the
> - * page cache.  Map is used to figure out the end points of the range to
> - * lookup pages.
> - *
> - * Return true if the desired type of offset was found, and the argument
> - * offset is filled with that address.  Otherwise, return false and keep
> - * offset unchanged.
> - */
> -STATIC bool
> -xfs_find_get_desired_pgoff(
> -	struct inode		*inode,
> -	struct xfs_bmbt_irec	*map,
> -	unsigned int		type,
> -	loff_t			*offset)
> -{
> -	struct xfs_inode	*ip = XFS_I(inode);
> -	struct xfs_mount	*mp = ip->i_mount;
> -	struct pagevec		pvec;
> -	pgoff_t			index;
> -	pgoff_t			end;
> -	loff_t			endoff;
> -	loff_t			startoff = *offset;
> -	loff_t			lastoff = startoff;
> -	bool			found = false;
> -
> -	pagevec_init(&pvec, 0);
> -
> -	index = startoff >> PAGE_SHIFT;
> -	endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
> -	end = (endoff - 1) >> PAGE_SHIFT;
> -	do {
> -		int		want;
> -		unsigned	nr_pages;
> -		unsigned int	i;
> -
> -		want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
> -		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
> -					  want);
> -		if (nr_pages == 0)
> -			break;
> -
> -		for (i = 0; i < nr_pages; i++) {
> -			struct page	*page = pvec.pages[i];
> -			loff_t		b_offset;
> -
> -			/*
> -			 * At this point, the page may be truncated or
> -			 * invalidated (changing page->mapping to NULL),
> -			 * or even swizzled back from swapper_space to tmpfs
> -			 * file mapping. However, page->index will not change
> -			 * because we have a reference on the page.
> -			 *
> -			 * If current page offset is beyond where we've ended,
> -			 * we've found a hole.
> -			 */
> -			if (type == HOLE_OFF && lastoff < endoff &&
> -			    lastoff < page_offset(pvec.pages[i])) {
> -				found = true;
> -				*offset = lastoff;
> -				goto out;
> -			}
> -			/* Searching done if the page index is out of range. */
> -			if (page->index > end)
> -				goto out;
> -
> -			lock_page(page);
> -			/*
> -			 * Page truncated or invalidated(page->mapping == NULL).
> -			 * We can freely skip it and proceed to check the next
> -			 * page.
> -			 */
> -			if (unlikely(page->mapping != inode->i_mapping)) {
> -				unlock_page(page);
> -				continue;
> -			}
> -
> -			if (!page_has_buffers(page)) {
> -				unlock_page(page);
> -				continue;
> -			}
> -
> -			found = xfs_lookup_buffer_offset(page, &b_offset, type);
> -			if (found) {
> -				/*
> -				 * The found offset may be less than the start
> -				 * point to search if this is the first time to
> -				 * come here.
> -				 */
> -				*offset = max_t(loff_t, startoff, b_offset);
> -				unlock_page(page);
> -				goto out;
> -			}
> -
> -			/*
> -			 * We either searching data but nothing was found, or
> -			 * searching hole but found a data buffer.  In either
> -			 * case, probably the next page contains the desired
> -			 * things, update the last offset to it so.
> -			 */
> -			lastoff = page_offset(page) + PAGE_SIZE;
> -			unlock_page(page);
> -		}
> -
> -		/*
> -		 * The number of returned pages less than our desired, search
> -		 * done.
> -		 */
> -		if (nr_pages < want)
> -			break;
> -
> -		index = pvec.pages[i - 1]->index + 1;
> -		pagevec_release(&pvec);
> -	} while (index <= end);
> -
> -	/* No page at lastoff and we are not done - we found a hole. */
> -	if (type == HOLE_OFF && lastoff < endoff) {
> -		*offset = lastoff;
> -		found = true;
> -	}
> -out:
> -	pagevec_release(&pvec);
> -	return found;
> -}
> -
> -/*
> - * caller must lock inode with xfs_ilock_data_map_shared,
> - * can we craft an appropriate ASSERT?
> - *
> - * end is because the VFS-level lseek interface is defined such that any
> - * offset past i_size shall return -ENXIO, but we use this for quota code
> - * which does not maintain i_size, and we want to SEEK_DATA past i_size.
> - */
> -loff_t
> -__xfs_seek_hole_data(
> -	struct inode		*inode,
> -	loff_t			start,
> -	loff_t			end,
> -	int			whence)
> -{
> -	struct xfs_inode	*ip = XFS_I(inode);
> -	struct xfs_mount	*mp = ip->i_mount;
> -	loff_t			uninitialized_var(offset);
> -	xfs_fileoff_t		fsbno;
> -	xfs_filblks_t		lastbno;
> -	int			error;
> -
> -	if (start >= end) {
> -		error = -ENXIO;
> -		goto out_error;
> -	}
> -
> -	/*
> -	 * Try to read extents from the first block indicated
> -	 * by fsbno to the end block of the file.
> -	 */
> -	fsbno = XFS_B_TO_FSBT(mp, start);
> -	lastbno = XFS_B_TO_FSB(mp, end);
> -
> -	for (;;) {
> -		struct xfs_bmbt_irec	map[2];
> -		int			nmap = 2;
> -		unsigned int		i;
> -
> -		error = xfs_bmapi_read(ip, fsbno, lastbno - fsbno, map, &nmap,
> -				       XFS_BMAPI_ENTIRE);
> -		if (error)
> -			goto out_error;
> -
> -		/* No extents at given offset, must be beyond EOF */
> -		if (nmap == 0) {
> -			error = -ENXIO;
> -			goto out_error;
> -		}
> -
> -		for (i = 0; i < nmap; i++) {
> -			offset = max_t(loff_t, start,
> -				       XFS_FSB_TO_B(mp, map[i].br_startoff));
> -
> -			/* Landed in the hole we wanted? */
> -			if (whence == SEEK_HOLE &&
> -			    map[i].br_startblock == HOLESTARTBLOCK)
> -				goto out;
> -
> -			/* Landed in the data extent we wanted? */
> -			if (whence == SEEK_DATA &&
> -			    (map[i].br_startblock == DELAYSTARTBLOCK ||
> -			     (map[i].br_state == XFS_EXT_NORM &&
> -			      !isnullstartblock(map[i].br_startblock))))
> -				goto out;
> -
> -			/*
> -			 * Landed in an unwritten extent, try to search
> -			 * for hole or data from page cache.
> -			 */
> -			if (map[i].br_state == XFS_EXT_UNWRITTEN) {
> -				if (xfs_find_get_desired_pgoff(inode, &map[i],
> -				      whence == SEEK_HOLE ? HOLE_OFF : DATA_OFF,
> -							&offset))
> -					goto out;
> -			}
> -		}
> -
> -		/*
> -		 * We only received one extent out of the two requested. This
> -		 * means we've hit EOF and didn't find what we are looking for.
> -		 */
> -		if (nmap == 1) {
> -			/*
> -			 * If we were looking for a hole, set offset to
> -			 * the end of the file (i.e., there is an implicit
> -			 * hole at the end of any file).
> -		 	 */
> -			if (whence == SEEK_HOLE) {
> -				offset = end;
> -				break;
> -			}
> -			/*
> -			 * If we were looking for data, it's nowhere to be found
> -			 */
> -			ASSERT(whence == SEEK_DATA);
> -			error = -ENXIO;
> -			goto out_error;
> -		}
> -
> -		ASSERT(i > 1);
> -
> -		/*
> -		 * Nothing was found, proceed to the next round of search
> -		 * if the next reading offset is not at or beyond EOF.
> -		 */
> -		fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount;
> -		start = XFS_FSB_TO_B(mp, fsbno);
> -		if (start >= end) {
> -			if (whence == SEEK_HOLE) {
> -				offset = end;
> -				break;
> -			}
> -			ASSERT(whence == SEEK_DATA);
> -			error = -ENXIO;
> -			goto out_error;
> -		}
> -	}
> -
> -out:
> -	/*
> -	 * If at this point we have found the hole we wanted, the returned
> -	 * offset may be bigger than the file size as it may be aligned to
> -	 * page boundary for unwritten extents.  We need to deal with this
> -	 * situation in particular.
> -	 */
> -	if (whence == SEEK_HOLE)
> -		offset = min_t(loff_t, offset, end);
> -
> -	return offset;
> -
> -out_error:
> -	return error;
> -}
> -
>  STATIC loff_t
>  xfs_seek_hole_data(
>  	struct file		*file,
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 10e89fc..17c441a 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -445,8 +445,6 @@ int	xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
>  		     xfs_fsize_t isize, bool *did_zeroing);
>  int	xfs_zero_range(struct xfs_inode *ip, xfs_off_t pos, xfs_off_t count,
>  		bool *did_zero);
> -loff_t	__xfs_seek_hole_data(struct inode *inode, loff_t start,
> -			     loff_t eof, int whence);
>  
>  
>  /* from xfs_iops.c */
> -- 
> 2.7.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christoph Hellwig June 20, 2017, 6:31 a.m. UTC | #2
On Fri, Jun 16, 2017 at 08:30:29AM -0700, Darrick J. Wong wrote:
> On Fri, Jun 16, 2017 at 04:51:20PM +0200, Andreas Gruenbacher wrote:
> > (This patch is largely untested.)
> 
> In principle the XFS bits look ok, but I think you'd be better off with
> a review from hch and, uh, while you wait, a run through the xfstests
> 'quota' group and probably 'auto' too?

I think for the quota code we should simply not even use seek
hole / data.  Quota files don't have delayed allocations, unwritten
extents or COW forks, so it's just a trivial lookup in the extent
list.  I'll fix that part up to make Andreas' life easier.
diff mbox

Patch

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 9d06cc3..a10bd921 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -39,6 +39,7 @@ 
 #include "xfs_trace.h"
 #include "xfs_log.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_iomap.h"
 
 /*
  * Lock order:
@@ -726,8 +727,8 @@  xfs_dq_get_next_id(
 	quotip = xfs_quota_inode(mp, type);
 	lock = xfs_ilock_data_map_shared(quotip);
 
-	offset = __xfs_seek_hole_data(VFS_I(quotip), XFS_FSB_TO_B(mp, start),
-				      eof, SEEK_DATA);
+	offset = __iomap_seek_hole_data(VFS_I(quotip), XFS_FSB_TO_B(mp, start), eof,
+					SEEK_DATA, &xfs_iomap_ops);
 	if (offset < 0)
 		error = offset;
 
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index b36dcd7..3acbbaf 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -953,326 +953,6 @@  xfs_file_readdir(
 	return xfs_readdir(ip, ctx, bufsize);
 }
 
-/*
- * This type is designed to indicate the type of offset we would like
- * to search from page cache for xfs_seek_hole_data().
- */
-enum {
-	HOLE_OFF = 0,
-	DATA_OFF,
-};
-
-/*
- * Lookup the desired type of offset from the given page.
- *
- * On success, return true and the offset argument will point to the
- * start of the region that was found.  Otherwise this function will
- * return false and keep the offset argument unchanged.
- */
-STATIC bool
-xfs_lookup_buffer_offset(
-	struct page		*page,
-	loff_t			*offset,
-	unsigned int		type)
-{
-	loff_t			lastoff = page_offset(page);
-	bool			found = false;
-	struct buffer_head	*bh, *head;
-
-	bh = head = page_buffers(page);
-	do {
-		/*
-		 * Unwritten extents that have data in the page
-		 * cache covering them can be identified by the
-		 * BH_Unwritten state flag.  Pages with multiple
-		 * buffers might have a mix of holes, data and
-		 * unwritten extents - any buffer with valid
-		 * data in it should have BH_Uptodate flag set
-		 * on it.
-		 */
-		if (buffer_unwritten(bh) ||
-		    buffer_uptodate(bh)) {
-			if (type == DATA_OFF)
-				found = true;
-		} else {
-			if (type == HOLE_OFF)
-				found = true;
-		}
-
-		if (found) {
-			*offset = lastoff;
-			break;
-		}
-		lastoff += bh->b_size;
-	} while ((bh = bh->b_this_page) != head);
-
-	return found;
-}
-
-/*
- * This routine is called to find out and return a data or hole offset
- * from the page cache for unwritten extents according to the desired
- * type for xfs_seek_hole_data().
- *
- * The argument offset is used to tell where we start to search from the
- * page cache.  Map is used to figure out the end points of the range to
- * lookup pages.
- *
- * Return true if the desired type of offset was found, and the argument
- * offset is filled with that address.  Otherwise, return false and keep
- * offset unchanged.
- */
-STATIC bool
-xfs_find_get_desired_pgoff(
-	struct inode		*inode,
-	struct xfs_bmbt_irec	*map,
-	unsigned int		type,
-	loff_t			*offset)
-{
-	struct xfs_inode	*ip = XFS_I(inode);
-	struct xfs_mount	*mp = ip->i_mount;
-	struct pagevec		pvec;
-	pgoff_t			index;
-	pgoff_t			end;
-	loff_t			endoff;
-	loff_t			startoff = *offset;
-	loff_t			lastoff = startoff;
-	bool			found = false;
-
-	pagevec_init(&pvec, 0);
-
-	index = startoff >> PAGE_SHIFT;
-	endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
-	end = (endoff - 1) >> PAGE_SHIFT;
-	do {
-		int		want;
-		unsigned	nr_pages;
-		unsigned int	i;
-
-		want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
-		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
-					  want);
-		if (nr_pages == 0)
-			break;
-
-		for (i = 0; i < nr_pages; i++) {
-			struct page	*page = pvec.pages[i];
-			loff_t		b_offset;
-
-			/*
-			 * At this point, the page may be truncated or
-			 * invalidated (changing page->mapping to NULL),
-			 * or even swizzled back from swapper_space to tmpfs
-			 * file mapping. However, page->index will not change
-			 * because we have a reference on the page.
-			 *
-			 * If current page offset is beyond where we've ended,
-			 * we've found a hole.
-			 */
-			if (type == HOLE_OFF && lastoff < endoff &&
-			    lastoff < page_offset(pvec.pages[i])) {
-				found = true;
-				*offset = lastoff;
-				goto out;
-			}
-			/* Searching done if the page index is out of range. */
-			if (page->index > end)
-				goto out;
-
-			lock_page(page);
-			/*
-			 * Page truncated or invalidated(page->mapping == NULL).
-			 * We can freely skip it and proceed to check the next
-			 * page.
-			 */
-			if (unlikely(page->mapping != inode->i_mapping)) {
-				unlock_page(page);
-				continue;
-			}
-
-			if (!page_has_buffers(page)) {
-				unlock_page(page);
-				continue;
-			}
-
-			found = xfs_lookup_buffer_offset(page, &b_offset, type);
-			if (found) {
-				/*
-				 * The found offset may be less than the start
-				 * point to search if this is the first time to
-				 * come here.
-				 */
-				*offset = max_t(loff_t, startoff, b_offset);
-				unlock_page(page);
-				goto out;
-			}
-
-			/*
-			 * We either searching data but nothing was found, or
-			 * searching hole but found a data buffer.  In either
-			 * case, probably the next page contains the desired
-			 * things, update the last offset to it so.
-			 */
-			lastoff = page_offset(page) + PAGE_SIZE;
-			unlock_page(page);
-		}
-
-		/*
-		 * The number of returned pages less than our desired, search
-		 * done.
-		 */
-		if (nr_pages < want)
-			break;
-
-		index = pvec.pages[i - 1]->index + 1;
-		pagevec_release(&pvec);
-	} while (index <= end);
-
-	/* No page at lastoff and we are not done - we found a hole. */
-	if (type == HOLE_OFF && lastoff < endoff) {
-		*offset = lastoff;
-		found = true;
-	}
-out:
-	pagevec_release(&pvec);
-	return found;
-}
-
-/*
- * caller must lock inode with xfs_ilock_data_map_shared,
- * can we craft an appropriate ASSERT?
- *
- * end is because the VFS-level lseek interface is defined such that any
- * offset past i_size shall return -ENXIO, but we use this for quota code
- * which does not maintain i_size, and we want to SEEK_DATA past i_size.
- */
-loff_t
-__xfs_seek_hole_data(
-	struct inode		*inode,
-	loff_t			start,
-	loff_t			end,
-	int			whence)
-{
-	struct xfs_inode	*ip = XFS_I(inode);
-	struct xfs_mount	*mp = ip->i_mount;
-	loff_t			uninitialized_var(offset);
-	xfs_fileoff_t		fsbno;
-	xfs_filblks_t		lastbno;
-	int			error;
-
-	if (start >= end) {
-		error = -ENXIO;
-		goto out_error;
-	}
-
-	/*
-	 * Try to read extents from the first block indicated
-	 * by fsbno to the end block of the file.
-	 */
-	fsbno = XFS_B_TO_FSBT(mp, start);
-	lastbno = XFS_B_TO_FSB(mp, end);
-
-	for (;;) {
-		struct xfs_bmbt_irec	map[2];
-		int			nmap = 2;
-		unsigned int		i;
-
-		error = xfs_bmapi_read(ip, fsbno, lastbno - fsbno, map, &nmap,
-				       XFS_BMAPI_ENTIRE);
-		if (error)
-			goto out_error;
-
-		/* No extents at given offset, must be beyond EOF */
-		if (nmap == 0) {
-			error = -ENXIO;
-			goto out_error;
-		}
-
-		for (i = 0; i < nmap; i++) {
-			offset = max_t(loff_t, start,
-				       XFS_FSB_TO_B(mp, map[i].br_startoff));
-
-			/* Landed in the hole we wanted? */
-			if (whence == SEEK_HOLE &&
-			    map[i].br_startblock == HOLESTARTBLOCK)
-				goto out;
-
-			/* Landed in the data extent we wanted? */
-			if (whence == SEEK_DATA &&
-			    (map[i].br_startblock == DELAYSTARTBLOCK ||
-			     (map[i].br_state == XFS_EXT_NORM &&
-			      !isnullstartblock(map[i].br_startblock))))
-				goto out;
-
-			/*
-			 * Landed in an unwritten extent, try to search
-			 * for hole or data from page cache.
-			 */
-			if (map[i].br_state == XFS_EXT_UNWRITTEN) {
-				if (xfs_find_get_desired_pgoff(inode, &map[i],
-				      whence == SEEK_HOLE ? HOLE_OFF : DATA_OFF,
-							&offset))
-					goto out;
-			}
-		}
-
-		/*
-		 * We only received one extent out of the two requested. This
-		 * means we've hit EOF and didn't find what we are looking for.
-		 */
-		if (nmap == 1) {
-			/*
-			 * If we were looking for a hole, set offset to
-			 * the end of the file (i.e., there is an implicit
-			 * hole at the end of any file).
-		 	 */
-			if (whence == SEEK_HOLE) {
-				offset = end;
-				break;
-			}
-			/*
-			 * If we were looking for data, it's nowhere to be found
-			 */
-			ASSERT(whence == SEEK_DATA);
-			error = -ENXIO;
-			goto out_error;
-		}
-
-		ASSERT(i > 1);
-
-		/*
-		 * Nothing was found, proceed to the next round of search
-		 * if the next reading offset is not at or beyond EOF.
-		 */
-		fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount;
-		start = XFS_FSB_TO_B(mp, fsbno);
-		if (start >= end) {
-			if (whence == SEEK_HOLE) {
-				offset = end;
-				break;
-			}
-			ASSERT(whence == SEEK_DATA);
-			error = -ENXIO;
-			goto out_error;
-		}
-	}
-
-out:
-	/*
-	 * If at this point we have found the hole we wanted, the returned
-	 * offset may be bigger than the file size as it may be aligned to
-	 * page boundary for unwritten extents.  We need to deal with this
-	 * situation in particular.
-	 */
-	if (whence == SEEK_HOLE)
-		offset = min_t(loff_t, offset, end);
-
-	return offset;
-
-out_error:
-	return error;
-}
-
 STATIC loff_t
 xfs_seek_hole_data(
 	struct file		*file,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 10e89fc..17c441a 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -445,8 +445,6 @@  int	xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
 		     xfs_fsize_t isize, bool *did_zeroing);
 int	xfs_zero_range(struct xfs_inode *ip, xfs_off_t pos, xfs_off_t count,
 		bool *did_zero);
-loff_t	__xfs_seek_hole_data(struct inode *inode, loff_t start,
-			     loff_t eof, int whence);
 
 
 /* from xfs_iops.c */