linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: david@fromorbit.com, darrick.wong@oracle.com
Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com
Subject: [PATCH 113/119] xfs: scrub btree records and pointers while querying
Date: Thu, 16 Jun 2016 18:30:03 -0700	[thread overview]
Message-ID: <146612700354.12839.18272855403371334654.stgit@birch.djwong.org> (raw)
In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org>

Create a function that walks a btree, checking the integrity of each
btree block (headers, keys, records) and calling back to the caller
to perform further checks on the records.

v2: Prefix function names with xfs_

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/Makefile                |    1 
 fs/xfs/libxfs/xfs_alloc.c      |   33 +++
 fs/xfs/libxfs/xfs_alloc.h      |    3 
 fs/xfs/libxfs/xfs_btree.c      |   12 +
 fs/xfs/libxfs/xfs_btree.h      |   15 +-
 fs/xfs/libxfs/xfs_format.h     |    2 
 fs/xfs/libxfs/xfs_rmap.c       |   39 ++++
 fs/xfs/libxfs/xfs_rmap_btree.h |    3 
 fs/xfs/libxfs/xfs_scrub.c      |  396 ++++++++++++++++++++++++++++++++++++++++
 fs/xfs/libxfs/xfs_scrub.h      |   76 ++++++++
 10 files changed, 571 insertions(+), 9 deletions(-)
 create mode 100644 fs/xfs/libxfs/xfs_scrub.c
 create mode 100644 fs/xfs/libxfs/xfs_scrub.h


diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 56c384b..8942390 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -58,6 +58,7 @@ xfs-y				+= $(addprefix libxfs/, \
 				   xfs_refcount.o \
 				   xfs_refcount_btree.o \
 				   xfs_sb.o \
+				   xfs_scrub.o \
 				   xfs_symlink_remote.o \
 				   xfs_trans_resv.o \
 				   )
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 188c359a..6fc1981 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2924,3 +2924,36 @@ err:
 	xfs_trans_brelse(tp, agbp);
 	return error;
 }
+
+/* Is there a record covering a given extent? */
+int
+xfs_alloc_record_exists(
+	struct xfs_btree_cur	*cur,
+	xfs_agblock_t		bno,
+	xfs_extlen_t		len,
+	bool			*is_freesp)
+{
+	int			stat;
+	xfs_agblock_t		fbno;
+	xfs_extlen_t		flen;
+	int			error;
+
+	error = xfs_alloc_lookup_le(cur, bno, len, &stat);
+	if (error)
+		return error;
+	if (!stat) {
+		*is_freesp = false;
+		return 0;
+	}
+
+	error = xfs_alloc_get_rec(cur, &fbno, &flen, &stat);
+	if (error)
+		return error;
+	if (!stat) {
+		*is_freesp = false;
+		return 0;
+	}
+
+	*is_freesp = (fbno <= bno && fbno + flen >= bno + len);
+	return 0;
+}
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 9f6373a4..4f2ce38 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -210,4 +210,7 @@ int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
 
 xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp);
 
+int xfs_alloc_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+		xfs_extlen_t len, bool *is_freesp);
+
 #endif	/* __XFS_ALLOC_H__ */
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 9c84184..5260085 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -549,7 +549,7 @@ xfs_btree_ptr_offset(
 /*
  * Return a pointer to the n-th record in the btree block.
  */
-STATIC union xfs_btree_rec *
+union xfs_btree_rec *
 xfs_btree_rec_addr(
 	struct xfs_btree_cur	*cur,
 	int			n,
@@ -562,7 +562,7 @@ xfs_btree_rec_addr(
 /*
  * Return a pointer to the n-th key in the btree block.
  */
-STATIC union xfs_btree_key *
+union xfs_btree_key *
 xfs_btree_key_addr(
 	struct xfs_btree_cur	*cur,
 	int			n,
@@ -575,7 +575,7 @@ xfs_btree_key_addr(
 /*
  * Return a pointer to the n-th high key in the btree block.
  */
-STATIC union xfs_btree_key *
+union xfs_btree_key *
 xfs_btree_high_key_addr(
 	struct xfs_btree_cur	*cur,
 	int			n,
@@ -588,7 +588,7 @@ xfs_btree_high_key_addr(
 /*
  * Return a pointer to the n-th block pointer in the btree block.
  */
-STATIC union xfs_btree_ptr *
+union xfs_btree_ptr *
 xfs_btree_ptr_addr(
 	struct xfs_btree_cur	*cur,
 	int			n,
@@ -622,7 +622,7 @@ xfs_btree_get_iroot(
  * Retrieve the block pointer from the cursor at the given level.
  * This may be an inode btree root or from a buffer.
  */
-STATIC struct xfs_btree_block *		/* generic btree block pointer */
+struct xfs_btree_block *		/* generic btree block pointer */
 xfs_btree_get_block(
 	struct xfs_btree_cur	*cur,	/* btree cursor */
 	int			level,	/* level in btree */
@@ -1733,7 +1733,7 @@ error0:
 	return error;
 }
 
-STATIC int
+int
 xfs_btree_lookup_get_block(
 	struct xfs_btree_cur	*cur,	/* btree cursor */
 	int			level,	/* level in the btree */
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index dbf299f..6f22cb0 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -194,7 +194,6 @@ struct xfs_btree_ops {
 
 	const struct xfs_buf_ops	*buf_ops;
 
-#if defined(DEBUG) || defined(XFS_WARN)
 	/* check that k1 is lower than k2 */
 	int	(*keys_inorder)(struct xfs_btree_cur *cur,
 				union xfs_btree_key *k1,
@@ -204,7 +203,6 @@ struct xfs_btree_ops {
 	int	(*recs_inorder)(struct xfs_btree_cur *cur,
 				union xfs_btree_rec *r1,
 				union xfs_btree_rec *r2);
-#endif
 };
 
 /* btree ops flags */
@@ -537,4 +535,17 @@ int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
 
 int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
 
+union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
+		struct xfs_btree_block *block);
+union xfs_btree_key *xfs_btree_key_addr(struct xfs_btree_cur *cur, int n,
+		struct xfs_btree_block *block);
+union xfs_btree_key *xfs_btree_high_key_addr(struct xfs_btree_cur *cur, int n,
+		struct xfs_btree_block *block);
+union xfs_btree_ptr *xfs_btree_ptr_addr(struct xfs_btree_cur *cur, int n,
+		struct xfs_btree_block *block);
+int xfs_btree_lookup_get_block(struct xfs_btree_cur *cur, int level,
+		union xfs_btree_ptr *pp, struct xfs_btree_block **blkp);
+struct xfs_btree_block *xfs_btree_get_block(struct xfs_btree_cur *cur,
+		int level, struct xfs_buf **bpp);
+
 #endif	/* __XFS_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 211a8b5..6ea8a84 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -518,7 +518,7 @@ static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp)
 		 (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE));
 }
 
-static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp)
+static inline bool xfs_sb_version_hasfinobt(xfs_sb_t *sbp)
 {
 	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
 		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT);
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index 29d08fc..e7673ec 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -2328,3 +2328,42 @@ xfs_rmap_free_defer(
 
 	return __xfs_rmap_add(mp, dfops, &ri);
 }
+
+/* Is there a record covering a given extent? */
+int
+xfs_rmap_record_exists(
+	struct xfs_btree_cur	*cur,
+	xfs_agblock_t		bno,
+	xfs_extlen_t		len,
+	struct xfs_owner_info	*oinfo,
+	bool			*has_rmap)
+{
+	uint64_t		owner;
+	uint64_t		offset;
+	unsigned int		flags;
+	int			stat;
+	struct xfs_rmap_irec	irec;
+	int			error;
+
+	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
+
+	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &stat);
+	if (error)
+		return error;
+	if (!stat) {
+		*has_rmap = false;
+		return 0;
+	}
+
+	error = xfs_rmap_get_rec(cur, &irec, &stat);
+	if (error)
+		return error;
+	if (!stat) {
+		*has_rmap = false;
+		return 0;
+	}
+
+	*has_rmap = (irec.rm_startblock <= bno &&
+		     irec.rm_startblock + irec.rm_blockcount >= bno + len);
+	return 0;
+}
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index 5baa81f..2f072c8 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -144,4 +144,7 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp);
 extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp,
 		xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used);
 
+extern int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+		xfs_extlen_t len, struct xfs_owner_info *oinfo, bool *has_rmap);
+
 #endif	/* __XFS_RMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_scrub.c b/fs/xfs/libxfs/xfs_scrub.c
new file mode 100644
index 0000000..d43d5c5
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_scrub.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2016 Oracle.  All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_btree.h"
+#include "xfs_bit.h"
+#include "xfs_alloc.h"
+#include "xfs_bmap.h"
+#include "xfs_ialloc.h"
+#include "xfs_refcount.h"
+#include "xfs_alloc_btree.h"
+#include "xfs_rmap_btree.h"
+#include "xfs_log_format.h"
+#include "xfs_trans.h"
+#include "xfs_scrub.h"
+
+static const char * const btree_types[] = {
+	[XFS_BTNUM_BNO]		= "bnobt",
+	[XFS_BTNUM_CNT]		= "cntbt",
+	[XFS_BTNUM_RMAP]	= "rmapbt",
+	[XFS_BTNUM_BMAP]	= "bmapbt",
+	[XFS_BTNUM_INO]		= "inobt",
+	[XFS_BTNUM_FINO]	= "finobt",
+	[XFS_BTNUM_REFC]	= "refcountbt",
+};
+
+/* Report a scrub corruption in dmesg. */
+void
+xfs_btree_scrub_error(
+	struct xfs_btree_cur		*cur,
+	int				level,
+	const char			*file,
+	int				line,
+	const char			*check)
+{
+	char				buf[16];
+	xfs_fsblock_t			fsbno;
+
+	if (cur->bc_ptrs[level] >= 1)
+		snprintf(buf, 16, " ptr %d", cur->bc_ptrs[level]);
+	else
+		buf[0] = 0;
+
+	fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, cur->bc_bufs[level]->b_bn);
+	xfs_alert(cur->bc_mp, "scrub: %s btree corruption in block %u/%u%s: %s, file: %s, line: %d",
+			btree_types[cur->bc_btnum],
+			XFS_FSB_TO_AGNO(cur->bc_mp, fsbno),
+			XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno),
+			buf, check, file, line);
+}
+
+/* AG metadata scrubbing */
+
+/*
+ * Make sure this record is in order and doesn't stray outside of the parent
+ * keys.
+ */
+static int
+xfs_btree_scrub_rec(
+	struct xfs_btree_scrub	*bs)
+{
+	struct xfs_btree_cur	*cur = bs->cur;
+	union xfs_btree_rec	*rec;
+	union xfs_btree_key	key;
+	union xfs_btree_key	*keyp;
+	struct xfs_btree_block	*block;
+	struct xfs_btree_block	*keyblock;
+
+	block = XFS_BUF_TO_BLOCK(cur->bc_bufs[0]);
+	rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
+
+	/* If this isn't the first record, are they in order? */
+	XFS_BTREC_SCRUB_CHECK(bs, bs->firstrec ||
+			cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec));
+	bs->firstrec = false;
+	bs->lastrec = *rec;
+
+	if (cur->bc_nlevels == 1)
+		return 0;
+
+	/* Is this at least as large as the parent low key? */
+	cur->bc_ops->init_key_from_rec(&key, rec);
+	keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[1]);
+	keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock);
+
+	XFS_BTKEY_SCRUB_CHECK(bs, 0,
+			cur->bc_ops->diff_two_keys(cur, keyp, &key) >= 0);
+
+	if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING))
+		return 0;
+
+	/* Is this no larger than the parent high key? */
+	keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock);
+
+	XFS_BTKEY_SCRUB_CHECK(bs, 0,
+			cur->bc_ops->diff_two_keys(cur, &key, keyp) >= 0);
+
+	return 0;
+}
+
+/*
+ * Make sure this key is in order and doesn't stray outside of the parent
+ * keys.
+ */
+static int
+xfs_btree_scrub_key(
+	struct xfs_btree_scrub	*bs,
+	int			level)
+{
+	struct xfs_btree_cur	*cur = bs->cur;
+	union xfs_btree_key	*key;
+	union xfs_btree_key	*keyp;
+	struct xfs_btree_block	*block;
+	struct xfs_btree_block	*keyblock;
+
+	block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]);
+	key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block);
+
+	/* If this isn't the first key, are they in order? */
+	XFS_BTKEY_SCRUB_CHECK(bs, level, bs->firstkey[level] ||
+			cur->bc_ops->keys_inorder(cur, &bs->lastkey[level],
+					key));
+	bs->firstkey[level] = false;
+	bs->lastkey[level] = *key;
+
+	if (level + 1 >= cur->bc_nlevels)
+		return 0;
+
+	/* Is this at least as large as the parent low key? */
+	keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[level + 1]);
+	keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
+
+	XFS_BTKEY_SCRUB_CHECK(bs, level,
+			cur->bc_ops->diff_two_keys(cur, keyp, key) >= 0);
+
+	if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING))
+		return 0;
+
+	/* Is this no larger than the parent high key? */
+	key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block);
+	keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
+
+	XFS_BTKEY_SCRUB_CHECK(bs, level,
+			cur->bc_ops->diff_two_keys(cur, key, keyp) >= 0);
+
+	return 0;
+}
+
+struct check_owner {
+	struct list_head	list;
+	xfs_agblock_t		bno;
+};
+
+/*
+ * Make sure this btree block isn't in the free list and that there's
+ * an rmap record for it.
+ */
+static int
+xfs_btree_block_check_owner(
+	struct xfs_btree_scrub		*bs,
+	xfs_agblock_t			bno)
+{
+	bool				has_rmap;
+	bool				is_freesp;
+	int				error;
+
+	/* Check that this block isn't free */
+	error = xfs_alloc_record_exists(bs->bno_cur, bno, 1, &is_freesp);
+	if (error)
+		goto err;
+	XFS_BTREC_SCRUB_CHECK(bs, !is_freesp);
+
+	if (!bs->rmap_cur)
+		return 0;
+
+	/* Check that there's an rmap record for this */
+	error = xfs_rmap_record_exists(bs->rmap_cur, bno, 1, &bs->oinfo,
+			&has_rmap);
+	if (error)
+		goto err;
+	XFS_BTREC_SCRUB_CHECK(bs, has_rmap);
+err:
+	return error;
+}
+
+/* Check the owner of a btree block. */
+static int
+xfs_btree_scrub_check_owner(
+	struct xfs_btree_scrub		*bs,
+	struct xfs_buf			*bp)
+{
+	struct xfs_btree_cur		*cur = bs->cur;
+	xfs_agblock_t			bno;
+	xfs_fsblock_t			fsbno;
+	struct check_owner		*co;
+
+	fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn);
+	bno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno);
+
+	/* Do we need to defer this one? */
+	if ((!bs->rmap_cur && xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb)) ||
+	    !bs->bno_cur) {
+		co = kmem_alloc(sizeof(struct check_owner), KM_SLEEP | KM_NOFS);
+		co->bno = bno;
+		list_add_tail(&co->list, &bs->to_check);
+		return 0;
+	}
+
+	return xfs_btree_block_check_owner(bs, bno);
+}
+
+/*
+ * Visit all nodes and leaves of a btree.  Check that all pointers and
+ * records are in order, that the keys reflect the records, and use a callback
+ * so that the caller can verify individual records.  The callback is the same
+ * as the one for xfs_btree_query_range, so therefore this function also
+ * returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a negative error code.
+ */
+int
+xfs_btree_scrub(
+	struct xfs_btree_scrub		*bs)
+{
+	struct xfs_btree_cur		*cur = bs->cur;
+	union xfs_btree_ptr		ptr;
+	union xfs_btree_ptr		*pp;
+	union xfs_btree_rec		*recp;
+	struct xfs_btree_block		*block;
+	int				level;
+	struct xfs_buf			*bp;
+	int				i;
+	struct check_owner		*co, *n;
+	int				error;
+
+	/* Finish filling out the scrub state */
+	bs->error = 0;
+	bs->firstrec = true;
+	for (i = 0; i < XFS_BTREE_MAXLEVELS; i++)
+		bs->firstkey[i] = true;
+	bs->bno_cur = bs->rmap_cur = NULL;
+	INIT_LIST_HEAD(&bs->to_check);
+	if (bs->cur->bc_btnum != XFS_BTNUM_BNO)
+		bs->bno_cur = xfs_allocbt_init_cursor(cur->bc_mp, NULL,
+				bs->agf_bp, bs->cur->bc_private.a.agno,
+				XFS_BTNUM_BNO);
+	if (bs->cur->bc_btnum != XFS_BTNUM_RMAP &&
+	    xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb))
+		bs->rmap_cur = xfs_rmapbt_init_cursor(cur->bc_mp, NULL,
+				bs->agf_bp, bs->cur->bc_private.a.agno);
+
+	/* Load the root of the btree. */
+	level = cur->bc_nlevels - 1;
+	cur->bc_ops->init_ptr_from_cur(cur, &ptr);
+	error = xfs_btree_lookup_get_block(cur, level, &ptr, &block);
+	if (error)
+		goto out;
+
+	xfs_btree_get_block(cur, level, &bp);
+	error = xfs_btree_check_block(cur, block, level, bp);
+	if (error)
+		goto out;
+	error = xfs_btree_scrub_check_owner(bs, bp);
+	if (error)
+		goto out;
+
+	cur->bc_ptrs[level] = 1;
+
+	while (level < cur->bc_nlevels) {
+		block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]);
+
+		if (level == 0) {
+			/* End of leaf, pop back towards the root. */
+			if (cur->bc_ptrs[level] >
+			    be16_to_cpu(block->bb_numrecs)) {
+				if (level < cur->bc_nlevels - 1)
+					cur->bc_ptrs[level + 1]++;
+				level++;
+				continue;
+			}
+
+			/* Records in order for scrub? */
+			error = xfs_btree_scrub_rec(bs);
+			if (error)
+				goto out;
+
+			recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
+			error = bs->scrub_rec(bs, recp);
+			if (error < 0 ||
+			    error == XFS_BTREE_QUERY_RANGE_ABORT)
+				break;
+
+			cur->bc_ptrs[level]++;
+			continue;
+		}
+
+		/* End of node, pop back towards the root. */
+		if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) {
+			if (level < cur->bc_nlevels - 1)
+				cur->bc_ptrs[level + 1]++;
+			level++;
+			continue;
+		}
+
+		/* Keys in order for scrub? */
+		error = xfs_btree_scrub_key(bs, level);
+		if (error)
+			goto out;
+
+		/* Drill another level deeper. */
+		pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block);
+		level--;
+		error = xfs_btree_lookup_get_block(cur, level, pp,
+				&block);
+		if (error)
+			goto out;
+
+		xfs_btree_get_block(cur, level, &bp);
+		error = xfs_btree_check_block(cur, block, level, bp);
+		if (error)
+			goto out;
+
+		error = xfs_btree_scrub_check_owner(bs, bp);
+		if (error)
+			goto out;
+
+		cur->bc_ptrs[level] = 1;
+	}
+
+out:
+	/*
+	 * If we don't end this function with the cursor pointing at a record
+	 * block, a subsequent non-error cursor deletion will not release
+	 * node-level buffers, causing a buffer leak.  This is quite possible
+	 * with a zero-results range query, so release the buffers if we
+	 * failed to return any results.
+	 */
+	if (cur->bc_bufs[0] == NULL) {
+		for (i = 0; i < cur->bc_nlevels; i++) {
+			if (cur->bc_bufs[i]) {
+				xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]);
+				cur->bc_bufs[i] = NULL;
+				cur->bc_ptrs[i] = 0;
+				cur->bc_ra[i] = 0;
+			}
+		}
+	}
+
+	/* Check the deferred stuff */
+	if (!error) {
+		if (bs->cur->bc_btnum == XFS_BTNUM_BNO)
+			bs->bno_cur = bs->cur;
+		else if (bs->cur->bc_btnum == XFS_BTNUM_RMAP)
+			bs->rmap_cur = bs->cur;
+		list_for_each_entry(co, &bs->to_check, list) {
+			error = xfs_btree_block_check_owner(bs, co->bno);
+			if (error)
+				break;
+		}
+	}
+	list_for_each_entry_safe(co, n, &bs->to_check, list) {
+		list_del(&co->list);
+		kmem_free(co);
+	}
+
+	if (bs->bno_cur && bs->bno_cur != bs->cur)
+		xfs_btree_del_cursor(bs->bno_cur, XFS_BTREE_ERROR);
+	if (bs->rmap_cur && bs->rmap_cur != bs->cur)
+		xfs_btree_del_cursor(bs->rmap_cur, XFS_BTREE_ERROR);
+
+	if (error || bs->error)
+		xfs_alert(cur->bc_mp,
+			"Corruption detected. Unmount and run xfs_repair.");
+
+	return error;
+}
diff --git a/fs/xfs/libxfs/xfs_scrub.h b/fs/xfs/libxfs/xfs_scrub.h
new file mode 100644
index 0000000..af80a9d
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_scrub.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Oracle.  All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef __XFS_SCRUB_H__
+#define	__XFS_SCRUB_H__
+
+/* btree scrub */
+struct xfs_btree_scrub;
+
+typedef int (*xfs_btree_scrub_rec_fn)(
+	struct xfs_btree_scrub	*bs,
+	union xfs_btree_rec	*rec);
+
+struct xfs_btree_scrub {
+	/* caller-provided scrub state */
+	struct xfs_btree_cur		*cur;
+	xfs_btree_scrub_rec_fn		scrub_rec;
+	struct xfs_buf			*agi_bp;
+	struct xfs_buf			*agf_bp;
+	struct xfs_buf			*agfl_bp;
+	struct xfs_owner_info		oinfo;
+
+	/* internal scrub state */
+	union xfs_btree_rec		lastrec;
+	bool				firstrec;
+	union xfs_btree_key		lastkey[XFS_BTREE_MAXLEVELS];
+	bool				firstkey[XFS_BTREE_MAXLEVELS];
+	struct xfs_btree_cur		*rmap_cur;
+	struct xfs_btree_cur		*bno_cur;
+	struct list_head		to_check;
+	int				error;
+};
+
+int xfs_btree_scrub(struct xfs_btree_scrub *bs);
+void xfs_btree_scrub_error(struct xfs_btree_cur *cur, int level,
+		const char *file, int line, const char *check);
+#define XFS_BTREC_SCRUB_CHECK(bs, fs_ok) \
+	if (!(fs_ok)) { \
+		xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \
+		(bs)->error = -EFSCORRUPTED; \
+	}
+#define XFS_BTREC_SCRUB_GOTO(bs, fs_ok, label) \
+	if (!(fs_ok)) { \
+		xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \
+		(bs)->error = -EFSCORRUPTED; \
+		goto label; \
+	}
+#define XFS_BTKEY_SCRUB_CHECK(bs, level, fs_ok) \
+	if (!(fs_ok)) { \
+		xfs_btree_scrub_error((bs)->cur, (level), __FILE__, __LINE__, #fs_ok); \
+		(bs)->error = -EFSCORRUPTED; \
+	}
+#define XFS_BTKEY_SCRUB_GOTO(bs, level, fs_ok, label) \
+	if (!(fs_ok)) { \
+		xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \
+		(bs)->error = -EFSCORRUPTED; \
+		goto label; \
+	}
+
+#endif	/* __XFS_SCRUB_H__ */


  parent reply	other threads:[~2016-06-17  1:30 UTC|newest]

Thread overview: 236+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-17  1:17 [PATCH v6 000/119] xfs: add reverse mapping, reflink, dedupe, and online scrub support Darrick J. Wong
2016-06-17  1:17 ` [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range Darrick J. Wong
2016-06-17 11:32   ` Christoph Hellwig
2016-06-28 19:19     ` Darrick J. Wong
2016-06-17  1:18 ` [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Darrick J. Wong
2016-06-17 11:41   ` Christoph Hellwig
2016-06-17 12:16     ` Brian Foster
2016-06-17 15:06       ` Christoph Hellwig
2016-06-17 16:54       ` Darrick J. Wong
2016-06-17 17:38         ` Brian Foster
2016-06-17  1:18 ` [PATCH 003/119] xfs: check offsets of variable length structures Darrick J. Wong
2016-06-17 11:33   ` Christoph Hellwig
2016-06-17 17:34   ` Brian Foster
2016-06-18 18:01     ` Darrick J. Wong
2016-06-20 12:38       ` Brian Foster
2016-06-17  1:18 ` [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace Darrick J. Wong
2016-06-17 11:34   ` Christoph Hellwig
2016-06-21  0:47     ` Dave Chinner
2016-06-17  1:18 ` [PATCH 005/119] xfs: check for a valid error_tag in errortag_add Darrick J. Wong
2016-06-17 11:34   ` Christoph Hellwig
2016-06-17  1:18 ` [PATCH 006/119] xfs: port differences from xfsprogs libxfs Darrick J. Wong
2016-06-17 15:06   ` Christoph Hellwig
2016-06-20  0:21   ` Dave Chinner
2016-07-13 23:39     ` Darrick J. Wong
2016-06-17  1:18 ` [PATCH 007/119] xfs: rearrange xfs_bmap_add_free parameters Darrick J. Wong
2016-06-17 11:39   ` Christoph Hellwig
2016-06-17  1:18 ` [PATCH 008/119] xfs: separate freelist fixing into a separate helper Darrick J. Wong
2016-06-17 11:52   ` Christoph Hellwig
2016-06-21  0:48     ` Dave Chinner
2016-06-21  1:40   ` Dave Chinner
2016-06-17  1:18 ` [PATCH 009/119] xfs: convert list of extents to free into a regular list Darrick J. Wong
2016-06-17 11:59   ` Christoph Hellwig
2016-06-18 20:15     ` Darrick J. Wong
2016-06-21  0:57       ` Dave Chinner
2016-06-17  1:18 ` [PATCH 010/119] xfs: create a standard btree size calculator code Darrick J. Wong
2016-06-20 14:31   ` Brian Foster
2016-06-20 19:34     ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 011/119] xfs: refactor btree maxlevels computation Darrick J. Wong
2016-06-20 14:31   ` Brian Foster
2016-06-20 18:23     ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion Darrick J. Wong
2016-06-21 13:00   ` Brian Foster
2016-06-27 22:30     ` Darrick J. Wong
2016-06-28 12:31       ` Brian Foster
2016-06-17  1:19 ` [PATCH 013/119] xfs: support btrees with overlapping intervals for keys Darrick J. Wong
2016-06-22 15:17   ` Brian Foster
2016-06-28  3:26     ` Darrick J. Wong
2016-06-28 12:32       ` Brian Foster
2016-06-28 17:36         ` Darrick J. Wong
2016-07-06  4:59   ` Dave Chinner
2016-07-06  8:09     ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 014/119] xfs: introduce interval queries on btrees Darrick J. Wong
2016-06-22 15:18   ` Brian Foster
2016-06-27 21:07     ` Darrick J. Wong
2016-06-28 12:32       ` Brian Foster
2016-06-28 16:29         ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 015/119] xfs: refactor btree owner change into a separate visit-blocks function Darrick J. Wong
2016-06-23 17:19   ` Brian Foster
2016-06-17  1:19 ` [PATCH 016/119] xfs: move deferred operations into a separate file Darrick J. Wong
2016-06-27 13:14   ` Brian Foster
2016-06-27 19:14     ` Darrick J. Wong
2016-06-28 12:32       ` Brian Foster
2016-06-28 18:51         ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 017/119] xfs: add tracepoints for the deferred ops mechanism Darrick J. Wong
2016-06-27 13:15   ` Brian Foster
2016-06-17  1:19 ` [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Darrick J. Wong
2016-06-27 13:15   ` Brian Foster
2016-06-27 21:41     ` Darrick J. Wong
2016-06-27 22:00       ` Darrick J. Wong
2016-06-28 12:32         ` Brian Foster
2016-06-28 16:33           ` Darrick J. Wong
2016-06-17  1:19 ` [PATCH 019/119] xfs: rework xfs_bmap_free callers to use xfs_defer_ops Darrick J. Wong
2016-06-17  1:20 ` [PATCH 020/119] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* Darrick J. Wong
2016-06-30  0:11   ` Darrick J. Wong
2016-06-17  1:20 ` [PATCH 021/119] xfs: rename flist/free_list to dfops Darrick J. Wong
2016-06-17  1:20 ` [PATCH 022/119] xfs: add tracepoints and error injection for deferred extent freeing Darrick J. Wong
2016-06-17  1:20 ` [PATCH 023/119] xfs: introduce rmap btree definitions Darrick J. Wong
2016-06-30 17:32   ` Brian Foster
2016-06-17  1:20 ` [PATCH 024/119] xfs: add rmap btree stats infrastructure Darrick J. Wong
2016-06-30 17:32   ` Brian Foster
2016-06-17  1:20 ` [PATCH 025/119] xfs: rmap btree add more reserved blocks Darrick J. Wong
2016-06-30 17:32   ` Brian Foster
2016-06-17  1:20 ` [PATCH 026/119] xfs: add owner field to extent allocation and freeing Darrick J. Wong
2016-07-06  4:01   ` Dave Chinner
2016-07-06  6:44     ` Darrick J. Wong
2016-07-07 15:12   ` Brian Foster
2016-07-07 19:09     ` Darrick J. Wong
2016-07-07 22:55       ` Dave Chinner
2016-07-08 11:37       ` Brian Foster
2016-06-17  1:20 ` [PATCH 027/119] xfs: introduce rmap extent operation stubs Darrick J. Wong
2016-06-17  1:20 ` [PATCH 028/119] xfs: define the on-disk rmap btree format Darrick J. Wong
2016-07-06  4:05   ` Dave Chinner
2016-07-06  6:44     ` Darrick J. Wong
2016-07-07 18:41   ` Brian Foster
2016-07-07 19:18     ` Darrick J. Wong
2016-07-07 23:14       ` Dave Chinner
2016-07-07 23:58         ` Darrick J. Wong
2016-06-17  1:20 ` [PATCH 029/119] xfs: add rmap btree growfs support Darrick J. Wong
2016-06-17  1:21 ` [PATCH 030/119] xfs: rmap btree transaction reservations Darrick J. Wong
2016-07-08 13:21   ` Brian Foster
2016-06-17  1:21 ` [PATCH 031/119] xfs: rmap btree requires more reserved free space Darrick J. Wong
2016-07-08 13:21   ` Brian Foster
2016-07-13 16:50     ` Darrick J. Wong
2016-07-13 18:32       ` Brian Foster
2016-07-13 23:50         ` Dave Chinner
2016-06-17  1:21 ` [PATCH 032/119] xfs: add rmap btree operations Darrick J. Wong
2016-07-08 18:33   ` Brian Foster
2016-07-08 23:53     ` Darrick J. Wong
2016-06-17  1:21 ` [PATCH 033/119] xfs: support overlapping intervals in the rmap btree Darrick J. Wong
2016-07-08 18:33   ` Brian Foster
2016-07-09  0:14     ` Darrick J. Wong
2016-07-09 13:25       ` Brian Foster
2016-06-17  1:21 ` [PATCH 034/119] xfs: teach rmapbt to support interval queries Darrick J. Wong
2016-07-08 18:34   ` Brian Foster
2016-07-09  0:16     ` Darrick J. Wong
2016-07-09 13:25       ` Brian Foster
2016-06-17  1:21 ` [PATCH 035/119] xfs: add tracepoints for the rmap functions Darrick J. Wong
2016-07-08 18:34   ` Brian Foster
2016-06-17  1:21 ` [PATCH 036/119] xfs: add an extent to the rmap btree Darrick J. Wong
2016-07-11 18:49   ` Brian Foster
2016-07-11 23:01     ` Darrick J. Wong
2016-06-17  1:21 ` [PATCH 037/119] xfs: remove an extent from " Darrick J. Wong
2016-07-11 18:49   ` Brian Foster
2016-06-17  1:21 ` [PATCH 038/119] xfs: convert unwritten status of reverse mappings Darrick J. Wong
2016-06-30  0:15   ` Darrick J. Wong
2016-07-13 18:27   ` Brian Foster
2016-07-13 20:43     ` Darrick J. Wong
2016-06-17  1:22 ` [PATCH 039/119] xfs: add rmap btree insert and delete helpers Darrick J. Wong
2016-07-13 18:28   ` Brian Foster
2016-07-13 18:37     ` Darrick J. Wong
2016-07-13 18:42       ` Brian Foster
2016-06-17  1:22 ` [PATCH 040/119] xfs: create helpers for mapping, unmapping, and converting file fork extents Darrick J. Wong
2016-07-13 18:28   ` Brian Foster
2016-07-13 18:47     ` Darrick J. Wong
2016-07-13 23:54       ` Dave Chinner
2016-07-13 23:55         ` Darrick J. Wong
2016-06-17  1:22 ` [PATCH 041/119] xfs: create rmap update intent log items Darrick J. Wong
2016-07-15 18:33   ` Brian Foster
2016-07-16  7:10     ` Darrick J. Wong
2016-06-17  1:22 ` [PATCH 042/119] xfs: log rmap intent items Darrick J. Wong
2016-07-15 18:33   ` Brian Foster
2016-07-16  7:34     ` Darrick J. Wong
2016-07-18 12:55       ` Brian Foster
2016-07-19 17:10         ` Darrick J. Wong
2016-06-17  1:22 ` [PATCH 043/119] xfs: enable the xfs_defer mechanism to process rmaps to update Darrick J. Wong
2016-07-15 18:33   ` Brian Foster
2016-06-17  1:22 ` [PATCH 044/119] xfs: propagate bmap updates to rmapbt Darrick J. Wong
2016-07-15 18:33   ` Brian Foster
2016-07-16  7:26     ` Darrick J. Wong
2016-07-18  1:21       ` Dave Chinner
2016-07-18 12:56         ` Brian Foster
2016-07-18 12:55       ` Brian Foster
2016-07-19  1:53         ` Darrick J. Wong
2016-07-19 11:37           ` Brian Foster
2016-06-17  1:22 ` [PATCH 045/119] xfs: add rmap btree geometry feature flag Darrick J. Wong
2016-07-18 13:34   ` Brian Foster
2016-06-17  1:22 ` [PATCH 046/119] xfs: add rmap btree block detection to log recovery Darrick J. Wong
2016-07-18 13:34   ` Brian Foster
2016-06-17  1:22 ` [PATCH 047/119] xfs: disable XFS_IOC_SWAPEXT when rmap btree is enabled Darrick J. Wong
2016-07-18 13:34   ` Brian Foster
2016-07-18 16:18     ` Darrick J. Wong
2016-06-17  1:22 ` [PATCH 048/119] xfs: don't update rmapbt when fixing agfl Darrick J. Wong
2016-07-18 13:34   ` Brian Foster
2016-07-18 15:53     ` Darrick J. Wong
2016-06-17  1:23 ` [PATCH 049/119] xfs: enable the rmap btree functionality Darrick J. Wong
2016-07-18 13:34   ` Brian Foster
2016-06-17  1:23 ` [PATCH 050/119] xfs: count the blocks in a btree Darrick J. Wong
2016-06-17  1:23 ` [PATCH 051/119] xfs: introduce tracepoints for AG reservation code Darrick J. Wong
2016-06-17  1:23 ` [PATCH 052/119] xfs: set up per-AG free space reservations Darrick J. Wong
2016-06-17  1:23 ` [PATCH 053/119] xfs: define tracepoints for refcount btree activities Darrick J. Wong
2016-06-17  1:23 ` [PATCH 054/119] xfs: introduce refcount btree definitions Darrick J. Wong
2016-06-17  1:23 ` [PATCH 055/119] xfs: add refcount btree stats infrastructure Darrick J. Wong
2016-06-17  1:23 ` [PATCH 056/119] xfs: refcount btree add more reserved blocks Darrick J. Wong
2016-06-17  1:23 ` [PATCH 057/119] xfs: define the on-disk refcount btree format Darrick J. Wong
2016-06-17  1:24 ` [PATCH 058/119] xfs: add refcount btree support to growfs Darrick J. Wong
2016-06-17  1:24 ` [PATCH 059/119] xfs: account for the refcount btree in the alloc/free log reservation Darrick J. Wong
2016-06-17  1:24 ` [PATCH 060/119] xfs: add refcount btree operations Darrick J. Wong
2016-06-17  1:24 ` [PATCH 061/119] xfs: create refcount update intent log items Darrick J. Wong
2016-06-17  1:24 ` [PATCH 062/119] xfs: log refcount intent items Darrick J. Wong
2016-06-17  1:24 ` [PATCH 063/119] xfs: adjust refcount of an extent of blocks in refcount btree Darrick J. Wong
2016-06-17  1:24 ` [PATCH 064/119] xfs: connect refcount adjust functions to upper layers Darrick J. Wong
2016-06-17  1:24 ` [PATCH 065/119] xfs: adjust refcount when unmapping file blocks Darrick J. Wong
2016-06-17  1:24 ` [PATCH 066/119] xfs: add refcount btree block detection to log recovery Darrick J. Wong
2016-06-17  1:25 ` [PATCH 067/119] xfs: refcount btree requires more reserved space Darrick J. Wong
2016-06-17  1:25 ` [PATCH 068/119] xfs: introduce reflink utility functions Darrick J. Wong
2016-06-17  1:25 ` [PATCH 069/119] xfs: create bmbt update intent log items Darrick J. Wong
2016-06-17  1:25 ` [PATCH 070/119] xfs: log bmap intent items Darrick J. Wong
2016-06-17  1:25 ` [PATCH 071/119] xfs: map an inode's offset to an exact physical block Darrick J. Wong
2016-06-17  1:25 ` [PATCH 072/119] xfs: implement deferred bmbt map/unmap operations Darrick J. Wong
2016-06-17  1:25 ` [PATCH 073/119] xfs: return work remaining at the end of a bunmapi operation Darrick J. Wong
2016-06-17  1:25 ` [PATCH 074/119] xfs: define tracepoints for reflink activities Darrick J. Wong
2016-06-17  1:25 ` [PATCH 075/119] xfs: add reflink feature flag to geometry Darrick J. Wong
2016-06-17  1:25 ` [PATCH 076/119] xfs: don't allow reflinked dir/dev/fifo/socket/pipe files Darrick J. Wong
2016-06-17  1:26 ` [PATCH 077/119] xfs: introduce the CoW fork Darrick J. Wong
2016-06-17  1:26 ` [PATCH 078/119] xfs: support bmapping delalloc extents in " Darrick J. Wong
2016-06-17  1:26 ` [PATCH 079/119] xfs: create delalloc extents in " Darrick J. Wong
2016-06-17  1:26 ` [PATCH 080/119] xfs: support allocating delayed " Darrick J. Wong
2016-06-17  1:26 ` [PATCH 081/119] xfs: allocate " Darrick J. Wong
2016-06-17  1:26 ` [PATCH 082/119] xfs: support removing extents from " Darrick J. Wong
2016-06-17  1:26 ` [PATCH 083/119] xfs: move mappings from cow fork to data fork after copy-write Darrick J. Wong
2016-06-17  1:26 ` [PATCH 084/119] xfs: implement CoW for directio writes Darrick J. Wong
2016-06-17  1:26 ` [PATCH 085/119] xfs: copy-on-write reflinked blocks when zeroing ranges of blocks Darrick J. Wong
2016-06-17  1:27 ` [PATCH 086/119] xfs: cancel CoW reservations and clear inode reflink flag when freeing blocks Darrick J. Wong
2016-06-17  1:27 ` [PATCH 087/119] xfs: cancel pending CoW reservations when destroying inodes Darrick J. Wong
2016-06-17  1:27 ` [PATCH 088/119] xfs: store in-progress CoW allocations in the refcount btree Darrick J. Wong
2016-06-17  1:27 ` [PATCH 089/119] xfs: reflink extents from one file to another Darrick J. Wong
2016-06-17  1:27 ` [PATCH 090/119] xfs: add clone file and clone range vfs functions Darrick J. Wong
2016-06-17  1:27 ` [PATCH 091/119] xfs: add dedupe range vfs function Darrick J. Wong
2016-06-17  1:27 ` [PATCH 092/119] xfs: teach get_bmapx and fiemap about shared extents and the CoW fork Darrick J. Wong
2016-06-17  1:27 ` [PATCH 093/119] xfs: swap inode reflink flags when swapping inode extents Darrick J. Wong
2016-06-17  1:27 ` [PATCH 094/119] xfs: unshare a range of blocks via fallocate Darrick J. Wong
2016-06-17  1:28 ` [PATCH 095/119] xfs: CoW shared EOF block when truncating file Darrick J. Wong
2016-06-17  1:28 ` [PATCH 096/119] xfs: support FS_XFLAG_REFLINK on reflink filesystems Darrick J. Wong
2016-06-17  1:28 ` [PATCH 097/119] xfs: create a separate cow extent size hint for the allocator Darrick J. Wong
2016-06-17  1:28 ` [PATCH 098/119] xfs: preallocate blocks for worst-case btree expansion Darrick J. Wong
2016-06-17  1:28 ` [PATCH 099/119] xfs: don't allow reflink when the AG is low on space Darrick J. Wong
2016-06-17  1:28 ` [PATCH 100/119] xfs: try other AGs to allocate a BMBT block Darrick J. Wong
2016-06-17  1:28 ` [PATCH 101/119] xfs: promote buffered writes to CoW when cowextsz is set Darrick J. Wong
2016-06-17  1:28 ` [PATCH 102/119] xfs: garbage collect old cowextsz reservations Darrick J. Wong
2016-06-17  1:28 ` [PATCH 103/119] xfs: provide switch to force filesystem to copy-on-write all the time Darrick J. Wong
2016-06-17  1:29 ` [PATCH 104/119] xfs: increase log reservations for reflink Darrick J. Wong
2016-06-17  1:29 ` [PATCH 105/119] xfs: use interval query for rmap alloc operations on shared files Darrick J. Wong
2016-06-17  1:29 ` [PATCH 106/119] xfs: convert unwritten status of reverse mappings for " Darrick J. Wong
2016-06-17  1:29 ` [PATCH 107/119] xfs: set a default CoW extent size of 32 blocks Darrick J. Wong
2016-06-17  1:29 ` [PATCH 108/119] xfs: don't allow realtime and reflinked files to mix Darrick J. Wong
2016-06-17  1:29 ` [PATCH 109/119] xfs: don't mix reflink and DAX mode for now Darrick J. Wong
2016-06-17  1:29 ` [PATCH 110/119] xfs: fail ->bmap for reflink inodes Darrick J. Wong
2016-06-17  1:29 ` [PATCH 111/119] xfs: recognize the reflink feature bit Darrick J. Wong
2016-06-17  1:29 ` [PATCH 112/119] xfs: introduce the XFS_IOC_GETFSMAPX ioctl Darrick J. Wong
2016-06-17  1:30 ` Darrick J. Wong [this message]
2016-06-17  1:30 ` [PATCH 114/119] xfs: create sysfs hooks to scrub various files Darrick J. Wong
2016-06-17  1:30 ` [PATCH 115/119] xfs: support scrubbing free space btrees Darrick J. Wong
2016-06-17  1:30 ` [PATCH 116/119] xfs: support scrubbing inode btrees Darrick J. Wong
2016-06-17  1:30 ` [PATCH 117/119] xfs: support scrubbing rmap btree Darrick J. Wong
2016-06-17  1:30 ` [PATCH 118/119] xfs: support scrubbing refcount btree Darrick J. Wong
2016-06-17  1:30 ` [PATCH 119/119] xfs: add btree scrub tracepoints Darrick J. Wong

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=146612700354.12839.18272855403371334654.stgit@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=david@fromorbit.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=vishal.l.verma@intel.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;
as well as URLs for NNTP newsgroup(s).