From: Christoph Hellwig <hch@infradead.org>
To: Patrick Schreurs <patrick@news-service.com>
Cc: Christoph Hellwig <hch@infradead.org>,
Tommy van Leeuwen <tommy@news-service.com>,
Bas Couwenberg <bas@news-service.com>, XFS List <xfs@oss.sgi.com>
Subject: Re: 2.6.31 xfs_fs_destroy_inode: cannot reclaim
Date: Mon, 12 Oct 2009 19:38:54 -0400 [thread overview]
Message-ID: <20091012233854.GA29446@infradead.org> (raw)
In-Reply-To: <4AD18C8D.90808@news-service.com>
On Sun, Oct 11, 2009 at 09:43:09AM +0200, Patrick Schreurs wrote:
> Hello Christoph,
>
> Attached you'll find a screenshot from a 2.6.31.3 server, which includes
> your patches and has XFS_DEBUG turned on. I truly hope this is useful to
> you.
Thanks. The patch below should fix the inode reclaim race that could
lead to the double free you're seeing. To be applied ontop of all
the other patches I sent you.
Index: xfs/fs/xfs/linux-2.6/xfs_sync.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_sync.c 2009-10-11 19:09:43.828254119 +0200
+++ xfs/fs/xfs/linux-2.6/xfs_sync.c 2009-10-12 13:48:14.886006087 +0200
@@ -670,22 +670,22 @@ xfs_reclaim_inode(
{
xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
- /* The hash lock here protects a thread in xfs_iget_core from
- * racing with us on linking the inode back with a vnode.
- * Once we have the XFS_IRECLAIM flag set it will not touch
- * us.
+ /*
+ * The hash lock here protects a thread in xfs_iget from racing with
+ * us on recycling the inode. Once we have the XFS_IRECLAIM flag set
+ * it will not touch it.
*/
- write_lock(&pag->pag_ici_lock);
spin_lock(&ip->i_flags_lock);
- if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
- !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
+ ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+ if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
spin_unlock(&ip->i_flags_lock);
write_unlock(&pag->pag_ici_lock);
- return -EAGAIN;
+ return 0;
}
__xfs_iflags_set(ip, XFS_IRECLAIM);
spin_unlock(&ip->i_flags_lock);
write_unlock(&pag->pag_ici_lock);
+
xfs_put_perag(ip->i_mount, pag);
/*
@@ -758,27 +758,107 @@ __xfs_inode_clear_reclaim_tag(
XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
}
-STATIC int
-xfs_reclaim_inode_now(
- struct xfs_inode *ip,
+STATIC xfs_inode_t *
+xfs_reclaim_ag_lookup(
+ struct xfs_mount *mp,
struct xfs_perag *pag,
+ uint32_t *first_index)
+{
+ int nr_found;
+ struct xfs_inode *ip;
+
+ /*
+ * use a gang lookup to find the next inode in the tree
+ * as the tree is sparse and a gang lookup walks to find
+ * the number of objects requested.
+ */
+ write_lock(&pag->pag_ici_lock);
+ nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
+ (void **)&ip, *first_index, 1, XFS_ICI_RECLAIM_TAG);
+ if (!nr_found)
+ goto unlock;
+
+ /*
+ * Update the index for the next lookup. Catch overflows
+ * into the next AG range which can occur if we have inodes
+ * in the last block of the AG and we are currently
+ * pointing to the last inode.
+ */
+ *first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+ if (*first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+ goto unlock;
+
+ return ip;
+
+unlock:
+ write_unlock(&pag->pag_ici_lock);
+ return NULL;
+}
+
+STATIC int
+xfs_reclaim_ag_walk(
+ struct xfs_mount *mp,
+ xfs_agnumber_t ag,
int flags)
{
- /* ignore if already under reclaim */
- if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
- read_unlock(&pag->pag_ici_lock);
- return 0;
+ struct xfs_perag *pag = &mp->m_perag[ag];
+ uint32_t first_index;
+ int last_error = 0;
+ int skipped;
+
+restart:
+ skipped = 0;
+ first_index = 0;
+ do {
+ int error = 0;
+ xfs_inode_t *ip;
+
+ ip = xfs_reclaim_ag_lookup(mp, pag, &first_index);
+ if (!ip)
+ break;
+
+ error = xfs_reclaim_inode(ip, flags);
+ if (error == EAGAIN) {
+ skipped++;
+ continue;
+ }
+ if (error)
+ last_error = error;
+ /*
+ * bail out if the filesystem is corrupted.
+ */
+ if (error == EFSCORRUPTED)
+ break;
+
+ } while (1);
+
+ if (skipped) {
+ delay(1);
+ goto restart;
}
- read_unlock(&pag->pag_ici_lock);
- return xfs_reclaim_inode(ip, flags);
+ xfs_put_perag(mp, pag);
+ return last_error;
}
int
xfs_reclaim_inodes(
- xfs_mount_t *mp,
- int mode)
+ xfs_mount_t *mp,
+ int mode)
{
- return xfs_inode_ag_iterator(mp, xfs_reclaim_inode_now, mode,
- XFS_ICI_RECLAIM_TAG);
+ int error = 0;
+ int last_error = 0;
+ xfs_agnumber_t ag;
+
+ for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
+ if (!mp->m_perag[ag].pag_ici_init)
+ continue;
+ error = xfs_reclaim_ag_walk(mp, ag, mode);
+ if (error) {
+ last_error = error;
+ if (error == EFSCORRUPTED)
+ break;
+ }
+ }
+ return XFS_ERROR(last_error);
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2009-10-12 23:37 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-16 10:27 2.6.31 xfs_fs_destroy_inode: cannot reclaim Tommy van Leeuwen
2009-09-17 18:59 ` Christoph Hellwig
2009-09-29 10:15 ` Patrick Schreurs
2009-09-29 12:57 ` Christoph Hellwig
2009-09-30 10:48 ` Patrick Schreurs
2009-09-30 12:41 ` Christoph Hellwig
2009-10-02 14:24 ` Bas Couwenberg
2009-10-05 21:43 ` Christoph Hellwig
2009-10-06 9:04 ` Patrick Schreurs
2009-10-07 1:19 ` Christoph Hellwig
2009-10-08 8:45 ` Patrick Schreurs
2009-10-11 7:43 ` Patrick Schreurs
2009-10-11 12:24 ` Christoph Hellwig
2009-10-12 23:38 ` Christoph Hellwig [this message]
2009-10-15 15:06 ` Tommy van Leeuwen
2009-10-18 23:59 ` Christoph Hellwig
2009-10-19 1:17 ` Dave Chinner
2009-10-19 3:53 ` Christoph Hellwig
2009-10-19 1:16 ` Dave Chinner
2009-10-19 3:54 ` Christoph Hellwig
2009-10-20 3:40 ` Dave Chinner
2009-10-21 9:45 ` Tommy van Leeuwen
2009-10-22 8:59 ` Christoph Hellwig
2009-10-27 10:41 ` Tommy van Leeuwen
[not found] ` <89c4f90c0910280519k759230c1r7b1586932ac792f7@mail.gmail.com>
2009-10-30 10:16 ` Christoph Hellwig
2009-11-03 14:46 ` Patrick Schreurs
2009-11-14 16:21 ` Christoph Hellwig
[not found] ` <4B0A8075.8080008@news-service.com>
[not found] ` <20091211115932.GA20632@infradead.org>
[not found] ` <4B3F9F88.9030307@news-service.com>
[not found] ` <20100107110446.GA13802@discord.disaster>
[not found] ` <4B45CFAC.4000607@news-service.com>
2010-01-08 11:31 ` [PATCH] Inode reclaim fixes (was Re: 2.6.31 xfs_fs_destroy_inode: cannot reclaim) Dave Chinner
2010-01-11 20:22 ` Patrick Schreurs
2010-01-15 11:01 ` Patrick Schreurs
2010-02-01 16:52 ` Patrick Schreurs
2010-02-08 10:16 ` Patrick Schreurs
2010-02-08 19:42 ` Christoph Hellwig
2010-02-09 8:48 ` Patrick Schreurs
2010-02-09 10:31 ` Christoph Hellwig
2010-02-10 12:42 ` Patrick Schreurs
2010-02-10 14:55 ` Christoph Hellwig
2010-02-10 15:42 ` Patrick Schreurs
2010-02-10 15:47 ` Christoph Hellwig
2010-02-24 18:30 ` Patrick Schreurs
2010-02-25 23:45 ` Dave Chinner
2010-03-01 9:51 ` 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=20091012233854.GA29446@infradead.org \
--to=hch@infradead.org \
--cc=bas@news-service.com \
--cc=patrick@news-service.com \
--cc=tommy@news-service.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox