All of lore.kernel.org
 help / color / mirror / Atom feed
* misc cleanups
@ 2017-04-19 19:29 Christoph Hellwig
  2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-19 19:29 UTC (permalink / raw)
  To: linux-xfs

Remove some unused #defines / enums and simplify the validation of
the unwritten extent bit.


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

* [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define
  2017-04-19 19:29 misc cleanups Christoph Hellwig
@ 2017-04-19 19:29 ` Christoph Hellwig
  2017-04-19 19:57   ` Darrick J. Wong
  2017-04-19 19:58   ` Eric Sandeen
  2017-04-19 19:29 ` [PATCH 2/3] xfs: remove unused values from xfs_exntst_t Christoph Hellwig
  2017-04-19 19:29 ` [PATCH 3/3] xfs: simplify validation of the unwritten extent bit Christoph Hellwig
  2 siblings, 2 replies; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-19 19:29 UTC (permalink / raw)
  To: linux-xfs

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_format.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 6b7579e7b60a..d114ed80a076 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -930,10 +930,8 @@ static inline uint xfs_dinode_size(int version)
 /*
  * The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
  * Since the pathconf interface is signed, we use 2^31 - 1 instead.
- * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
  */
 #define	XFS_MAXLINK		((1U << 31) - 1U)
-#define	XFS_MAXLINK_1		65535U
 
 /*
  * Values for di_format
-- 
2.11.0


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

* [PATCH 2/3] xfs: remove unused values from xfs_exntst_t
  2017-04-19 19:29 misc cleanups Christoph Hellwig
  2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
@ 2017-04-19 19:29 ` Christoph Hellwig
  2017-04-19 19:59   ` Darrick J. Wong
  2017-04-19 19:59   ` Eric Sandeen
  2017-04-19 19:29 ` [PATCH 3/3] xfs: simplify validation of the unwritten extent bit Christoph Hellwig
  2 siblings, 2 replies; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-19 19:29 UTC (permalink / raw)
  To: linux-xfs

We only ever use the normal and unwritten states.  And the actual
ondisk format (this enum isn't despite being in xfs_format.h) only
has space for the unwritten bit anyway.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_format.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index d114ed80a076..8425884668a8 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1588,7 +1588,6 @@ typedef enum {
  */
 typedef enum {
 	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
-	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
 } xfs_exntst_t;
 
 /*
-- 
2.11.0


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

* [PATCH 3/3] xfs: simplify validation of the unwritten extent bit
  2017-04-19 19:29 misc cleanups Christoph Hellwig
  2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
  2017-04-19 19:29 ` [PATCH 2/3] xfs: remove unused values from xfs_exntst_t Christoph Hellwig
@ 2017-04-19 19:29 ` Christoph Hellwig
  2017-04-19 20:17   ` Darrick J. Wong
  2 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-19 19:29 UTC (permalink / raw)
  To: linux-xfs

XFS only supports the unwritten extent bit in the data fork, and only if
the file system has a version 5 superblock or the unwritten extent
feature bit.

We currently have two routines that validate the invariant:
xfs_check_nostate_extents which return -EFSCORRUPTED when it's not met,
and xfs_validate_extent that triggers and assert in debug build.

Both of them iterate over all extents of an inode fork when called,
which isn't very efficient.

This patch instead adds a new helper that verifies the invariant one
extent at a time, and calls it from the places where we iterate over
all extents to converted them from or two the in-memory format.  The
callers then return -EFSCORRUPTED when reading invalid extents from
disk, or trigger an assert when writing them to disk.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_bmap.c       | 16 +-------
 fs/xfs/libxfs/xfs_bmap.h       |  2 -
 fs/xfs/libxfs/xfs_bmap_btree.c | 26 ------------
 fs/xfs/libxfs/xfs_bmap_btree.h | 21 ++++++----
 fs/xfs/libxfs/xfs_format.h     |  8 ----
 fs/xfs/libxfs/xfs_inode_fork.c | 90 ++++++++++++------------------------------
 6 files changed, 41 insertions(+), 122 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 9bd104f32908..ad5ae571f74f 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1260,7 +1260,6 @@ xfs_bmap_read_extents(
 	xfs_fsblock_t		bno;	/* block # of "block" */
 	xfs_buf_t		*bp;	/* buffer for "block" */
 	int			error;	/* error return value */
-	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
 	xfs_extnum_t		i, j;	/* index into the extents list */
 	xfs_ifork_t		*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
@@ -1271,8 +1270,6 @@ xfs_bmap_read_extents(
 
 	mp = ip->i_mount;
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
-					XFS_EXTFMT_INODE(ip);
 	block = ifp->if_broot;
 	/*
 	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
@@ -1340,18 +1337,9 @@ xfs_bmap_read_extents(
 			xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
 			trp->l0 = be64_to_cpu(frp->l0);
 			trp->l1 = be64_to_cpu(frp->l1);
-		}
-		if (exntf == XFS_EXTFMT_NOSTATE) {
-			/*
-			 * Check all attribute bmap btree records and
-			 * any "older" data bmap btree records for a
-			 * set bit in the "extent flag" position.
-			 */
-			if (unlikely(xfs_check_nostate_extents(ifp,
-					start, num_recs))) {
+			if (!xfs_bmbt_validate_extent(mp, whichfork, trp)) {
 				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
-						 XFS_ERRLEVEL_LOW,
-						 ip->i_mount);
+						 XFS_ERRLEVEL_LOW, mp);
 				goto error0;
 			}
 		}
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index a6e612cabe15..c35a14fa1527 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -244,8 +244,6 @@ int	xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork,
 		struct xfs_bmbt_irec *del);
 void	xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx,
 		struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del);
-int	xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
-		xfs_extnum_t num);
 uint	xfs_default_attroffset(struct xfs_inode *ip);
 int	xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
 		xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index fd55db479385..a5d34a37f314 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -366,32 +366,6 @@ xfs_bmbt_to_bmdr(
 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 }
 
-/*
- * Check extent records, which have just been read, for
- * any bit in the extent flag field. ASSERT on debug
- * kernels, as this condition should not occur.
- * Return an error condition (1) if any flags found,
- * otherwise return 0.
- */
-
-int
-xfs_check_nostate_extents(
-	xfs_ifork_t		*ifp,
-	xfs_extnum_t		idx,
-	xfs_extnum_t		num)
-{
-	for (; num > 0; num--, idx++) {
-		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
-		if ((ep->l0 >>
-		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
-			ASSERT(0);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-
 STATIC struct xfs_btree_cur *
 xfs_bmbt_dup_cursor(
 	struct xfs_btree_cur	*cur)
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index 90347a99c6d2..9da5a8d4f184 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -25,13 +25,6 @@ struct xfs_inode;
 struct xfs_trans;
 
 /*
- * Extent state and extent format macros.
- */
-#define XFS_EXTFMT_INODE(x)	\
-	(xfs_sb_version_hasextflgbit(&((x)->i_mount->m_sb)) ? \
-		XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE)
-
-/*
  * Btree block header size depends on a superblock flag.
  */
 #define XFS_BMBT_BLOCK_LEN(mp) \
@@ -139,4 +132,18 @@ extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
 extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
 		struct xfs_trans *, struct xfs_inode *, int);
 
+/*
+ * Check that the extent does not contain an invalid unwritten extent flag.
+ */
+static inline bool xfs_bmbt_validate_extent(struct xfs_mount *mp, int whichfork,
+		struct xfs_bmbt_rec_host *ep)
+{
+	if (ep->l0 >> (64 - BMBT_EXNTFLAG_BITLEN) == 0)
+		return true;
+	if (whichfork == XFS_DATA_FORK &&
+	    xfs_sb_version_hasextflgbit(&mp->m_sb))
+		return true;
+	return false;
+}
+
 #endif	/* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 8425884668a8..a1dccd8d96bc 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1576,14 +1576,6 @@ static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
 }
 
 /*
- * Possible extent formats.
- */
-typedef enum {
-	XFS_EXTFMT_NOSTATE = 0,
-	XFS_EXTFMT_HASSTATE
-} xfs_exntfmt_t;
-
-/*
  * Possible extent states.
  */
 typedef enum {
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 8a37efe04de3..0e80f34fe97c 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -42,35 +42,6 @@ STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
 STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
 STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
 
-#ifdef DEBUG
-/*
- * Make sure that the extents in the given memory buffer
- * are valid.
- */
-void
-xfs_validate_extents(
-	xfs_ifork_t		*ifp,
-	int			nrecs,
-	xfs_exntfmt_t		fmt)
-{
-	xfs_bmbt_irec_t		irec;
-	xfs_bmbt_rec_host_t	rec;
-	int			i;
-
-	for (i = 0; i < nrecs; i++) {
-		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
-		rec.l0 = get_unaligned(&ep->l0);
-		rec.l1 = get_unaligned(&ep->l1);
-		xfs_bmbt_get_all(&rec, &irec);
-		if (fmt == XFS_EXTFMT_NOSTATE)
-			ASSERT(irec.br_state == XFS_EXT_NORM);
-	}
-}
-#else /* DEBUG */
-#define xfs_validate_extents(ifp, nrecs, fmt)
-#endif /* DEBUG */
-
-
 /*
  * Move inode type and inode format specific information from the
  * on-disk inode to the in-core inode.  For fifos, devs, and sockets
@@ -352,40 +323,33 @@ xfs_iformat_local(
 }
 
 /*
- * The file consists of a set of extents all
- * of which fit into the on-disk inode.
- * If there are few enough extents to fit into
- * the if_inline_ext, then copy them there.
- * Otherwise allocate a buffer for them and copy
- * them into it.  Either way, set if_extents
- * to point at the extents.
+ * The file consists of a set of extents all of which fit into the on-disk
+ * inode.  If there are few enough extents to fit into the if_inline_ext, then
+ * copy them there.  Otherwise allocate a buffer for them and copy them into it.
+ * Either way, set if_extents to point at the extents.
  */
 STATIC int
 xfs_iformat_extents(
-	xfs_inode_t	*ip,
-	xfs_dinode_t	*dip,
-	int		whichfork)
+	struct xfs_inode	*ip,
+	struct xfs_dinode	*dip,
+	int			whichfork)
 {
-	xfs_bmbt_rec_t	*dp;
-	xfs_ifork_t	*ifp;
-	int		nex;
-	int		size;
-	int		i;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	nex = XFS_DFORK_NEXTENTS(dip, whichfork);
-	size = nex * (uint)sizeof(xfs_bmbt_rec_t);
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
+	int			nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+	int			size = nex * sizeof(xfs_bmbt_rec_t);
+	struct xfs_bmbt_rec	*dp;
+	int			i;
 
 	/*
-	 * If the number of extents is unreasonable, then something
-	 * is wrong and we just bail out rather than crash in
-	 * kmem_alloc() or memcpy() below.
+	 * If the number of extents is unreasonable, then something is wrong and
+	 * we just bail out rather than crash in kmem_alloc() or memcpy() below.
 	 */
-	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
+	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
 		xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
 			(unsigned long long) ip->i_ino, nex);
 		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
-				     ip->i_mount, dip);
+				     mp, dip);
 		return -EFSCORRUPTED;
 	}
 
@@ -400,22 +364,17 @@ xfs_iformat_extents(
 	ifp->if_bytes = size;
 	if (size) {
 		dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
-		xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
 		for (i = 0; i < nex; i++, dp++) {
 			xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
 			ep->l0 = get_unaligned_be64(&dp->l0);
 			ep->l1 = get_unaligned_be64(&dp->l1);
+			if (!xfs_bmbt_validate_extent(mp, whichfork, ep)) {
+				XFS_ERROR_REPORT("xfs_iformat_extents(2)",
+						 XFS_ERRLEVEL_LOW, mp);
+				return -EFSCORRUPTED;
+			}
 		}
 		XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
-		if (whichfork != XFS_DATA_FORK ||
-			XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
-				if (unlikely(xfs_check_nostate_extents(
-				    ifp, 0, nex))) {
-					XFS_ERROR_REPORT("xfs_iformat_extents(2)",
-							 XFS_ERRLEVEL_LOW,
-							 ip->i_mount);
-					return -EFSCORRUPTED;
-				}
 	}
 	ifp->if_flags |= XFS_IFEXTENTS;
 	return 0;
@@ -518,7 +477,6 @@ xfs_iread_extents(
 		xfs_iext_destroy(ifp);
 		return error;
 	}
-	xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
 	ifp->if_flags |= XFS_IFEXTENTS;
 	return 0;
 }
@@ -837,6 +795,9 @@ xfs_iextents_copy(
 	copied = 0;
 	for (i = 0; i < nrecs; i++) {
 		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
+
+		ASSERT(xfs_bmbt_validate_extent(ip->i_mount, whichfork, ep));
+
 		start_block = xfs_bmbt_get_startblock(ep);
 		if (isnullstartblock(start_block)) {
 			/*
@@ -852,7 +813,6 @@ xfs_iextents_copy(
 		copied++;
 	}
 	ASSERT(copied != 0);
-	xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip));
 
 	return (copied * (uint)sizeof(xfs_bmbt_rec_t));
 }
-- 
2.11.0


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

* Re: [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define
  2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
@ 2017-04-19 19:57   ` Darrick J. Wong
  2017-04-19 19:58   ` Eric Sandeen
  1 sibling, 0 replies; 11+ messages in thread
From: Darrick J. Wong @ 2017-04-19 19:57 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Apr 19, 2017 at 09:29:02PM +0200, Christoph Hellwig wrote:
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_format.h | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 6b7579e7b60a..d114ed80a076 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -930,10 +930,8 @@ static inline uint xfs_dinode_size(int version)
>  /*
>   * The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
>   * Since the pathconf interface is signed, we use 2^31 - 1 instead.
> - * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
>   */
>  #define	XFS_MAXLINK		((1U << 31) - 1U)
> -#define	XFS_MAXLINK_1		65535U

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

>  
>  /*
>   * Values for di_format
> -- 
> 2.11.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define
  2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
  2017-04-19 19:57   ` Darrick J. Wong
@ 2017-04-19 19:58   ` Eric Sandeen
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Sandeen @ 2017-04-19 19:58 UTC (permalink / raw)
  To: Christoph Hellwig, linux-xfs

On 4/19/17 2:29 PM, Christoph Hellwig wrote:
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Tricky! ;)

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  fs/xfs/libxfs/xfs_format.h | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 6b7579e7b60a..d114ed80a076 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -930,10 +930,8 @@ static inline uint xfs_dinode_size(int version)
>  /*
>   * The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
>   * Since the pathconf interface is signed, we use 2^31 - 1 instead.
> - * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
>   */
>  #define	XFS_MAXLINK		((1U << 31) - 1U)
> -#define	XFS_MAXLINK_1		65535U
>  
>  /*
>   * Values for di_format
> 

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

* Re: [PATCH 2/3] xfs: remove unused values from xfs_exntst_t
  2017-04-19 19:29 ` [PATCH 2/3] xfs: remove unused values from xfs_exntst_t Christoph Hellwig
@ 2017-04-19 19:59   ` Darrick J. Wong
  2017-04-19 19:59   ` Eric Sandeen
  1 sibling, 0 replies; 11+ messages in thread
From: Darrick J. Wong @ 2017-04-19 19:59 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Apr 19, 2017 at 09:29:03PM +0200, Christoph Hellwig wrote:
> We only ever use the normal and unwritten states.  And the actual
> ondisk format (this enum isn't despite being in xfs_format.h) only
> has space for the unwritten bit anyway.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_format.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index d114ed80a076..8425884668a8 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -1588,7 +1588,6 @@ typedef enum {
>   */
>  typedef enum {
>  	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
> -	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
>  } xfs_exntst_t;
>  
>  /*
> -- 
> 2.11.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/3] xfs: remove unused values from xfs_exntst_t
  2017-04-19 19:29 ` [PATCH 2/3] xfs: remove unused values from xfs_exntst_t Christoph Hellwig
  2017-04-19 19:59   ` Darrick J. Wong
@ 2017-04-19 19:59   ` Eric Sandeen
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Sandeen @ 2017-04-19 19:59 UTC (permalink / raw)
  To: Christoph Hellwig, linux-xfs

On 4/19/17 2:29 PM, Christoph Hellwig wrote:
> We only ever use the normal and unwritten states.  And the actual
> ondisk format (this enum isn't despite being in xfs_format.h) only
> has space for the unwritten bit anyway.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  fs/xfs/libxfs/xfs_format.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index d114ed80a076..8425884668a8 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -1588,7 +1588,6 @@ typedef enum {
>   */
>  typedef enum {
>  	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
> -	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
>  } xfs_exntst_t;
>  
>  /*
> 

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

* Re: [PATCH 3/3] xfs: simplify validation of the unwritten extent bit
  2017-04-19 19:29 ` [PATCH 3/3] xfs: simplify validation of the unwritten extent bit Christoph Hellwig
@ 2017-04-19 20:17   ` Darrick J. Wong
  2017-04-20 14:38     ` Christoph Hellwig
  0 siblings, 1 reply; 11+ messages in thread
From: Darrick J. Wong @ 2017-04-19 20:17 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Wed, Apr 19, 2017 at 09:29:04PM +0200, Christoph Hellwig wrote:
> XFS only supports the unwritten extent bit in the data fork, and only if
> the file system has a version 5 superblock or the unwritten extent
> feature bit.
> 
> We currently have two routines that validate the invariant:
> xfs_check_nostate_extents which return -EFSCORRUPTED when it's not met,
> and xfs_validate_extent that triggers and assert in debug build.
> 
> Both of them iterate over all extents of an inode fork when called,
> which isn't very efficient.
> 
> This patch instead adds a new helper that verifies the invariant one
> extent at a time, and calls it from the places where we iterate over
> all extents to converted them from or two the in-memory format.  The
> callers then return -EFSCORRUPTED when reading invalid extents from
> disk, or trigger an assert when writing them to disk.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/libxfs/xfs_bmap.c       | 16 +-------
>  fs/xfs/libxfs/xfs_bmap.h       |  2 -
>  fs/xfs/libxfs/xfs_bmap_btree.c | 26 ------------
>  fs/xfs/libxfs/xfs_bmap_btree.h | 21 ++++++----
>  fs/xfs/libxfs/xfs_format.h     |  8 ----
>  fs/xfs/libxfs/xfs_inode_fork.c | 90 ++++++++++++------------------------------
>  6 files changed, 41 insertions(+), 122 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 9bd104f32908..ad5ae571f74f 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1260,7 +1260,6 @@ xfs_bmap_read_extents(
>  	xfs_fsblock_t		bno;	/* block # of "block" */
>  	xfs_buf_t		*bp;	/* buffer for "block" */
>  	int			error;	/* error return value */
> -	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
>  	xfs_extnum_t		i, j;	/* index into the extents list */
>  	xfs_ifork_t		*ifp;	/* fork structure */
>  	int			level;	/* btree level, for checking */
> @@ -1271,8 +1270,6 @@ xfs_bmap_read_extents(
>  
>  	mp = ip->i_mount;
>  	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
> -					XFS_EXTFMT_INODE(ip);
>  	block = ifp->if_broot;
>  	/*
>  	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
> @@ -1340,18 +1337,9 @@ xfs_bmap_read_extents(
>  			xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
>  			trp->l0 = be64_to_cpu(frp->l0);
>  			trp->l1 = be64_to_cpu(frp->l1);
> -		}
> -		if (exntf == XFS_EXTFMT_NOSTATE) {
> -			/*
> -			 * Check all attribute bmap btree records and
> -			 * any "older" data bmap btree records for a
> -			 * set bit in the "extent flag" position.
> -			 */
> -			if (unlikely(xfs_check_nostate_extents(ifp,
> -					start, num_recs))) {
> +			if (!xfs_bmbt_validate_extent(mp, whichfork, trp)) {
>  				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
> -						 XFS_ERRLEVEL_LOW,
> -						 ip->i_mount);
> +						 XFS_ERRLEVEL_LOW, mp);
>  				goto error0;
>  			}
>  		}
> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
> index a6e612cabe15..c35a14fa1527 100644
> --- a/fs/xfs/libxfs/xfs_bmap.h
> +++ b/fs/xfs/libxfs/xfs_bmap.h
> @@ -244,8 +244,6 @@ int	xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork,
>  		struct xfs_bmbt_irec *del);
>  void	xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx,
>  		struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del);
> -int	xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
> -		xfs_extnum_t num);
>  uint	xfs_default_attroffset(struct xfs_inode *ip);
>  int	xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
>  		xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index fd55db479385..a5d34a37f314 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -366,32 +366,6 @@ xfs_bmbt_to_bmdr(
>  	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
>  }
>  
> -/*
> - * Check extent records, which have just been read, for
> - * any bit in the extent flag field. ASSERT on debug
> - * kernels, as this condition should not occur.
> - * Return an error condition (1) if any flags found,
> - * otherwise return 0.
> - */
> -
> -int
> -xfs_check_nostate_extents(
> -	xfs_ifork_t		*ifp,
> -	xfs_extnum_t		idx,
> -	xfs_extnum_t		num)
> -{
> -	for (; num > 0; num--, idx++) {
> -		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
> -		if ((ep->l0 >>
> -		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
> -			ASSERT(0);
> -			return 1;
> -		}
> -	}
> -	return 0;
> -}
> -
> -
>  STATIC struct xfs_btree_cur *
>  xfs_bmbt_dup_cursor(
>  	struct xfs_btree_cur	*cur)
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
> index 90347a99c6d2..9da5a8d4f184 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.h
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.h
> @@ -25,13 +25,6 @@ struct xfs_inode;
>  struct xfs_trans;
>  
>  /*
> - * Extent state and extent format macros.
> - */
> -#define XFS_EXTFMT_INODE(x)	\
> -	(xfs_sb_version_hasextflgbit(&((x)->i_mount->m_sb)) ? \
> -		XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE)
> -
> -/*
>   * Btree block header size depends on a superblock flag.
>   */
>  #define XFS_BMBT_BLOCK_LEN(mp) \
> @@ -139,4 +132,18 @@ extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
>  extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
>  		struct xfs_trans *, struct xfs_inode *, int);
>  
> +/*
> + * Check that the extent does not contain an invalid unwritten extent flag.
> + */
> +static inline bool xfs_bmbt_validate_extent(struct xfs_mount *mp, int whichfork,
> +		struct xfs_bmbt_rec_host *ep)

