From: Dave Chinner <david@fromorbit.com>
To: stable@kernel.org
Cc: xfs@oss.sgi.com
Subject: [PATCH 09/19] xfs: Ensure we force all busy extents in range to disk
Date: Fri, 12 Mar 2010 09:42:07 +1100 [thread overview]
Message-ID: <1268347337-7160-10-git-send-email-david@fromorbit.com> (raw)
In-Reply-To: <1268347337-7160-1-git-send-email-david@fromorbit.com>
>From fd45e4784164d1017521086524e3442318c67370
Date: Sat, 2 Jan 2010 02:38:56 +0000
When we search for and find a busy extent during allocation we
force the log out to ensure the extent free transaction is on
disk before the allocation transaction. The current implementation
has a subtle bug in it--it does not handle multiple overlapping
ranges.
That is, if we free lots of little extents into a single
contiguous extent, then allocate the contiguous extent, the busy
search code stops searching at the first extent it finds that
overlaps the allocated range. It then uses the commit LSN of the
transaction to force the log out to.
Unfortunately, the other busy ranges might have more recent
commit LSNs than the first busy extent that is found, and this
results in xfs_alloc_search_busy() returning before all the
extent free transactions are on disk for the range being
allocated. This can lead to potential metadata corruption or
stale data exposure after a crash because log replay won't replay
all the extent free transactions that cover the allocation range.
Modified-by: Alex Elder <aelder@sgi.com>
(Dropped the "found" argument from the xfs_alloc_busysearch trace
event.)
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
---
fs/xfs/xfs_alloc.c | 52 +++++++++++++++++++++-------------------------------
1 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 2cf944e..4cd1c23 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2703,45 +2703,35 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
xfs_mount_t *mp;
xfs_perag_busy_t *bsy;
xfs_agblock_t uend, bend;
- xfs_lsn_t lsn;
+ xfs_lsn_t lsn = 0;
int cnt;
mp = tp->t_mountp;
spin_lock(&mp->m_perag[agno].pagb_lock);
- cnt = mp->m_perag[agno].pagb_count;
-
uend = bno + len - 1;
- /* search pagb_list for this slot, skipping open slots */
- for (bsy = mp->m_perag[agno].pagb_list; cnt; bsy++) {
-
- /*
- * (start1,length1) within (start2, length2)
- */
- if (bsy->busy_tp != NULL) {
- bend = bsy->busy_start + bsy->busy_length - 1;
- if ((bno > bend) || (uend < bsy->busy_start)) {
- cnt--;
- } else {
- TRACE_BUSYSEARCH("xfs_alloc_search_busy",
- "found1", agno, bno, len, tp);
- break;
- }
- }
- }
-
/*
- * If a block was found, force the log through the LSN of the
- * transaction that freed the block
+ * search pagb_list for this slot, skipping open slots. We have to
+ * search the entire array as there may be multiple overlaps and
+ * we have to get the most recent LSN for the log force to push out
+ * all the transactions that span the range.
*/
- if (cnt) {
- TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, tp);
- lsn = bsy->busy_tp->t_commit_lsn;
- spin_unlock(&mp->m_perag[agno].pagb_lock);
- xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
- } else {
- TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, tp);
- spin_unlock(&mp->m_perag[agno].pagb_lock);
+ for (cnt = 0; cnt < mp->m_perag[agno].pagb_count; cnt++) {
+ bsy = &mp->m_perag[agno].pagb_list[cnt];
+ if (!bsy->busy_tp)
+ continue;
+ bend = bsy->busy_start + bsy->busy_length - 1;
+ if (bno > bend || uend < bsy->busy_start)
+ continue;
+
+ /* (start1,length1) within (start2, length2) */
+ if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0)
+ lsn = bsy->busy_tp->t_commit_lsn;
}
+ spin_unlock(&mp->m_perag[agno].pagb_lock);
+ TRACE_BUSYSEARCH("xfs_alloc_search_busy", lsn ? "found" : "not-found",
+ agno, bno, len, tp);
+ if (lsn)
+ xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
--
1.6.5
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2010-03-11 22:41 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1268347337-7160-1-git-send-email-david@fromorbit.com>
2010-03-11 22:41 ` [PATCH 01/19] xfs: simplify inode teardown Dave Chinner
2010-03-11 22:42 ` [PATCH 02/19] xfs: fix mmap_sem/iolock inversion in xfs_free_eofblocks Dave Chinner
2010-03-11 22:42 ` [PATCH 03/19] xfs: I/O completion handlers must use NOFS allocations Dave Chinner
2010-03-11 22:42 ` [PATCH 04/19] xfs: Wrapped journal record corruption on read at recovery Dave Chinner
2010-03-11 22:42 ` [PATCH 05/19] xfs: Fix error return for fallocate() on XFS Dave Chinner
2010-03-11 22:42 ` [PATCH 06/19] xfs: check for not fully initialized inodes in xfs_ireclaim Dave Chinner
2010-03-11 22:42 ` [PATCH 07/19] xfs: fix timestamp handling in xfs_setattr Dave Chinner
2010-03-11 22:42 ` [PATCH 08/19] xfs: Don't flush stale inodes Dave Chinner
2010-03-11 22:42 ` Dave Chinner [this message]
2010-03-11 22:42 ` [PATCH 10/19] xfs: reclaim inodes under a write lock Dave Chinner
2010-03-11 22:42 ` [PATCH 11/19] xfs: Avoid inodes in reclaim when flushing from inode cache Dave Chinner
2010-03-11 22:42 ` [PATCH 12/19] xfs: reclaim all inodes by background tree walks Dave Chinner
2010-03-11 22:42 ` [PATCH 13/19] xfs: fix stale inode flush avoidance Dave Chinner
2010-03-11 22:42 ` [PATCH 14/19] xfs: xfs_swap_extents needs to handle dynamic fork offsets Dave Chinner
2010-03-11 22:42 ` [PATCH 15/19] xfs: quota limit statvfs available blocks Dave Chinner
2010-03-11 22:42 ` [PATCH 16/19] xfs: don't hold onto reserved blocks on remount,ro Dave Chinner
2010-03-11 22:42 ` [PATCH 17/19] xfs: remove invalid barrier optimization from xfs_fsync Dave Chinner
2010-03-11 22:42 ` [PATCH 18/19] xfs: Non-blocking inode locking in IO completion 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=1268347337-7160-10-git-send-email-david@fromorbit.com \
--to=david@fromorbit.com \
--cc=stable@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox