Support XFS

diff --git a/utils/fstype.c b/utils/fstype.c
index bbc236a..743e449 100644
--- a/utils/fstype.c
+++ b/utils/fstype.c
@@ -7,7 +7,7 @@
  *  FSSIZE - filesystem size (if known)
  *
  * We currently detect (in order):
- *  gzip, cramfs, romfs, minix, ext3, ext2, reiserfs
+ *  gzip, cramfs, romfs, xfs, minix, ext3, ext2, reiserfs
  *
  * MINIX, ext3 and Reiserfs bits are currently untested.
  */
@@ -24,6 +24,7 @@
 #define _LINUX_EXT2_FS_SB
 #include <linux/ext2_fs.h>
 #include "ext3_fs.h"
+#include "xfs_sb.h"
 
 /*
  * reiserfs_fs.h is too sick to include directly.
@@ -160,6 +161,19 @@
 	return 0;
 }
 
+static int xfs_image(const unsigned char *buf, unsigned long *blocks)
+{
+	const struct xfs_sb *sb =
+		(const struct xfs_sb *)buf;
+
+	if (__be32_to_cpu(sb->sb_magicnum) == XFS_SB_MAGIC) {
+		*blocks = __be64_to_cpu(sb->sb_dblocks) *
+			  (__be32_to_cpu(sb->sb_blocksize) / BLOCK_SIZE);
+		return 1;
+	}
+	return 0;
+}
+
 struct imagetype {
 	off_t		block;
 	const char	name[12];
@@ -170,6 +184,7 @@
 	{ 0,	"gzip",		gzip_image	},
 	{ 0,	"cramfs",	cramfs_image	},
 	{ 0,	"romfs",	romfs_image	},
+	{ 0,	"xfs",		xfs_image	},
 	{ 1,	"minix",	minix_image	},
 	{ 1,	"ext3",		ext3_image	},
 	{ 1,	"ext2",		ext2_image	},
diff --git a/utils/xfs_sb.h b/utils/xfs_sb.h
new file mode 100644
index 0000000..ffc79b1
--- /dev/null
+++ b/utils/xfs_sb.h
@@ -0,0 +1,17 @@
+/*
+ * Super block
+ * Fits into a sector-sized buffer at address 0 of each allocation group.
+ * Only the first of these is ever updated except during growfs.
+ */
+
+struct xfs_buf;
+struct xfs_mount;
+
+#define	XFS_SB_MAGIC		0x58465342	/* 'XFSB' */
+
+typedef struct xfs_sb
+{
+	__u32	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
+	__u32	sb_blocksize;	/* logical block size, bytes */
+	__u64	sb_dblocks;	/* number of data blocks */
+} xfs_sb_t;