Would be nice to have this function formatted the same way as most of
the rest of the xfs functions, even if it is static inline...

> +{
> +	if (ep->l0 >> (64 - BMBT_EXNTFLAG_BITLEN) == 0)
> +		return true;
> +	if (whichfork == XFS_DATA_FORK &&
> +	    xfs_sb_version_hasextflgbit(&mp->m_sb))
> +		return true;
> +	return false;
> +}
> +
>  #endif	/* __XFS_BMAP_BTREE_H__ */
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 8425884668a8..a1dccd8d96bc 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -1576,14 +1576,6 @@ static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
>  }
>  
>  /*
> - * Possible extent formats.
> - */
> -typedef enum {
> -	XFS_EXTFMT_NOSTATE = 0,
> -	XFS_EXTFMT_HASSTATE
> -} xfs_exntfmt_t;
> -
> -/*
>   * Possible extent states.
>   */
>  typedef enum {
> diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
> index 8a37efe04de3..0e80f34fe97c 100644
> --- a/fs/xfs/libxfs/xfs_inode_fork.c
> +++ b/fs/xfs/libxfs/xfs_inode_fork.c
> @@ -42,35 +42,6 @@ STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
>  STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
>  STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
>  
> -#ifdef DEBUG
> -/*
> - * Make sure that the extents in the given memory buffer
> - * are valid.
> - */
> -void
> -xfs_validate_extents(
> -	xfs_ifork_t		*ifp,
> -	int			nrecs,
> -	xfs_exntfmt_t		fmt)
> -{
> -	xfs_bmbt_irec_t		irec;
> -	xfs_bmbt_rec_host_t	rec;
> -	int			i;
> -
> -	for (i = 0; i < nrecs; i++) {
> -		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
> -		rec.l0 = get_unaligned(&ep->l0);
> -		rec.l1 = get_unaligned(&ep->l1);
> -		xfs_bmbt_get_all(&rec, &irec);
> -		if (fmt == XFS_EXTFMT_NOSTATE)
> -			ASSERT(irec.br_state == XFS_EXT_NORM);
> -	}
> -}
> -#else /* DEBUG */
> -#define xfs_validate_extents(ifp, nrecs, fmt)
> -#endif /* DEBUG */
> -
> -
>  /*
>   * Move inode type and inode format specific information from the
>   * on-disk inode to the in-core inode.  For fifos, devs, and sockets
> @@ -352,40 +323,33 @@ xfs_iformat_local(
>  }
>  
>  /*
> - * The file consists of a set of extents all
> - * of which fit into the on-disk inode.
> - * If there are few enough extents to fit into
> - * the if_inline_ext, then copy them there.
> - * Otherwise allocate a buffer for them and copy
> - * them into it.  Either way, set if_extents
> - * to point at the extents.
> + * The file consists of a set of extents all of which fit into the on-disk
> + * inode.  If there are few enough extents to fit into the if_inline_ext, then
> + * copy them there.  Otherwise allocate a buffer for them and copy them into it.
> + * Either way, set if_extents to point at the extents.
>   */
>  STATIC int
>  xfs_iformat_extents(
> -	xfs_inode_t	*ip,
> -	xfs_dinode_t	*dip,
> -	int		whichfork)
> +	struct xfs_inode	*ip,
> +	struct xfs_dinode	*dip,
> +	int			whichfork)
>  {
> -	xfs_bmbt_rec_t	*dp;
> -	xfs_ifork_t	*ifp;
> -	int		nex;
> -	int		size;
> -	int		i;
> -
> -	ifp = XFS_IFORK_PTR(ip, whichfork);
> -	nex = XFS_DFORK_NEXTENTS(dip, whichfork);
> -	size = nex * (uint)sizeof(xfs_bmbt_rec_t);
> +	struct xfs_mount	*mp = ip->i_mount;
> +	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
> +	int			nex = XFS_DFORK_NEXTENTS(dip, whichfork);
> +	int			size = nex * sizeof(xfs_bmbt_rec_t);
> +	struct xfs_bmbt_rec	*dp;
> +	int			i;
>  
>  	/*
> -	 * If the number of extents is unreasonable, then something
> -	 * is wrong and we just bail out rather than crash in
> -	 * kmem_alloc() or memcpy() below.
> +	 * If the number of extents is unreasonable, then something is wrong and
> +	 * we just bail out rather than crash in kmem_alloc() or memcpy() below.
>  	 */
> -	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
> +	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
>  		xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
>  			(unsigned long long) ip->i_ino, nex);
>  		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
> -				     ip->i_mount, dip);
> +				     mp, dip);
>  		return -EFSCORRUPTED;
>  	}
>  
> @@ -400,22 +364,17 @@ xfs_iformat_extents(
>  	ifp->if_bytes = size;
>  	if (size) {
>  		dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
> -		xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
>  		for (i = 0; i < nex; i++, dp++) {
>  			xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
>  			ep->l0 = get_unaligned_be64(&dp->l0);
>  			ep->l1 = get_unaligned_be64(&dp->l1);
> +			if (!xfs_bmbt_validate_extent(mp, whichfork, ep)) {
> +				XFS_ERROR_REPORT("xfs_iformat_extents(2)",
> +						 XFS_ERRLEVEL_LOW, mp);
> +				return -EFSCORRUPTED;
> +			}
>  		}
>  		XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
> -		if (whichfork != XFS_DATA_FORK ||
> -			XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
> -				if (unlikely(xfs_check_nostate_extents(
> -				    ifp, 0, nex))) {
> -					XFS_ERROR_REPORT("xfs_iformat_extents(2)",
> -							 XFS_ERRLEVEL_LOW,
> -							 ip->i_mount);
> -					return -EFSCORRUPTED;
> -				}
>  	}
>  	ifp->if_flags |= XFS_IFEXTENTS;
>  	return 0;
> @@ -518,7 +477,6 @@ xfs_iread_extents(
>  		xfs_iext_destroy(ifp);
>  		return error;
>  	}
> -	xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
>  	ifp->if_flags |= XFS_IFEXTENTS;
>  	return 0;
>  }
> @@ -837,6 +795,9 @@ xfs_iextents_copy(
>  	copied = 0;
>  	for (i = 0; i < nrecs; i++) {
>  		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
> +
> +		ASSERT(xfs_bmbt_validate_extent(ip->i_mount, whichfork, ep));

Wouldn't this be better off in xfs_iflush_int (like the inline dir
verifier) since we could prevent bad metadata from hitting the disk?
Rather than this, which doesn't do anything on non-debug kernels.

OTOH I guess we don't do any verification of the records getting written
to the bmbt leaves either...

--D

> +
>  		start_block = xfs_bmbt_get_startblock(ep);
>  		if (isnullstartblock(start_block)) {
>  			/*
> @@ -852,7 +813,6 @@ xfs_iextents_copy(
>  		copied++;
>  	}
>  	ASSERT(copied != 0);
> -	xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip));
>  
>  	return (copied * (uint)sizeof(xfs_bmbt_rec_t));
>  }
> -- 
> 2.11.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/3] xfs: simplify validation of the unwritten extent bit
  2017-04-19 20:17   ` Darrick J. Wong
@ 2017-04-20 14:38     ` Christoph Hellwig
  2017-04-20 16:56       ` Darrick J. Wong
  0 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-20 14:38 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs

[can you trim the quote?  Makes reading it and properly quoting it
 so much easier..]

> > +static inline bool xfs_bmbt_validate_extent(struct xfs_mount *mp, int whichfork,
> > +		struct xfs_bmbt_rec_host *ep)
> 
> Would be nice to have this function formatted the same way as most of
> the rest of the xfs functions, even if it is static inline...

It's actually the usual style for our inlines.  But if you prefer it
differently I can do that.

> Wouldn't this be better off in xfs_iflush_int (like the inline dir
> verifier) since we could prevent bad metadata from hitting the disk?
> Rather than this, which doesn't do anything on non-debug kernels.

xfs_iflush_int actually calls xfs_iflush_fork which calls
xfs_iextents_copy, so it's in the right spot already.  Converting it
from an assert to an error would have to go through these layers
that don't currently expect errors.  Note that we also call
xfs_iextents_copy from xfs_inode_item_format_data_fork /
xfs_inode_item_format_attr_fork, which are called earlier than
xfs_iflush_int, where error propagation is even worse.

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

* Re: [PATCH 3/3] xfs: simplify validation of the unwritten extent bit
  2017-04-20 14:38     ` Christoph Hellwig
@ 2017-04-20 16:56       ` Darrick J. Wong
  0 siblings, 0 replies; 11+ messages in thread
From: Darrick J. Wong @ 2017-04-20 16:56 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Thu, Apr 20, 2017 at 04:38:57PM +0200, Christoph Hellwig wrote:
> [can you trim the quote?  Makes reading it and properly quoting it
>  so much easier..]
> 
> > > +static inline bool xfs_bmbt_validate_extent(struct xfs_mount *mp, int whichfork,
> > > +		struct xfs_bmbt_rec_host *ep)
> > 
> > Would be nice to have this function formatted the same way as most of
> > the rest of the xfs functions, even if it is static inline...
> 
> It's actually the usual style for our inlines.  But if you prefer it
> differently I can do that.

Nah, don't worry about it.

Though I do wonder why static inlines get different treatment; it's
rather nice to be able to search for ^xfs_function and find its
definition.

> > Wouldn't this be better off in xfs_iflush_int (like the inline dir
> > verifier) since we could prevent bad metadata from hitting the disk?
> > Rather than this, which doesn't do anything on non-debug kernels.
> 
> xfs_iflush_int actually calls xfs_iflush_fork which calls
> xfs_iextents_copy, so it's in the right spot already.  Converting it
> from an assert to an error would have to go through these layers
> that don't currently expect errors.  Note that we also call
> xfs_iextents_copy from xfs_inode_item_format_data_fork /
> xfs_inode_item_format_attr_fork, which are called earlier than
> xfs_iflush_int, where error propagation is even worse.

Fair enough.  The rest looks ok, so I'll go run it through testing.

--D

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

end of thread, other threads:[~2017-04-20 16:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-19 19:29 misc cleanups Christoph Hellwig
2017-04-19 19:29 ` [PATCH 1/3] xfs: remove the unused XFS_MAXLINK_1 define Christoph Hellwig
2017-04-19 19:57   ` Darrick J. Wong
2017-04-19 19:58   ` Eric Sandeen
2017-04-19 19:29 ` [PATCH 2/3] xfs: remove unused values from xfs_exntst_t Christoph Hellwig
2017-04-19 19:59   ` Darrick J. Wong
2017-04-19 19:59   ` Eric Sandeen
2017-04-19 19:29 ` [PATCH 3/3] xfs: simplify validation of the unwritten extent bit Christoph Hellwig
2017-04-19 20:17   ` Darrick J. Wong
2017-04-20 14:38     ` Christoph Hellwig
2017-04-20 16:56       ` Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.