linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* simplify the blockgc iwalk infrastructure
@ 2021-03-24  7:03 Christoph Hellwig
  2021-03-24  7:03 ` [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes Christoph Hellwig
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Christoph Hellwig @ 2021-03-24  7:03 UTC (permalink / raw)
  To: linux-xfs

Hi all,

this series switches quotaoff to use the VFS s_inodes list and then
simplifies the iwalk infrastructure for its only remaining user.

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

* [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes
  2021-03-24  7:03 simplify the blockgc iwalk infrastructure Christoph Hellwig
@ 2021-03-24  7:03 ` Christoph Hellwig
  2021-03-24 17:50   ` Darrick J. Wong
  2021-03-24  7:03 ` [PATCH 2/3] xfs: simplify the perage inode walk infrastructure Christoph Hellwig
  2021-03-24  7:03 ` [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback Christoph Hellwig
  2 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2021-03-24  7:03 UTC (permalink / raw)
  To: linux-xfs

Using xfs_inode_walk in xfs_qm_dqrele_all_inodes is complete overkill,
given that function simplify wants to iterate all live inodes known
to the VFS.  Just iterate over the s_inodes list.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_icache.c      |  2 +-
 fs/xfs/xfs_icache.h      |  2 ++
 fs/xfs/xfs_qm_syscalls.c | 56 +++++++++++++++++++++++++---------------
 3 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 1d7720a0c068b7..c0d084e3526a9c 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -233,7 +233,7 @@ xfs_inode_clear_reclaim_tag(
 	xfs_perag_clear_reclaim_tag(pag);
 }
 
-static void
+void
 xfs_inew_wait(
 	struct xfs_inode	*ip)
 {
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index d1fddb1524200b..d70d93c2bb1084 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -78,4 +78,6 @@ int xfs_icache_inode_is_allocated(struct xfs_mount *mp, struct xfs_trans *tp,
 void xfs_blockgc_stop(struct xfs_mount *mp);
 void xfs_blockgc_start(struct xfs_mount *mp);
 
+void xfs_inew_wait(struct xfs_inode *ip);
+
 #endif
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index ca1b57d291dc90..88dfd520ae91de 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -748,41 +748,27 @@ xfs_qm_scall_getquota_next(
 	return error;
 }
 
-STATIC int
+static void
 xfs_dqrele_inode(
 	struct xfs_inode	*ip,
-	void			*args)
+	uint			flags)
 {
-	uint			*flags = args;
-
-	/* skip quota inodes */
-	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
-	    ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
-	    ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
-		ASSERT(ip->i_udquot == NULL);
-		ASSERT(ip->i_gdquot == NULL);
-		ASSERT(ip->i_pdquot == NULL);
-		return 0;
-	}
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	if ((*flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
+	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 		xfs_qm_dqrele(ip->i_udquot);
 		ip->i_udquot = NULL;
 	}
-	if ((*flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
+	if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
 		xfs_qm_dqrele(ip->i_gdquot);
 		ip->i_gdquot = NULL;
 	}
-	if ((*flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
+	if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
 		xfs_qm_dqrele(ip->i_pdquot);
 		ip->i_pdquot = NULL;
 	}
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	return 0;
 }
 
-
 /*
  * Go thru all the inodes in the file system, releasing their dquots.
  *
@@ -794,7 +780,35 @@ xfs_qm_dqrele_all_inodes(
 	struct xfs_mount	*mp,
 	uint			flags)
 {
+	struct super_block	*sb = mp->m_super;
+	struct inode		*inode, *old_inode = NULL;
+
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_walk(mp, XFS_INODE_WALK_INEW_WAIT, xfs_dqrele_inode,
-			&flags, XFS_ICI_NO_TAG);
+
+	spin_lock(&sb->s_inode_list_lock);
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+		struct xfs_inode	*ip = XFS_I(inode);
+
+		if (XFS_FORCED_SHUTDOWN(mp))
+			break;
+		if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
+			continue;
+		if (xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
+			continue;
+		if (!igrab(inode))
+			continue;
+		spin_unlock(&sb->s_inode_list_lock);
+
+		iput(old_inode);
+		old_inode = inode;
+
+		if (xfs_iflags_test(ip, XFS_INEW))
+			xfs_inew_wait(ip);
+		xfs_dqrele_inode(ip, flags);
+
+		spin_lock(&sb->s_inode_list_lock);
+	}
+	spin_unlock(&sb->s_inode_list_lock);
+
+	iput(old_inode);
 }
-- 
2.30.1


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

* [PATCH 2/3] xfs: simplify the perage inode walk infrastructure
  2021-03-24  7:03 simplify the blockgc iwalk infrastructure Christoph Hellwig
  2021-03-24  7:03 ` [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes Christoph Hellwig
@ 2021-03-24  7:03 ` Christoph Hellwig
  2021-03-24 17:57   ` Darrick J. Wong
  2021-03-24  7:03 ` [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback Christoph Hellwig
  2 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2021-03-24  7:03 UTC (permalink / raw)
  To: linux-xfs

Remove the generic xfs_inode_walk and just open code the only caller.
Note that this leads to a somewhat ugly forward delcaration for
xfs_blockgc_scan_inode, but with other changes in that area pending
it seems like the lesser evil.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_icache.c | 103 +++++++++++++-------------------------------
 fs/xfs/xfs_icache.h |  11 -----
 2 files changed, 30 insertions(+), 84 deletions(-)

diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index c0d084e3526a9c..7fdf77df66269c 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -728,11 +728,9 @@ xfs_icache_inode_is_allocated(
  */
 STATIC bool
 xfs_inode_walk_ag_grab(
-	struct xfs_inode	*ip,
-	int			flags)
+	struct xfs_inode	*ip)
 {
 	struct inode		*inode = VFS_I(ip);
-	bool			newinos = !!(flags & XFS_INODE_WALK_INEW_WAIT);
 
 	ASSERT(rcu_read_lock_held());
 
@@ -742,8 +740,7 @@ xfs_inode_walk_ag_grab(
 		goto out_unlock_noent;
 
 	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
-	if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
-	    __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
+	if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
 		goto out_unlock_noent;
 	spin_unlock(&ip->i_flags_lock);
 
@@ -763,17 +760,19 @@ xfs_inode_walk_ag_grab(
 	return false;
 }
 
+static int
+xfs_blockgc_scan_inode(
+	struct xfs_inode	*ip,
+	void			*args);
+
 /*
  * For a given per-AG structure @pag, grab, @execute, and rele all incore
  * inodes with the given radix tree @tag.
  */
 STATIC int
-xfs_inode_walk_ag(
+xfs_blockgc_free_space_ag(
 	struct xfs_perag	*pag,
-	int			iter_flags,
-	int			(*execute)(struct xfs_inode *ip, void *args),
-	void			*args,
-	int			tag)
+	struct xfs_eofblocks	*eofb)
 {
 	struct xfs_mount	*mp = pag->pag_mount;
 	uint32_t		first_index;
@@ -793,17 +792,9 @@ xfs_inode_walk_ag(
 		int		i;
 
 		rcu_read_lock();
-
-		if (tag == XFS_ICI_NO_TAG)
-			nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
-					(void **)batch, first_index,
-					XFS_LOOKUP_BATCH);
-		else
-			nr_found = radix_tree_gang_lookup_tag(
-					&pag->pag_ici_root,
-					(void **) batch, first_index,
-					XFS_LOOKUP_BATCH, tag);
-
+		nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
+				(void **) batch, first_index,
+				XFS_LOOKUP_BATCH, XFS_ICI_BLOCKGC_TAG);
 		if (!nr_found) {
 			rcu_read_unlock();
 			break;
@@ -816,7 +807,7 @@ xfs_inode_walk_ag(
 		for (i = 0; i < nr_found; i++) {
 			struct xfs_inode *ip = batch[i];
 
-			if (done || !xfs_inode_walk_ag_grab(ip, iter_flags))
+			if (done || !xfs_inode_walk_ag_grab(ip))
 				batch[i] = NULL;
 
 			/*
@@ -844,10 +835,7 @@ xfs_inode_walk_ag(
 		for (i = 0; i < nr_found; i++) {
 			if (!batch[i])
 				continue;
-			if ((iter_flags & XFS_INODE_WALK_INEW_WAIT) &&
-			    xfs_iflags_test(batch[i], XFS_INEW))
-				xfs_inew_wait(batch[i]);
-			error = execute(batch[i], args);
+			error = xfs_blockgc_scan_inode(batch[i], eofb);
 			xfs_irele(batch[i]);
 			if (error == -EAGAIN) {
 				skipped++;
@@ -872,49 +860,6 @@ xfs_inode_walk_ag(
 	return last_error;
 }
 
-/* Fetch the next (possibly tagged) per-AG structure. */
-static inline struct xfs_perag *
-xfs_inode_walk_get_perag(
-	struct xfs_mount	*mp,
-	xfs_agnumber_t		agno,
-	int			tag)
-{
-	if (tag == XFS_ICI_NO_TAG)
-		return xfs_perag_get(mp, agno);
-	return xfs_perag_get_tag(mp, agno, tag);
-}
-
-/*
- * Call the @execute function on all incore inodes matching the radix tree
- * @tag.
- */
-int
-xfs_inode_walk(
-	struct xfs_mount	*mp,
-	int			iter_flags,
-	int			(*execute)(struct xfs_inode *ip, void *args),
-	void			*args,
-	int			tag)
-{
-	struct xfs_perag	*pag;
-	int			error = 0;
-	int			last_error = 0;
-	xfs_agnumber_t		ag;
-
-	ag = 0;
-	while ((pag = xfs_inode_walk_get_perag(mp, ag, tag))) {
-		ag = pag->pag_agno + 1;
-		error = xfs_inode_walk_ag(pag, iter_flags, execute, args, tag);
-		xfs_perag_put(pag);
-		if (error) {
-			last_error = error;
-			if (error == -EFSCORRUPTED)
-				break;
-		}
-	}
-	return last_error;
-}
-
 /*
  * Grab the inode for reclaim exclusively.
  *
@@ -1617,8 +1562,7 @@ xfs_blockgc_worker(
 
 	if (!sb_start_write_trylock(mp->m_super))
 		return;
-	error = xfs_inode_walk_ag(pag, 0, xfs_blockgc_scan_inode, NULL,
-			XFS_ICI_BLOCKGC_TAG);
+	error = xfs_blockgc_free_space_ag(pag, NULL);
 	if (error)
 		xfs_info(mp, "AG %u preallocation gc worker failed, err=%d",
 				pag->pag_agno, error);
@@ -1634,10 +1578,23 @@ xfs_blockgc_free_space(
 	struct xfs_mount	*mp,
 	struct xfs_eofblocks	*eofb)
 {
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		ag = 0;
+	int			error = 0, last_error = 0;
+
 	trace_xfs_blockgc_free_space(mp, eofb, _RET_IP_);
 
-	return xfs_inode_walk(mp, 0, xfs_blockgc_scan_inode, eofb,
-			XFS_ICI_BLOCKGC_TAG);
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_BLOCKGC_TAG))) {
+		ag = pag->pag_agno + 1;
+		error = xfs_blockgc_free_space_ag(pag, eofb);
+		xfs_perag_put(pag);
+		if (error) {
+			if (error == -EFSCORRUPTED)
+				return error;
+			last_error = error;
+		}
+	}
+	return last_error;
 }
 
 /*
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index d70d93c2bb1084..da390097546c67 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -20,8 +20,6 @@ struct xfs_eofblocks {
 /*
  * tags for inode radix tree
  */
-#define XFS_ICI_NO_TAG		(-1)	/* special flag for an untagged lookup
-					   in xfs_inode_walk */
 #define XFS_ICI_RECLAIM_TAG	0	/* inode is to be reclaimed */
 /* Inode has speculative preallocations (posteof or cow) to clean. */
 #define XFS_ICI_BLOCKGC_TAG	1
@@ -34,11 +32,6 @@ struct xfs_eofblocks {
 #define XFS_IGET_DONTCACHE	0x4
 #define XFS_IGET_INCORE		0x8	/* don't read from disk or reinit */
 
-/*
- * flags for AG inode iterator
- */
-#define XFS_INODE_WALK_INEW_WAIT	0x1	/* wait on new inodes */
-
 int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
 	     uint flags, uint lock_flags, xfs_inode_t **ipp);
 
@@ -68,10 +61,6 @@ void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip);
 
 void xfs_blockgc_worker(struct work_struct *work);
 
-int xfs_inode_walk(struct xfs_mount *mp, int iter_flags,
-	int (*execute)(struct xfs_inode *ip, void *args),
-	void *args, int tag);
-
 int xfs_icache_inode_is_allocated(struct xfs_mount *mp, struct xfs_trans *tp,
 				  xfs_ino_t ino, bool *inuse);
 
-- 
2.30.1


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

* [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback
  2021-03-24  7:03 simplify the blockgc iwalk infrastructure Christoph Hellwig
  2021-03-24  7:03 ` [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes Christoph Hellwig
  2021-03-24  7:03 ` [PATCH 2/3] xfs: simplify the perage inode walk infrastructure Christoph Hellwig
@ 2021-03-24  7:03 ` Christoph Hellwig
  2021-03-24 18:03   ` Darrick J. Wong
  2 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2021-03-24  7:03 UTC (permalink / raw)
  To: linux-xfs

Pass the actual structure instead of a void pointer here now
that none of the functions is used as a callback.

Signed-off-by: Christoph Hellwig <hch@lst.de>
 xfs_inode_free_cowblocks(
---
 fs/xfs/xfs_icache.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 7fdf77df66269c..06286b5b613252 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -763,7 +763,7 @@ xfs_inode_walk_ag_grab(
 static int
 xfs_blockgc_scan_inode(
 	struct xfs_inode	*ip,
-	void			*args);
+	struct xfs_eofblocks	*eofb);
 
 /*
  * For a given per-AG structure @pag, grab, @execute, and rele all incore
@@ -1228,10 +1228,9 @@ xfs_reclaim_worker(
 STATIC int
 xfs_inode_free_eofblocks(
 	struct xfs_inode	*ip,
-	void			*args,
+	struct xfs_eofblocks	*eofb,
 	unsigned int		*lockflags)
 {
-	struct xfs_eofblocks	*eofb = args;
 	bool			wait;
 
 	wait = eofb && (eofb->eof_flags & XFS_EOF_FLAGS_SYNC);
@@ -1436,10 +1435,9 @@ xfs_prep_free_cowblocks(
 STATIC int
 xfs_inode_free_cowblocks(
 	struct xfs_inode	*ip,
-	void			*args,
+	struct xfs_eofblocks	*eofb,
 	unsigned int		*lockflags)
 {
-	struct xfs_eofblocks	*eofb = args;
 	bool			wait;
 	int			ret = 0;
 
@@ -1534,16 +1532,16 @@ xfs_blockgc_start(
 static int
 xfs_blockgc_scan_inode(
 	struct xfs_inode	*ip,
-	void			*args)
+	struct xfs_eofblocks	*eofb)
 {
 	unsigned int		lockflags = 0;
 	int			error;
 
-	error = xfs_inode_free_eofblocks(ip, args, &lockflags);
+	error = xfs_inode_free_eofblocks(ip, eofb, &lockflags);
 	if (error)
 		goto unlock;
 
-	error = xfs_inode_free_cowblocks(ip, args, &lockflags);
+	error = xfs_inode_free_cowblocks(ip, eofb, &lockflags);
 unlock:
 	if (lockflags)
 		xfs_iunlock(ip, lockflags);
-- 
2.30.1


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

* Re: [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes
  2021-03-24  7:03 ` [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes Christoph Hellwig
@ 2021-03-24 17:50   ` Darrick J. Wong
  0 siblings, 0 replies; 9+ messages in thread
From: Darrick J. Wong @ 2021-03-24 17:50 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Mar 24, 2021 at 08:03:05AM +0100, Christoph Hellwig wrote:
> Using xfs_inode_walk in xfs_qm_dqrele_all_inodes is complete overkill,
> given that function simplify wants to iterate all live inodes known
> to the VFS.  Just iterate over the s_inodes list.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Seems fine to me...
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/xfs/xfs_icache.c      |  2 +-
>  fs/xfs/xfs_icache.h      |  2 ++
>  fs/xfs/xfs_qm_syscalls.c | 56 +++++++++++++++++++++++++---------------
>  3 files changed, 38 insertions(+), 22 deletions(-)
> 
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 1d7720a0c068b7..c0d084e3526a9c 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -233,7 +233,7 @@ xfs_inode_clear_reclaim_tag(
>  	xfs_perag_clear_reclaim_tag(pag);
>  }
>  
> -static void
> +void
>  xfs_inew_wait(
>  	struct xfs_inode	*ip)
>  {
> diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
> index d1fddb1524200b..d70d93c2bb1084 100644
> --- a/fs/xfs/xfs_icache.h
> +++ b/fs/xfs/xfs_icache.h
> @@ -78,4 +78,6 @@ int xfs_icache_inode_is_allocated(struct xfs_mount *mp, struct xfs_trans *tp,
>  void xfs_blockgc_stop(struct xfs_mount *mp);
>  void xfs_blockgc_start(struct xfs_mount *mp);
>  
> +void xfs_inew_wait(struct xfs_inode *ip);
> +
>  #endif
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index ca1b57d291dc90..88dfd520ae91de 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -748,41 +748,27 @@ xfs_qm_scall_getquota_next(
>  	return error;
>  }
>  
> -STATIC int
> +static void
>  xfs_dqrele_inode(
>  	struct xfs_inode	*ip,
> -	void			*args)
> +	uint			flags)
>  {
> -	uint			*flags = args;
> -
> -	/* skip quota inodes */
> -	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
> -	    ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
> -	    ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
> -		ASSERT(ip->i_udquot == NULL);
> -		ASSERT(ip->i_gdquot == NULL);
> -		ASSERT(ip->i_pdquot == NULL);
> -		return 0;
> -	}
> -
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -	if ((*flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
> +	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
>  		xfs_qm_dqrele(ip->i_udquot);
>  		ip->i_udquot = NULL;
>  	}
> -	if ((*flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
> +	if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
>  		xfs_qm_dqrele(ip->i_gdquot);
>  		ip->i_gdquot = NULL;
>  	}
> -	if ((*flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
> +	if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
>  		xfs_qm_dqrele(ip->i_pdquot);
>  		ip->i_pdquot = NULL;
>  	}
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
> -	return 0;
>  }
>  
> -
>  /*
>   * Go thru all the inodes in the file system, releasing their dquots.
>   *
> @@ -794,7 +780,35 @@ xfs_qm_dqrele_all_inodes(
>  	struct xfs_mount	*mp,
>  	uint			flags)
>  {
> +	struct super_block	*sb = mp->m_super;
> +	struct inode		*inode, *old_inode = NULL;
> +
>  	ASSERT(mp->m_quotainfo);
> -	xfs_inode_walk(mp, XFS_INODE_WALK_INEW_WAIT, xfs_dqrele_inode,
> -			&flags, XFS_ICI_NO_TAG);
> +
> +	spin_lock(&sb->s_inode_list_lock);
> +	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
> +		struct xfs_inode	*ip = XFS_I(inode);
> +
> +		if (XFS_FORCED_SHUTDOWN(mp))
> +			break;
> +		if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
> +			continue;
> +		if (xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
> +			continue;
> +		if (!igrab(inode))
> +			continue;
> +		spin_unlock(&sb->s_inode_list_lock);
> +
> +		iput(old_inode);
> +		old_inode = inode;
> +
> +		if (xfs_iflags_test(ip, XFS_INEW))
> +			xfs_inew_wait(ip);
> +		xfs_dqrele_inode(ip, flags);
> +
> +		spin_lock(&sb->s_inode_list_lock);
> +	}
> +	spin_unlock(&sb->s_inode_list_lock);
> +
> +	iput(old_inode);
>  }
> -- 
> 2.30.1
> 

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

* Re: [PATCH 2/3] xfs: simplify the perage inode walk infrastructure
  2021-03-24  7:03 ` [PATCH 2/3] xfs: simplify the perage inode walk infrastructure Christoph Hellwig
@ 2021-03-24 17:57   ` Darrick J. Wong
  2021-03-24 17:59     ` Christoph Hellwig
  0 siblings, 1 reply; 9+ messages in thread
From: Darrick J. Wong @ 2021-03-24 17:57 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Mar 24, 2021 at 08:03:06AM +0100, Christoph Hellwig wrote:
> Remove the generic xfs_inode_walk and just open code the only caller.

This is going in the wrong direction for me.  Maybe.

I was planning to combine the reclaim inode walk into this function, and
later on share it with inactivation.  This made for one switch-happy
iteration function, but it meant there was only one loop.

OFC maybe the point that you and/or Dave were trying to make is that I
should be doing the opposite, and combining the inactivation loop into
what is now the (badly misnamed) xfs_reclaim_inodes_ag?  And leave this
blockgc loop alone?

<shrug>

--D

> Note that this leads to a somewhat ugly forward delcaration for
> xfs_blockgc_scan_inode, but with other changes in that area pending
> it seems like the lesser evil.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/xfs_icache.c | 103 +++++++++++++-------------------------------
>  fs/xfs/xfs_icache.h |  11 -----
>  2 files changed, 30 insertions(+), 84 deletions(-)
> 
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index c0d084e3526a9c..7fdf77df66269c 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -728,11 +728,9 @@ xfs_icache_inode_is_allocated(
>   */
>  STATIC bool
>  xfs_inode_walk_ag_grab(
> -	struct xfs_inode	*ip,
> -	int			flags)
> +	struct xfs_inode	*ip)
>  {
>  	struct inode		*inode = VFS_I(ip);
> -	bool			newinos = !!(flags & XFS_INODE_WALK_INEW_WAIT);
>  
>  	ASSERT(rcu_read_lock_held());
>  
> @@ -742,8 +740,7 @@ xfs_inode_walk_ag_grab(
>  		goto out_unlock_noent;
>  
>  	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
> -	if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
> -	    __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
> +	if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
>  		goto out_unlock_noent;
>  	spin_unlock(&ip->i_flags_lock);
>  
> @@ -763,17 +760,19 @@ xfs_inode_walk_ag_grab(
>  	return false;
>  }
>  
> +static int
> +xfs_blockgc_scan_inode(
> +	struct xfs_inode	*ip,
> +	void			*args);
> +
>  /*
>   * For a given per-AG structure @pag, grab, @execute, and rele all incore
>   * inodes with the given radix tree @tag.
>   */
>  STATIC int
> -xfs_inode_walk_ag(
> +xfs_blockgc_free_space_ag(
>  	struct xfs_perag	*pag,
> -	int			iter_flags,
> -	int			(*execute)(struct xfs_inode *ip, void *args),
> -	void			*args,
> -	int			tag)
> +	struct xfs_eofblocks	*eofb)
>  {
>  	struct xfs_mount	*mp = pag->pag_mount;
>  	uint32_t		first_index;
> @@ -793,17 +792,9 @@ xfs_inode_walk_ag(
>  		int		i;
>  
>  		rcu_read_lock();
> -
> -		if (tag == XFS_ICI_NO_TAG)
> -			nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
> -					(void **)batch, first_index,
> -					XFS_LOOKUP_BATCH);
> -		else
> -			nr_found = radix_tree_gang_lookup_tag(
> -					&pag->pag_ici_root,
> -					(void **) batch, first_index,
> -					XFS_LOOKUP_BATCH, tag);
> -
> +		nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
> +				(void **) batch, first_index,
> +				XFS_LOOKUP_BATCH, XFS_ICI_BLOCKGC_TAG);
>  		if (!nr_found) {
>  			rcu_read_unlock();
>  			break;
> @@ -816,7 +807,7 @@ xfs_inode_walk_ag(
>  		for (i = 0; i < nr_found; i++) {
>  			struct xfs_inode *ip = batch[i];
>  
> -			if (done || !xfs_inode_walk_ag_grab(ip, iter_flags))
> +			if (done || !xfs_inode_walk_ag_grab(ip))
>  				batch[i] = NULL;
>  
>  			/*
> @@ -844,10 +835,7 @@ xfs_inode_walk_ag(
>  		for (i = 0; i < nr_found; i++) {
>  			if (!batch[i])
>  				continue;
> -			if ((iter_flags & XFS_INODE_WALK_INEW_WAIT) &&
> -			    xfs_iflags_test(batch[i], XFS_INEW))
> -				xfs_inew_wait(batch[i]);
> -			error = execute(batch[i], args);
> +			error = xfs_blockgc_scan_inode(batch[i], eofb);
>  			xfs_irele(batch[i]);
>  			if (error == -EAGAIN) {
>  				skipped++;
> @@ -872,49 +860,6 @@ xfs_inode_walk_ag(
>  	return last_error;
>  }
>  
> -/* Fetch the next (possibly tagged) per-AG structure. */
> -static inline struct xfs_perag *
> -xfs_inode_walk_get_perag(
> -	struct xfs_mount	*mp,
> -	xfs_agnumber_t		agno,
> -	int			tag)
> -{
> -	if (tag == XFS_ICI_NO_TAG)
> -		return xfs_perag_get(mp, agno);
> -	return xfs_perag_get_tag(mp, agno, tag);
> -}
> -
> -/*
> - * Call the @execute function on all incore inodes matching the radix tree
> - * @tag.
> - */
> -int
> -xfs_inode_walk(
> -	struct xfs_mount	*mp,
> -	int			iter_flags,
> -	int			(*execute)(struct xfs_inode *ip, void *args),
> -	void			*args,
> -	int			tag)
> -{
> -	struct xfs_perag	*pag;
> -	int			error = 0;
> -	int			last_error = 0;
> -	xfs_agnumber_t		ag;
> -
> -	ag = 0;
> -	while ((pag = xfs_inode_walk_get_perag(mp, ag, tag))) {
> -		ag = pag->pag_agno + 1;
> -		error = xfs_inode_walk_ag(pag, iter_flags, execute, args, tag);
> -		xfs_perag_put(pag);
> -		if (error) {
> -			last_error = error;
> -			if (error == -EFSCORRUPTED)
> -				break;
> -		}
> -	}
> -	return last_error;
> -}
> -
>  /*
>   * Grab the inode for reclaim exclusively.
>   *
> @@ -1617,8 +1562,7 @@ xfs_blockgc_worker(
>  
>  	if (!sb_start_write_trylock(mp->m_super))
>  		return;
> -	error = xfs_inode_walk_ag(pag, 0, xfs_blockgc_scan_inode, NULL,
> -			XFS_ICI_BLOCKGC_TAG);
> +	error = xfs_blockgc_free_space_ag(pag, NULL);
>  	if (error)
>  		xfs_info(mp, "AG %u preallocation gc worker failed, err=%d",
>  				pag->pag_agno, error);
> @@ -1634,10 +1578,23 @@ xfs_blockgc_free_space(
>  	struct xfs_mount	*mp,
>  	struct xfs_eofblocks	*eofb)
>  {
> +	struct xfs_perag	*pag;
> +	xfs_agnumber_t		ag = 0;
> +	int			error = 0, last_error = 0;
> +
>  	trace_xfs_blockgc_free_space(mp, eofb, _RET_IP_);
>  
> -	return xfs_inode_walk(mp, 0, xfs_blockgc_scan_inode, eofb,
> -			XFS_ICI_BLOCKGC_TAG);
> +	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_BLOCKGC_TAG))) {
> +		ag = pag->pag_agno + 1;
> +		error = xfs_blockgc_free_space_ag(pag, eofb);
> +		xfs_perag_put(pag);
> +		if (error) {
> +			if (error == -EFSCORRUPTED)
> +				return error;
> +			last_error = error;
> +		}
> +	}
> +	return last_error;
>  }
>  
>  /*
> diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
> index d70d93c2bb1084..da390097546c67 100644
> --- a/fs/xfs/xfs_icache.h
> +++ b/fs/xfs/xfs_icache.h
> @@ -20,8 +20,6 @@ struct xfs_eofblocks {
>  /*
>   * tags for inode radix tree
>   */
> -#define XFS_ICI_NO_TAG		(-1)	/* special flag for an untagged lookup
> -					   in xfs_inode_walk */
>  #define XFS_ICI_RECLAIM_TAG	0	/* inode is to be reclaimed */
>  /* Inode has speculative preallocations (posteof or cow) to clean. */
>  #define XFS_ICI_BLOCKGC_TAG	1
> @@ -34,11 +32,6 @@ struct xfs_eofblocks {
>  #define XFS_IGET_DONTCACHE	0x4
>  #define XFS_IGET_INCORE		0x8	/* don't read from disk or reinit */
>  
> -/*
> - * flags for AG inode iterator
> - */
> -#define XFS_INODE_WALK_INEW_WAIT	0x1	/* wait on new inodes */
> -
>  int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
>  	     uint flags, uint lock_flags, xfs_inode_t **ipp);
>  
> @@ -68,10 +61,6 @@ void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip);
>  
>  void xfs_blockgc_worker(struct work_struct *work);
>  
> -int xfs_inode_walk(struct xfs_mount *mp, int iter_flags,
> -	int (*execute)(struct xfs_inode *ip, void *args),
> -	void *args, int tag);
> -
>  int xfs_icache_inode_is_allocated(struct xfs_mount *mp, struct xfs_trans *tp,
>  				  xfs_ino_t ino, bool *inuse);
>  
> -- 
> 2.30.1
> 

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

* Re: [PATCH 2/3] xfs: simplify the perage inode walk infrastructure
  2021-03-24 17:57   ` Darrick J. Wong
@ 2021-03-24 17:59     ` Christoph Hellwig
  2021-03-25  4:30       ` Darrick J. Wong
  0 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2021-03-24 17:59 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

On Wed, Mar 24, 2021 at 10:57:35AM -0700, Darrick J. Wong wrote:
> On Wed, Mar 24, 2021 at 08:03:06AM +0100, Christoph Hellwig wrote:
> > Remove the generic xfs_inode_walk and just open code the only caller.
> 
> This is going in the wrong direction for me.  Maybe.
> 
> I was planning to combine the reclaim inode walk into this function, and
> later on share it with inactivation.  This made for one switch-happy
> iteration function, but it meant there was only one loop.

Ok, we can skip this for now if this gets in your way.  Or I can resend
a different patch 2 that just removes the no tag case for now.

> OFC maybe the point that you and/or Dave were trying to make is that I
> should be doing the opposite, and combining the inactivation loop into
> what is now the (badly misnamed) xfs_reclaim_inodes_ag?  And leave this
> blockgc loop alone?

That is my gut feeling.  No guarantee it actually works out, and given
that I've lead you down the wrong road a few times I already feel guily
ahead of time..

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

* Re: [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback
  2021-03-24  7:03 ` [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback Christoph Hellwig
@ 2021-03-24 18:03   ` Darrick J. Wong
  0 siblings, 0 replies; 9+ messages in thread
From: Darrick J. Wong @ 2021-03-24 18:03 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Mar 24, 2021 at 08:03:07AM +0100, Christoph Hellwig wrote:
> Pass the actual structure instead of a void pointer here now
> that none of the functions is used as a callback.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
>  xfs_inode_free_cowblocks(

Assuming this ends up fitting in somewhere,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/xfs/xfs_icache.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 7fdf77df66269c..06286b5b613252 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -763,7 +763,7 @@ xfs_inode_walk_ag_grab(
>  static int
>  xfs_blockgc_scan_inode(
>  	struct xfs_inode	*ip,
> -	void			*args);
> +	struct xfs_eofblocks	*eofb);
>  
>  /*
>   * For a given per-AG structure @pag, grab, @execute, and rele all incore
> @@ -1228,10 +1228,9 @@ xfs_reclaim_worker(
>  STATIC int
>  xfs_inode_free_eofblocks(
>  	struct xfs_inode	*ip,
> -	void			*args,
> +	struct xfs_eofblocks	*eofb,
>  	unsigned int		*lockflags)
>  {
> -	struct xfs_eofblocks	*eofb = args;
>  	bool			wait;
>  
>  	wait = eofb && (eofb->eof_flags & XFS_EOF_FLAGS_SYNC);
> @@ -1436,10 +1435,9 @@ xfs_prep_free_cowblocks(
>  STATIC int
>  xfs_inode_free_cowblocks(
>  	struct xfs_inode	*ip,
> -	void			*args,
> +	struct xfs_eofblocks	*eofb,
>  	unsigned int		*lockflags)
>  {
> -	struct xfs_eofblocks	*eofb = args;
>  	bool			wait;
>  	int			ret = 0;
>  
> @@ -1534,16 +1532,16 @@ xfs_blockgc_start(
>  static int
>  xfs_blockgc_scan_inode(
>  	struct xfs_inode	*ip,
> -	void			*args)
> +	struct xfs_eofblocks	*eofb)
>  {
>  	unsigned int		lockflags = 0;
>  	int			error;
>  
> -	error = xfs_inode_free_eofblocks(ip, args, &lockflags);
> +	error = xfs_inode_free_eofblocks(ip, eofb, &lockflags);
>  	if (error)
>  		goto unlock;
>  
> -	error = xfs_inode_free_cowblocks(ip, args, &lockflags);
> +	error = xfs_inode_free_cowblocks(ip, eofb, &lockflags);
>  unlock:
>  	if (lockflags)
>  		xfs_iunlock(ip, lockflags);
> -- 
> 2.30.1
> 

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

* Re: [PATCH 2/3] xfs: simplify the perage inode walk infrastructure
  2021-03-24 17:59     ` Christoph Hellwig
@ 2021-03-25  4:30       ` Darrick J. Wong
  0 siblings, 0 replies; 9+ messages in thread
From: Darrick J. Wong @ 2021-03-25  4:30 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Mar 24, 2021 at 06:59:37PM +0100, Christoph Hellwig wrote:
> On Wed, Mar 24, 2021 at 10:57:35AM -0700, Darrick J. Wong wrote:
> > On Wed, Mar 24, 2021 at 08:03:06AM +0100, Christoph Hellwig wrote:
> > > Remove the generic xfs_inode_walk and just open code the only caller.
> > 
> > This is going in the wrong direction for me.  Maybe.
> > 
> > I was planning to combine the reclaim inode walk into this function, and
> > later on share it with inactivation.  This made for one switch-happy
> > iteration function, but it meant there was only one loop.
> 
> Ok, we can skip this for now if this gets in your way.  Or I can resend
> a different patch 2 that just removes the no tag case for now.
> 
> > OFC maybe the point that you and/or Dave were trying to make is that I
> > should be doing the opposite, and combining the inactivation loop into
> > what is now the (badly misnamed) xfs_reclaim_inodes_ag?  And leave this
> > blockgc loop alone?
> 
> That is my gut feeling.  No guarantee it actually works out, and given
> that I've lead you down the wrong road a few times I already feel guily
> ahead of time..

Actually, collapsing all of the tag walkers into xfs_inode_walk was
pretty straightforward, and in the end I just borrowed bits and pieces
from patches 2 and 3 to make it happen and clean up the arguments.  The
net change is 55 lines deleted and ~1k less code (granted with all the
debugging and ubsan crud turned on).

--D

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

end of thread, other threads:[~2021-03-25  4:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-24  7:03 simplify the blockgc iwalk infrastructure Christoph Hellwig
2021-03-24  7:03 ` [PATCH 1/3] xfs: use s_inodes in xfs_qm_dqrele_all_inodes Christoph Hellwig
2021-03-24 17:50   ` Darrick J. Wong
2021-03-24  7:03 ` [PATCH 2/3] xfs: simplify the perage inode walk infrastructure Christoph Hellwig
2021-03-24 17:57   ` Darrick J. Wong
2021-03-24 17:59     ` Christoph Hellwig
2021-03-25  4:30       ` Darrick J. Wong
2021-03-24  7:03 ` [PATCH 3/3] xfs: pass struct xfs_eofblocks to the inode scan callback Christoph Hellwig
2021-03-24 18:03   ` Darrick J. Wong

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).