linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4/10] xfs: implement xfs_perag_inumbers
@ 2013-12-28 11:20 Jeff Liu
  2014-01-07  7:08 ` Jeff Liu
  0 siblings, 1 reply; 2+ messages in thread
From: Jeff Liu @ 2013-12-28 11:20 UTC (permalink / raw)
  To: xfs@oss.sgi.com

From: Jie Liu <jeff.liu@oracle.com>

Introduce xfs_perag_inumbers(), it could be used to fetch inode inode
number tables per allocation group via a new ioctl(2) in the future.
Also, that would be a net win considering the scalability for a file
system with huge number of inodes as multiple allocation groups can be
scanned in parallel.

Refactor xfs_inumbers() with it.

Signed-off-by: Jie Liu <jeff.liu@oracle.com>
---
 fs/xfs/xfs_itable.c | 175 +++++++++++++++++++++++++++++++++-------------------
 fs/xfs/xfs_itable.h |  13 +++-
 2 files changed, 121 insertions(+), 67 deletions(-)

diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 4d262f6..b890d1f 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -569,51 +569,42 @@ xfs_inumbers_fmt(
 }
 
 /*
- * Return inode number table for the filesystem.
+ * Return inode number table in an allocation group.  Record how many elements
+ * have been written out and update the last allocation group inode number on
+ * success.  Otherwise, those values will remain the same and return error.
  */
-int					/* error status */
-xfs_inumbers(
-	struct xfs_mount	*mp,/* mount point for filesystem */
-	xfs_ino_t		*lastino,/* last inode returned */
-	int			*count,/* size of buffer/count returned */
-	void			__user *ubuffer,/* buffer with inode desc */
+static int
+xfs_perag_inumbers(
+	struct xfs_mount	*mp,
+	struct xfs_aginumbers	*aip,
+	struct xfs_inogrp	*buffer,
+	int			bcount,
 	inumbers_fmt_pf		formatter)
 {
-	xfs_agnumber_t		agno = XFS_INO_TO_AGNO(mp, *lastino);
-	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, *lastino);
-	int			left = *count;
-	struct xfs_btree_cur	*cur = NULL;
-	struct xfs_buf		*agbp = NULL;
-	struct xfs_inogrp	*buffer;
-	int			bcount;
-	int			bufidx;
+	xfs_agnumber_t		agno = aip->ai_agno;
+	xfs_agino_t		agino = *(aip->ai_lastip);
+	char			*ubuffer = aip->ai_ubuffer;
+	int			ubleft = aip->ai_icount;
+	int			bufidx = 0;
+	long			count = 0;/* # elements written out */
+	struct xfs_agi		*agi;
+	struct xfs_buf		*agbp;
+	struct xfs_btree_cur	*cur;
 	int			error;
 
-	*count = 0;
-	if (agno >= mp->m_sb.sb_agcount ||
-	    *lastino != XFS_AGINO_TO_INO(mp, agno, agino))
-		return 0;
-
-	bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
-	buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
-	bufidx = error = 0;
-	do {
+	error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
+	if (error)
+		return error;
+	agi = XFS_BUF_TO_AGI(agbp);
+	cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
+	for (;;) {
 		struct xfs_inobt_rec_incore	r;
 		int				stat;
 
-		if (!agbp) {
-			error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
-			if (error)
-				break;
-			cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
-		}
+		/* Done if failed to lookup or no inode chuck is found */
 		error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, &stat);
-		if (error)
+		if (error || stat == 0)
 			break;
-		if (!stat) {
-			/* Done, proceed to look up the next AG */
-			goto next_ag;
-		}
 
 		error = xfs_inobt_get_rec(cur, &r, &stat);
 		if (error)
@@ -621,59 +612,113 @@ xfs_inumbers(
 		XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
 
 		agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1;
-		buffer[bufidx].xi_startino =
-			XFS_AGINO_TO_INO(mp, agno, r.ir_startino);
-		buffer[bufidx].xi_alloccount =
-			XFS_INODES_PER_CHUNK - r.ir_freecount;
+		buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno,
+							      r.ir_startino);
+		buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK -
+					       r.ir_freecount;
 		buffer[bufidx].xi_allocmask = ~r.ir_free;
-		if (++bufidx == bcount) {
+		/* Run out of the given buffer range, it's time to write out */
+		if (++bufidx == ubleft) {
 			long	written;
+
 			error = formatter(ubuffer, buffer, bufidx, &written);
 			if (error)
 				break;
 			ubuffer += written;
-			*count += bufidx;
+			count += bufidx;
 			bufidx = 0;
 		}
-		if (!--left)
+		if (!--ubleft)
 			break;
 
 		error = xfs_btree_increment(cur, 0, &stat);
-		if (error)
+		if (error || stat == 0) {
+			/* Done if failed or there are no rightward entries */
 			break;
-		if (stat) {
-			/*
-			 * The agino value has already been bumped, just try
-			 * to skip up to it.
-			 */
-			agino += XFS_INODES_PER_CHUNK;
-			continue;
 		}
 
-next_ag:
-		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-		cur = NULL;
-		xfs_buf_relse(agbp);
-		agbp = NULL;
-		agino = 0;
-	} while (++agno < mp->m_sb.sb_agcount);
+		/*
+		 * The agino value has already been bumped.  Just try to skip
+		 * up to it.
+		 */
+		agino += XFS_INODES_PER_CHUNK;
+	}
 
 	if (!error) {
+		/*
+		 * There might have remaining inode number tables reside in
+		 * buffer which have not yet been written out if we iterate
+		 * beyond inode btree.  We need to handle them separately.
+		 */
 		if (bufidx) {
 			long	written;
+
 			error = formatter(ubuffer, buffer, bufidx, &written);
-			if (!error)
-				*count += bufidx;
+			if (error)
+				goto error0;
+			count += bufidx;
 		}
-		*lastino = XFS_AGINO_TO_INO(mp, agno, agino);
+		/* Update the last AG inode number */
+		*(aip->ai_lastip) = agino;
+		/* Record how many elements have been written out */
+		aip->ai_ocount = count;
 	}
 
 error0:
+	xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	xfs_buf_relse(agbp);
+
+	return error;
+}
+
+/* Return inode number table for the filesystem */
+int
+xfs_inumbers(
+	struct xfs_mount	*mp,/* mount point for filesystem */
+	xfs_ino_t		*lastinop,/* last inode returned */
+	int			*ubcountp,/* size of buffer/count returned */
+	void			__user *ubuffer,/* buffer with inode desc */
+	inumbers_fmt_pf		formatter)
+{
+	xfs_agnumber_t		agno = XFS_INO_TO_AGNO(mp, *lastinop);
+	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, *lastinop);
+	int			ubleft = *ubcountp;
+	struct xfs_inogrp	*buffer;
+	int			count;
+	int			error;
+
+	*ubcountp = 0;
+	if (agno >= mp->m_sb.sb_agcount ||
+	    *lastinop != XFS_AGINO_TO_INO(mp, agno, agino))
+		return 0;
+
+	count = MIN(ubleft, (int)(PAGE_SIZE / sizeof(*buffer)));
+	buffer = kmem_alloc(count * sizeof(*buffer), KM_SLEEP);
+	do {
+		struct xfs_aginumbers	ai;
+
+		ai.ai_agno = agno;
+		ai.ai_lastip = &agino;
+		ai.ai_icount = ubleft;
+		ai.ai_ubuffer = ubuffer;
+		ai.ai_ocount = 0;
+		error = xfs_perag_inumbers(mp, &ai, buffer, count, formatter);
+		if (error)
+			break;
+
+		*ubcountp += ai.ai_ocount;
+		ubleft -= ai.ai_ocount;
+		ASSERT(ubleft >= 0);
+		if (!ubleft)
+			break;
+
+		ubuffer = ai.ai_ubuffer;
+		agino = 0;
+	} while (++agno < mp->m_sb.sb_agcount);
+
+	if (!error)
+		*lastinop = XFS_AGINO_TO_INO(mp, agno, agino);
+
 	kmem_free(buffer);
-	if (cur)
-		xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :
-					   XFS_BTREE_NOERROR));
-	if (agbp)
-		xfs_buf_relse(agbp);
 	return error;
 }
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 60ce988..f78bbcf 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -83,17 +83,26 @@ xfs_bulkstat_one(
 
 typedef int (*inumbers_fmt_pf)(
 	void			__user *ubuffer, /* buffer to write to */
-	const xfs_inogrp_t	*buffer,	/* buffer to read from */
+	const struct xfs_inogrp	*buffer,	/* buffer to read from */
 	long			count,		/* # of elements to read */
 	long			*written);	/* # of bytes written */
 
 int
 xfs_inumbers_fmt(
 	void			__user *ubuffer, /* buffer to write to */
-	const xfs_inogrp_t	*buffer,	/* buffer to read from */
+	const struct xfs_inogrp	*buffer,	/* buffer to read from */
 	long			count,		/* # of elements to read */
 	long			*written);	/* # of bytes written */
 
+/* This structure is used for xfs_inumbers per allocation group */
+struct xfs_aginumbers {
+	xfs_agnumber_t		ai_agno;/* AG number */
+	xfs_agino_t		*ai_lastip;/* last AG inode number */
+	char			__user *ai_ubuffer;/* user buffer to write to */
+	__uint32_t		ai_icount;/* # of elements to read */
+	__uint32_t		ai_ocount;/* # of elements written */
+};
+
 int					/* error status */
 xfs_inumbers(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
-- 
1.8.3.2

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

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

* Re: [PATCH 4/10] xfs: implement xfs_perag_inumbers
  2013-12-28 11:20 [PATCH 4/10] xfs: implement xfs_perag_inumbers Jeff Liu
@ 2014-01-07  7:08 ` Jeff Liu
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Liu @ 2014-01-07  7:08 UTC (permalink / raw)
  To: xfs@oss.sgi.com

As per the discussion with Brain in "[PATCH 3/10] xfs: consolidate xfs_inumbers",

Please ignore this patch since it need a distinct fix.

Thanks,
-Jeff

On 12/28 2013 19:20 PM, Jeff Liu wrote:
> From: Jie Liu <jeff.liu@oracle.com>
> 
> Introduce xfs_perag_inumbers(), it could be used to fetch inode inode
> number tables per allocation group via a new ioctl(2) in the future.
> Also, that would be a net win considering the scalability for a file
> system with huge number of inodes as multiple allocation groups can be
> scanned in parallel.
> 
> Refactor xfs_inumbers() with it.
> 
> Signed-off-by: Jie Liu <jeff.liu@oracle.com>
> ---
>  fs/xfs/xfs_itable.c | 175 +++++++++++++++++++++++++++++++++-------------------
>  fs/xfs/xfs_itable.h |  13 +++-
>  2 files changed, 121 insertions(+), 67 deletions(-)
> 
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 4d262f6..b890d1f 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -569,51 +569,42 @@ xfs_inumbers_fmt(
>  }
>  
>  /*
> - * Return inode number table for the filesystem.
> + * Return inode number table in an allocation group.  Record how many elements
> + * have been written out and update the last allocation group inode number on
> + * success.  Otherwise, those values will remain the same and return error.
>   */
> -int					/* error status */
> -xfs_inumbers(
> -	struct xfs_mount	*mp,/* mount point for filesystem */
> -	xfs_ino_t		*lastino,/* last inode returned */
> -	int			*count,/* size of buffer/count returned */
> -	void			__user *ubuffer,/* buffer with inode desc */
> +static int
> +xfs_perag_inumbers(
> +	struct xfs_mount	*mp,
> +	struct xfs_aginumbers	*aip,
> +	struct xfs_inogrp	*buffer,
> +	int			bcount,
>  	inumbers_fmt_pf		formatter)
>  {
> -	xfs_agnumber_t		agno = XFS_INO_TO_AGNO(mp, *lastino);
> -	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, *lastino);
> -	int			left = *count;
> -	struct xfs_btree_cur	*cur = NULL;
> -	struct xfs_buf		*agbp = NULL;
> -	struct xfs_inogrp	*buffer;
> -	int			bcount;
> -	int			bufidx;
> +	xfs_agnumber_t		agno = aip->ai_agno;
> +	xfs_agino_t		agino = *(aip->ai_lastip);
> +	char			*ubuffer = aip->ai_ubuffer;
> +	int			ubleft = aip->ai_icount;
> +	int			bufidx = 0;
> +	long			count = 0;/* # elements written out */
> +	struct xfs_agi		*agi;
> +	struct xfs_buf		*agbp;
> +	struct xfs_btree_cur	*cur;
>  	int			error;
>  
> -	*count = 0;
> -	if (agno >= mp->m_sb.sb_agcount ||
> -	    *lastino != XFS_AGINO_TO_INO(mp, agno, agino))
> -		return 0;
> -
> -	bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
> -	buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
> -	bufidx = error = 0;
> -	do {
> +	error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
> +	if (error)
> +		return error;
> +	agi = XFS_BUF_TO_AGI(agbp);
> +	cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
> +	for (;;) {
>  		struct xfs_inobt_rec_incore	r;
>  		int				stat;
>  
> -		if (!agbp) {
> -			error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
> -			if (error)
> -				break;
> -			cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
> -		}
> +		/* Done if failed to lookup or no inode chuck is found */
>  		error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, &stat);
> -		if (error)
> +		if (error || stat == 0)
>  			break;
> -		if (!stat) {
> -			/* Done, proceed to look up the next AG */
> -			goto next_ag;
> -		}
>  
>  		error = xfs_inobt_get_rec(cur, &r, &stat);
>  		if (error)
> @@ -621,59 +612,113 @@ xfs_inumbers(
>  		XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
>  
>  		agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1;
> -		buffer[bufidx].xi_startino =
> -			XFS_AGINO_TO_INO(mp, agno, r.ir_startino);
> -		buffer[bufidx].xi_alloccount =
> -			XFS_INODES_PER_CHUNK - r.ir_freecount;
> +		buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno,
> +							      r.ir_startino);
> +		buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK -
> +					       r.ir_freecount;
>  		buffer[bufidx].xi_allocmask = ~r.ir_free;
> -		if (++bufidx == bcount) {
> +		/* Run out of the given buffer range, it's time to write out */
> +		if (++bufidx == ubleft) {
>  			long	written;
> +
>  			error = formatter(ubuffer, buffer, bufidx, &written);
>  			if (error)
>  				break;
>  			ubuffer += written;
> -			*count += bufidx;
> +			count += bufidx;
>  			bufidx = 0;
>  		}
> -		if (!--left)
> +		if (!--ubleft)
>  			break;
>  
>  		error = xfs_btree_increment(cur, 0, &stat);
> -		if (error)
> +		if (error || stat == 0) {
> +			/* Done if failed or there are no rightward entries */
>  			break;
> -		if (stat) {
> -			/*
> -			 * The agino value has already been bumped, just try
> -			 * to skip up to it.
> -			 */
> -			agino += XFS_INODES_PER_CHUNK;
> -			continue;
>  		}
>  
> -next_ag:
> -		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
> -		cur = NULL;
> -		xfs_buf_relse(agbp);
> -		agbp = NULL;
> -		agino = 0;
> -	} while (++agno < mp->m_sb.sb_agcount);
> +		/*
> +		 * The agino value has already been bumped.  Just try to skip
> +		 * up to it.
> +		 */
> +		agino += XFS_INODES_PER_CHUNK;
> +	}
>  
>  	if (!error) {
> +		/*
> +		 * There might have remaining inode number tables reside in
> +		 * buffer which have not yet been written out if we iterate
> +		 * beyond inode btree.  We need to handle them separately.
> +		 */
>  		if (bufidx) {
>  			long	written;
> +
>  			error = formatter(ubuffer, buffer, bufidx, &written);
> -			if (!error)
> -				*count += bufidx;
> +			if (error)
> +				goto error0;
> +			count += bufidx;
>  		}
> -		*lastino = XFS_AGINO_TO_INO(mp, agno, agino);
> +		/* Update the last AG inode number */
> +		*(aip->ai_lastip) = agino;
> +		/* Record how many elements have been written out */
> +		aip->ai_ocount = count;
>  	}
>  
>  error0:
> +	xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
> +	xfs_buf_relse(agbp);
> +
> +	return error;
> +}
> +
> +/* Return inode number table for the filesystem */
> +int
> +xfs_inumbers(
> +	struct xfs_mount	*mp,/* mount point for filesystem */
> +	xfs_ino_t		*lastinop,/* last inode returned */
> +	int			*ubcountp,/* size of buffer/count returned */
> +	void			__user *ubuffer,/* buffer with inode desc */
> +	inumbers_fmt_pf		formatter)
> +{
> +	xfs_agnumber_t		agno = XFS_INO_TO_AGNO(mp, *lastinop);
> +	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, *lastinop);
> +	int			ubleft = *ubcountp;
> +	struct xfs_inogrp	*buffer;
> +	int			count;
> +	int			error;
> +
> +	*ubcountp = 0;
> +	if (agno >= mp->m_sb.sb_agcount ||
> +	    *lastinop != XFS_AGINO_TO_INO(mp, agno, agino))
> +		return 0;
> +
> +	count = MIN(ubleft, (int)(PAGE_SIZE / sizeof(*buffer)));
> +	buffer = kmem_alloc(count * sizeof(*buffer), KM_SLEEP);
> +	do {
> +		struct xfs_aginumbers	ai;
> +
> +		ai.ai_agno = agno;
> +		ai.ai_lastip = &agino;
> +		ai.ai_icount = ubleft;
> +		ai.ai_ubuffer = ubuffer;
> +		ai.ai_ocount = 0;
> +		error = xfs_perag_inumbers(mp, &ai, buffer, count, formatter);
> +		if (error)
> +			break;
> +
> +		*ubcountp += ai.ai_ocount;
> +		ubleft -= ai.ai_ocount;
> +		ASSERT(ubleft >= 0);
> +		if (!ubleft)
> +			break;
> +
> +		ubuffer = ai.ai_ubuffer;
> +		agino = 0;
> +	} while (++agno < mp->m_sb.sb_agcount);
> +
> +	if (!error)
> +		*lastinop = XFS_AGINO_TO_INO(mp, agno, agino);
> +
>  	kmem_free(buffer);
> -	if (cur)
> -		xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :
> -					   XFS_BTREE_NOERROR));
> -	if (agbp)
> -		xfs_buf_relse(agbp);
>  	return error;
>  }
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index 60ce988..f78bbcf 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -83,17 +83,26 @@ xfs_bulkstat_one(
>  
>  typedef int (*inumbers_fmt_pf)(
>  	void			__user *ubuffer, /* buffer to write to */
> -	const xfs_inogrp_t	*buffer,	/* buffer to read from */
> +	const struct xfs_inogrp	*buffer,	/* buffer to read from */
>  	long			count,		/* # of elements to read */
>  	long			*written);	/* # of bytes written */
>  
>  int
>  xfs_inumbers_fmt(
>  	void			__user *ubuffer, /* buffer to write to */
> -	const xfs_inogrp_t	*buffer,	/* buffer to read from */
> +	const struct xfs_inogrp	*buffer,	/* buffer to read from */
>  	long			count,		/* # of elements to read */
>  	long			*written);	/* # of bytes written */
>  
> +/* This structure is used for xfs_inumbers per allocation group */
> +struct xfs_aginumbers {
> +	xfs_agnumber_t		ai_agno;/* AG number */
> +	xfs_agino_t		*ai_lastip;/* last AG inode number */
> +	char			__user *ai_ubuffer;/* user buffer to write to */
> +	__uint32_t		ai_icount;/* # of elements to read */
> +	__uint32_t		ai_ocount;/* # of elements written */
> +};
> +
>  int					/* error status */
>  xfs_inumbers(
>  	xfs_mount_t		*mp,	/* mount point for filesystem */
> 

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

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

end of thread, other threads:[~2014-01-07  7:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-28 11:20 [PATCH 4/10] xfs: implement xfs_perag_inumbers Jeff Liu
2014-01-07  7:08 ` Jeff Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).