[libguestfs/f16] New upstream stable version 1.14.6.

Richard W.M. Jones rjones at fedoraproject.org
Wed Dec 7 12:24:46 UTC 2011


commit 0889be725a6e41edee69077dff4acdfc64d8644c
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Wed Dec 7 12:22:55 2011 +0000

    New upstream stable version 1.14.6.
    
    - Add support for inspection of MD devices (RHBZ#760245).
    - Use git to manage patches.

 .gitignore                                         |    1 +
 ...-API-mdadm-create-for-creating-MD-devices.patch |  411 ++++++++++++++++++
 0002-New-API-list-md-devices.patch                 |  280 ++++++++++++
 ...date-list-filesystems-to-check-md-devices.patch |  204 +++++++++
 0004-New-API-mdadm-detail.patch                    |  228 ++++++++++
 ...-devices-to-guestfish-device-autocompleti.patch |   28 ++
 ...e-an-MD-variant-of-the-dummy-Fedora-image.patch |  398 +++++++++++++++++
 0007-md-Inspect-MD-devices.patch                   |   40 ++
 0008-Rename-mdadm_-apis-to-md_.patch               |  254 +++++++++++
 ...Cleanup-iteration-over-fstab-entries-in-i.patch |  115 +++++
 0010-inspection-Handle-MD-devices-in-fstab.patch   |  456 ++++++++++++++++++++
 libguestfs.spec                                    |   32 ++-
 sources                                            |    2 +-
 13 files changed, 2447 insertions(+), 2 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 052b4e8..78b70f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,3 +100,4 @@ libguestfs-1.5.3.tar.gz
 /libguestfs-1.14.3.tar.gz
 /libguestfs-1.14.4.tar.gz
 /libguestfs-1.14.5.tar.gz
+/libguestfs-1.14.6.tar.gz
diff --git a/0001-New-API-mdadm-create-for-creating-MD-devices.patch b/0001-New-API-mdadm-create-for-creating-MD-devices.patch
new file mode 100644
index 0000000..1679a2a
--- /dev/null
+++ b/0001-New-API-mdadm-create-for-creating-MD-devices.patch
@@ -0,0 +1,411 @@
+From 73d203c116777249ae37ffdc01eb539e3b1423ed Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 11 Nov 2011 11:01:46 +0000
+Subject: [PATCH 01/10] New API: mdadm-create for creating MD devices. (cherry
+ picked from commit
+ c11a92751e003b3d4bc3584b598afc9bd9d9e703)
+
+---
+ daemon/Makefile.am             |    1 +
+ daemon/md.c                    |  170 ++++++++++++++++++++++++++++++++++++++++
+ generator/generator_actions.ml |   58 ++++++++++++++
+ po/POTFILES.in                 |    1 +
+ regressions/Makefile.am        |    1 +
+ regressions/test-mdadm.sh      |   95 ++++++++++++++++++++++
+ src/MAX_PROC_NR                |    2 +-
+ 7 files changed, 327 insertions(+), 1 deletions(-)
+ create mode 100644 daemon/md.c
+ create mode 100755 regressions/test-mdadm.sh
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index e071cc8..a19a157 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -129,6 +129,7 @@ guestfsd_SOURCES = \
+ 	luks.c \
+ 	lvm.c \
+ 	lvm-filter.c \
++	md.c \
+ 	mkfs.c \
+ 	mknod.c \
+ 	modprobe.c \
+diff --git a/daemon/md.c b/daemon/md.c
+new file mode 100644
+index 0000000..1adb4ac
+--- /dev/null
++++ b/daemon/md.c
+@@ -0,0 +1,170 @@
++/* libguestfs - the guestfsd daemon
++ * Copyright (C) 2011 Red Hat Inc.
++ *
++ * 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 will 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 to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <inttypes.h>
++#include <glob.h>
++
++#include "daemon.h"
++#include "actions.h"
++#include "optgroups.h"
++
++int
++optgroup_mdadm_available (void)
++{
++  return prog_exists ("mdadm");
++}
++
++static size_t
++count_bits (uint64_t bitmap)
++{
++  size_t c;
++
++  if (bitmap == 0)
++    return 0;
++
++  c = bitmap & 1 ? 1 : 0;
++  bitmap >>= 1;
++  return c + count_bits (bitmap);
++}
++
++/* Takes optional arguments, consult optargs_bitmask. */
++int
++do_mdadm_create (const char *name, char *const *devices,
++                 int64_t missingbitmap, int nrdevices, int spare,
++                 int64_t chunk, const char *level)
++{
++  char nrdevices_s[32];
++  char spare_s[32];
++  char chunk_s[32];
++  size_t j;
++  int r;
++  char *err;
++  uint64_t umissingbitmap = (uint64_t) missingbitmap;
++
++  /* Check the optional parameters and set defaults where appropriate. */
++  if (!(optargs_bitmask & GUESTFS_MDADM_CREATE_MISSINGBITMAP_BITMASK))
++    umissingbitmap = 0;
++
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) {
++    if (spare < 0) {
++      reply_with_error ("spare must not be negative");
++      return -1;
++    }
++  }
++  else
++    spare = 0;
++
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_NRDEVICES_BITMASK) {
++    if (nrdevices < 2) {
++      reply_with_error ("nrdevices is less than 2");
++      return -1;
++    }
++  }
++  else
++    nrdevices = count_strings (devices) + count_bits (umissingbitmap);
++
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_LEVEL_BITMASK) {
++    if (STRNEQ (level, "linear") && STRNEQ (level, "raid0") &&
++        STRNEQ (level, "0") && STRNEQ (level, "stripe") &&
++        STRNEQ (level, "raid1") && STRNEQ (level, "1") &&
++        STRNEQ (level, "mirror") &&
++        STRNEQ (level, "raid4") && STRNEQ (level, "4") &&
++        STRNEQ (level, "raid5") && STRNEQ (level, "5") &&
++        STRNEQ (level, "raid6") && STRNEQ (level, "6") &&
++        STRNEQ (level, "raid10") && STRNEQ (level, "10")) {
++      reply_with_error ("unknown level parameter: %s", level);
++      return -1;
++    }
++  }
++  else
++    level = "raid1";
++
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) {
++    /* chunk is bytes in the libguestfs API, but K when we pass it to mdadm */
++    if ((chunk & 1023) != 0) {
++      reply_with_error ("chunk size must be a multiple of 1024 bytes");
++      return -1;
++    }
++  }
++
++  /* Check invariant. */
++  if (count_strings (devices) + count_bits (umissingbitmap) !=
++      (size_t) (nrdevices + spare)) {
++    reply_with_error ("devices (%zu) + bits set in missingbitmap (%zu) is not equal to nrdevices (%d) + spare (%d)",
++                      count_strings (devices), count_bits (umissingbitmap),
++                      nrdevices, spare);
++    return -1;
++  }
++
++  size_t MAX_ARGS = nrdevices + 16;
++  const char *argv[MAX_ARGS];
++  size_t i = 0;
++
++  ADD_ARG (argv, i, "mdadm");
++  ADD_ARG (argv, i, "--create");
++  /* --run suppresses "Continue creating array" question */
++  ADD_ARG (argv, i, "--run");
++  ADD_ARG (argv, i, name);
++  ADD_ARG (argv, i, "--level");
++  ADD_ARG (argv, i, level);
++  ADD_ARG (argv, i, "--raid-devices");
++  snprintf (nrdevices_s, sizeof nrdevices_s, "%d", nrdevices);
++  ADD_ARG (argv, i, nrdevices_s);
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) {
++    ADD_ARG (argv, i, "--spare-devices");
++    snprintf (spare_s, sizeof spare_s, "%d", spare);
++    ADD_ARG (argv, i, spare_s);
++  }
++  if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) {
++    ADD_ARG (argv, i, "--chunk");
++    snprintf (chunk_s, sizeof chunk_s, "%" PRIi64, chunk / 1024);
++    ADD_ARG (argv, i, chunk_s);
++  }
++
++  /* Add devices and "missing". */
++  j = 0;
++  while (devices[j] != NULL || umissingbitmap != 0) {
++    if (umissingbitmap & 1)
++      ADD_ARG (argv, i, "missing");
++    else {
++      ADD_ARG (argv, i, devices[j]);
++      j++;
++    }
++    umissingbitmap >>= 1;
++  }
++
++  ADD_ARG (argv, i, NULL);
++
++  r = commandv (NULL, &err, argv);
++  if (r == -1) {
++    reply_with_error ("mdadm: %s: %s", name, err);
++    free (err);
++    return -1;
++  }
++
++  free (err);
++
++  udev_settle ();
++
++  return 0;
++}
+diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
+index d3fa3e0..80814f5 100644
+--- a/generator/generator_actions.ml
++++ b/generator/generator_actions.ml
+@@ -6332,6 +6332,64 @@ is for copying blocks within existing files.  See C<guestfs_cp>,
+ C<guestfs_cp_a> and C<guestfs_mv> for general file copying and
+ moving functions.");
+ 
++  ("mdadm_create", (RErr, [String "name"; DeviceList "devices"], [Int64 "missingbitmap"; Int "nrdevices"; Int "spare"; Int64 "chunk"; String "level"]), 299, [Optional "mdadm"],
++   [],
++   "create a Linux md (RAID) device",
++   "\
++Create a Linux md (RAID) device named C<name> on the devices
++in the list C<devices>.
++
++The optional parameters are:
++
++=over 4
++
++=item C<missingbitmap>
++
++A bitmap of missing devices.  If a bit is set it means that a
++missing device is added to the array.  The least significant bit
++corresponds to the first device in the array.
++
++As examples:
++
++If C<devices = [\"/dev/sda\"]> and C<missingbitmap = 0x1> then
++the resulting array would be C<[E<lt>missingE<gt>, \"/dev/sda\"]>.
++
++If C<devices = [\"/dev/sda\"]> and C<missingbitmap = 0x2> then
++the resulting array would be C<[\"/dev/sda\", E<lt>missingE<gt>]>.
++
++This defaults to C<0> (no missing devices).
++
++The length of C<devices> + the number of bits set in
++C<missingbitmap> must equal C<nrdevices> + C<spare>.
++
++=item C<nrdevices>
++
++The number of active RAID devices.
++
++If not set, this defaults to the length of C<devices> plus
++the number of bits set in C<missingbitmap>.
++
++=item C<spare>
++
++The number of spare devices.
++
++If not set, this defaults to C<0>.
++
++=item C<chunk>
++
++The chunk size in bytes.
++
++=item C<level>
++
++The RAID level, which can be one of:
++I<linear>, I<raid0>, I<0>, I<stripe>, I<raid1>, I<1>, I<mirror>,
++I<raid4>, I<4>, I<raid5>, I<5>, I<raid6>, I<6>, I<raid10>, I<10>.
++Some of these are synonymous, and more levels may be added in future.
++
++If not set, this defaults to C<raid1>.
++
++=back");
++
+ ]
+ 
+ let all_functions = non_daemon_functions @ daemon_functions
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 0ed9e45..fcc612d 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -48,6 +48,7 @@ daemon/ls.c
+ daemon/luks.c
+ daemon/lvm-filter.c
+ daemon/lvm.c
++daemon/md.c
+ daemon/mkfs.c
+ daemon/mknod.c
+ daemon/modprobe.c
+diff --git a/regressions/Makefile.am b/regressions/Makefile.am
+index 0af7e8c..5263905 100644
+--- a/regressions/Makefile.am
++++ b/regressions/Makefile.am
+@@ -49,6 +49,7 @@ TESTS = \
+ 	test-luks-list.sh \
+ 	test-lvm-filtering.sh \
+ 	test-lvm-mapping.pl \
++	test-mdadm.sh \
+ 	test-noexec-stack.pl \
+ 	test-qemudie-killsub.sh \
+ 	test-qemudie-midcommand.sh \
+diff --git a/regressions/test-mdadm.sh b/regressions/test-mdadm.sh
+new file mode 100755
+index 0000000..3ad4f22
+--- /dev/null
++++ b/regressions/test-mdadm.sh
+@@ -0,0 +1,95 @@
++#!/bin/bash -
++# libguestfs
++# Copyright (C) 2011 Red Hat Inc.
++#
++# 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 will 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 to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++# Test guestfish mdadm-create command.
++
++set -e
++
++rm -f md-test1.img md-test2.img md-test3.img md-test4.img
++
++../fish/guestfish <<EOF
++# Add four empty disks
++sparse md-test1.img 100M
++sparse md-test2.img 100M
++sparse md-test3.img 100M
++sparse md-test4.img 100M
++run
++
++# Create lots of test partitions.
++part-init /dev/sda mbr
++part-add /dev/sda p 4096 8191
++part-add /dev/sda p 8192 12287
++part-add /dev/sda p 12288 16383
++part-add /dev/sda p 16384 20479
++part-init /dev/sdb mbr
++part-add /dev/sdb p 4096 8191
++part-add /dev/sdb p 8192 12287
++part-add /dev/sdb p 12288 16383
++part-add /dev/sdb p 16384 20479
++part-init /dev/sdc mbr
++part-add /dev/sdc p 4096 8191
++part-add /dev/sdc p 8192 12287
++part-add /dev/sdc p 12288 16383
++part-add /dev/sdc p 16384 20479
++part-init /dev/sdd mbr
++part-add /dev/sdd p 4096 8191
++part-add /dev/sdd p 8192 12287
++part-add /dev/sdd p 12288 16383
++part-add /dev/sdd p 16384 20479
++
++# RAID 1.
++mdadm-create r1t1 "/dev/sda1 /dev/sdb1"
++mdadm-create r1t2 "/dev/sdc1 /dev/sdd1" chunk:65536
++
++# RAID 5.
++mdadm-create r5t1 "/dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2" \
++  missingbitmap:0x10 nrdevices:4 spare:1 level:5
++
++mdadm-create r5t2 "/dev/sda3 /dev/sdb3" missingbitmap:0x1 level:5
++
++mdadm-create r5t3 "/dev/sdc3 /dev/sdd3" \
++  missingbitmap:0x6 nrdevices:2 spare:2 level:5
++
++# Make some filesystems and put some content on the
++# new RAID devices to see if they work.
++mkfs ext2 /dev/md/r1t1
++mkfs ext2 /dev/md/r1t2
++mkfs ext2 /dev/md/r5t1
++mkfs ext2 /dev/md/r5t2
++mkfs ext2 /dev/md/r5t3
++
++mkmountpoint /r1t1
++mount /dev/md/r1t1 /r1t1
++mkmountpoint /r1t2
++mount /dev/md/r1t2 /r1t2
++mkmountpoint /r5t1
++mount /dev/md/r5t1 /r5t1
++mkmountpoint /r5t2
++mount /dev/md/r5t2 /r5t2
++mkmountpoint /r5t3
++mount /dev/md/r5t3 /r5t3
++
++touch /r1t1/foo
++mkdir /r1t2/bar
++write /r5t1/foo "hello"
++write /r5t2/bar "goodbye"
++write /r5t3/baz "testing"
++
++EOF
++
++rm -f md-test1.img md-test2.img md-test3.img md-test4.img
+diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
+index 95de1ee..03a5b41 100644
+--- a/src/MAX_PROC_NR
++++ b/src/MAX_PROC_NR
+@@ -1 +1 @@
+-297
++299
+-- 
+1.7.6
+
diff --git a/0002-New-API-list-md-devices.patch b/0002-New-API-list-md-devices.patch
new file mode 100644
index 0000000..4a145f1
--- /dev/null
+++ b/0002-New-API-list-md-devices.patch
@@ -0,0 +1,280 @@
+From ce20d5484cdaac1258e8c4328183bdb4967856d1 Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Thu, 10 Nov 2011 17:56:10 +0000
+Subject: [PATCH 02/10] New API: list-md-devices.
+
+Return a list of Linux MD devices detected in the guest.
+
+This API complements list_devices, list_partitions, list_lvs and
+list_dm_devices.
+(cherry picked from commit 00a0fab50b3803be8db5b7d9fa0869a70b0da556)
+---
+ appliance/init                      |    3 ++
+ daemon/daemon.h                     |    1 +
+ daemon/guestfsd.c                   |   24 +++++++++----
+ daemon/md.c                         |   62 +++++++++++++++++++++++++++++++++++
+ generator/generator_actions.ml      |    6 +++
+ regressions/Makefile.am             |    1 +
+ regressions/test-list-md-devices.sh |   59 +++++++++++++++++++++++++++++++++
+ src/MAX_PROC_NR                     |    2 +-
+ 8 files changed, 150 insertions(+), 8 deletions(-)
+ create mode 100755 regressions/test-list-md-devices.sh
+
+diff --git a/appliance/init b/appliance/init
+index ee80334..0f32a55 100755
+--- a/appliance/init
++++ b/appliance/init
+@@ -70,6 +70,9 @@ ifconfig lo 127.0.0.1
+ ifconfig eth0 169.254.2.10
+ route add default gw 169.254.2.2
+ 
++# Scan for MDs.
++mdadm -As --auto=yes --run
++
+ # Scan for LVM.
+ modprobe dm_mod ||:
+ 
+diff --git a/daemon/daemon.h b/daemon/daemon.h
+index 489c38d..69097c3 100644
+--- a/daemon/daemon.h
++++ b/daemon/daemon.h
+@@ -47,6 +47,7 @@ extern int xwrite (int sock, const void *buf, size_t len)
+ extern int xread (int sock, void *buf, size_t len)
+   __attribute__((__warn_unused_result__));
+ 
++extern int add_string_nodup (char ***argv, int *size, int *alloc, char *str);
+ extern int add_string (char ***argv, int *size, int *alloc, const char *str);
+ extern size_t count_strings (char *const *argv);
+ extern void sort_strings (char **argv, int len);
+diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
+index eacbc1d..38cfd1a 100644
+--- a/daemon/guestfsd.c
++++ b/daemon/guestfsd.c
+@@ -415,10 +415,9 @@ xread (int sock, void *v_buf, size_t len)
+ }
+ 
+ int
+-add_string (char ***argv, int *size, int *alloc, const char *str)
++add_string_nodup (char ***argv, int *size, int *alloc, char *str)
+ {
+   char **new_argv;
+-  char *new_str;
+ 
+   if (*size >= *alloc) {
+     *alloc += 64;
+@@ -426,25 +425,36 @@ add_string (char ***argv, int *size, int *alloc, const char *str)
+     if (new_argv == NULL) {
+       reply_with_perror ("realloc");
+       free_strings (*argv);
++      *argv = NULL;
+       return -1;
+     }
+     *argv = new_argv;
+   }
+ 
++  (*argv)[*size] = str;
++
++  (*size)++;
++  return 0;
++}
++
++int
++add_string (char ***argv, int *size, int *alloc, const char *str)
++{
++  char *new_str;
++
+   if (str) {
+     new_str = strdup (str);
+     if (new_str == NULL) {
+       reply_with_perror ("strdup");
+       free_strings (*argv);
++      *argv = NULL;
+       return -1;
+     }
+-  } else
++  } else {
+     new_str = NULL;
++  }
+ 
+-  (*argv)[*size] = new_str;
+-
+-  (*size)++;
+-  return 0;
++  return add_string_nodup (argv, size, alloc, new_str);
+ }
+ 
+ size_t
+diff --git a/daemon/md.c b/daemon/md.c
+index 1adb4ac..257bd0f 100644
+--- a/daemon/md.c
++++ b/daemon/md.c
+@@ -168,3 +168,65 @@ do_mdadm_create (const char *name, char *const *devices,
+ 
+   return 0;
+ }
++
++static int
++glob_errfunc (const char *epath, int eerrno)
++{
++  fprintf (stderr, "glob: failure reading %s: %s\n", epath, strerror (eerrno));
++  return 1;
++}
++
++char **
++do_list_md_devices (void)
++{
++  char **r = NULL;
++  int size = 0, alloc = 0;
++  glob_t mds;
++
++  memset(&mds, 0, sizeof(mds));
++
++#define PREFIX "/sys/block/md"
++#define SUFFIX "/md"
++
++  /* Look for directories under /sys/block matching md[0-9]*
++   * As an additional check, we also make sure they have a md subdirectory.
++   */
++  int err = glob (PREFIX "[0-9]*" SUFFIX, GLOB_ERR, glob_errfunc, &mds);
++  if (err == GLOB_NOSPACE) {
++    reply_with_error ("glob: returned GLOB_NOSPACE: "
++                      "rerun with LIBGUESTFS_DEBUG=1");
++    goto error;
++  } else if (err == GLOB_ABORTED) {
++    reply_with_error ("glob: returned GLOB_ABORTED: "
++                      "rerun with LIBGUESTFS_DEBUG=1");
++    goto error;
++  }
++
++  for (size_t i = 0; i < mds.gl_pathc; i++) {
++    size_t len = strlen (mds.gl_pathv[i]) - strlen (PREFIX) - strlen (SUFFIX);
++
++#define DEV "/dev/md"
++    char *dev = malloc (strlen(DEV) + len  + 1);
++    if (NULL == dev) {
++      reply_with_perror("malloc");
++      goto error;
++    }
++
++    char *n = dev;
++    n = mempcpy(n, DEV, strlen(DEV));
++    n = mempcpy(n, &mds.gl_pathv[i][strlen(PREFIX)], len);
++    *n = '\0';
++
++    if (add_string_nodup (&r, &size, &alloc, dev) == -1) goto error;
++  }
++
++  if (add_string_nodup (&r, &size, &alloc, NULL) == -1) goto error;
++  globfree (&mds);
++
++  return r;
++
++error:
++  globfree (&mds);
++  if (r != NULL) free_strings (r);
++  return NULL;
++}
+diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
+index 80814f5..9255a59 100644
+--- a/generator/generator_actions.ml
++++ b/generator/generator_actions.ml
+@@ -6390,6 +6390,12 @@ If not set, this defaults to C<raid1>.
+ 
+ =back");
+ 
++  ("list_md_devices", (RStringList "devices", [], []), 300, [],
++   [],
++   "list Linux md (RAID) devices",
++   "\
++List all Linux md devices.");
++
+ ]
+ 
+ let all_functions = non_daemon_functions @ daemon_functions
+diff --git a/regressions/Makefile.am b/regressions/Makefile.am
+index 5263905..f273464 100644
+--- a/regressions/Makefile.am
++++ b/regressions/Makefile.am
+@@ -45,6 +45,7 @@ TESTS = \
+ 	test-guestfish-tilde.sh \
+ 	test-inspect-fstab.sh \
+ 	test-launch-race.pl \
++	test-list-md-devices.sh \
+ 	test-luks.sh \
+ 	test-luks-list.sh \
+ 	test-lvm-filtering.sh \
+diff --git a/regressions/test-list-md-devices.sh b/regressions/test-list-md-devices.sh
+new file mode 100755
+index 0000000..cd12d80
+--- /dev/null
++++ b/regressions/test-list-md-devices.sh
+@@ -0,0 +1,59 @@
++#!/bin/bash -
++# libguestfs
++# Copyright (C) 2011 Red Hat Inc.
++#
++# 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 will 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 to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++# Test guestfish list-md-devices command
++
++set -e
++
++output=$(
++../fish/guestfish <<EOF
++# Add 2 empty disks
++sparse md-test1.img 100M
++sparse md-test2.img 100M
++run
++
++# list-md-devices should return nothing
++list-md-devices
++
++# Create a raid1 based on the 2 disks
++mdadm-create test "/dev/sda /dev/sdb" level:raid1
++EOF
++)
++
++# Ensure list-md-devices above returned nothing
++if [ ! -z "$output" ]; then
++    echo "$0: error: output of list-md-devices with no MD devices did not match expected output"
++    echo $output
++    exit 1;
++fi
++
++# Ensure list-md-devices now returns the newly created md device
++output=$(
++../fish/guestfish -a md-test1.img -a md-test2.img <<EOF
++run
++list-md-devices
++EOF
++)
++
++if [ "$output" != "/dev/md127" ]; then
++    echo "$0: error: output of list-md-devices did not match expected output"
++    echo "$output"
++    exit 1
++fi
++
++rm -f md-test1.img md-test2.img
+diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
+index 03a5b41..697cb3a 100644
+--- a/src/MAX_PROC_NR
++++ b/src/MAX_PROC_NR
+@@ -1 +1 @@
+-299
++300
+-- 
+1.7.6
+
diff --git a/0003-Update-list-filesystems-to-check-md-devices.patch b/0003-Update-list-filesystems-to-check-md-devices.patch
new file mode 100644
index 0000000..329e939
--- /dev/null
+++ b/0003-Update-list-filesystems-to-check-md-devices.patch
@@ -0,0 +1,204 @@
+From d8064e0d76f9a5b0efec6224edd98f3b27e0132d Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Thu, 10 Nov 2011 17:57:16 +0000
+Subject: [PATCH 03/10] Update list-filesystems to check md devices. (cherry
+ picked from commit
+ b051fffc6f4f6c095a3401f89a47fbb948a71ee1)
+
+---
+ regressions/Makefile.am              |    1 +
+ regressions/test-list-filesystems.sh |   76 ++++++++++++++++++++++++++++++++++
+ src/listfs.c                         |   51 ++++++++++++-----------
+ 3 files changed, 104 insertions(+), 24 deletions(-)
+ create mode 100755 regressions/test-list-filesystems.sh
+
+diff --git a/regressions/Makefile.am b/regressions/Makefile.am
+index f273464..c75d54a 100644
+--- a/regressions/Makefile.am
++++ b/regressions/Makefile.am
+@@ -45,6 +45,7 @@ TESTS = \
+ 	test-guestfish-tilde.sh \
+ 	test-inspect-fstab.sh \
+ 	test-launch-race.pl \
++	test-list-filesystems.sh \
+ 	test-list-md-devices.sh \
+ 	test-luks.sh \
+ 	test-luks-list.sh \
+diff --git a/regressions/test-list-filesystems.sh b/regressions/test-list-filesystems.sh
+new file mode 100755
+index 0000000..1144286
+--- /dev/null
++++ b/regressions/test-list-filesystems.sh
+@@ -0,0 +1,76 @@
++#!/bin/bash -
++# libguestfs
++# Copyright (C) 2011 Red Hat Inc.
++#
++# 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 will 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 to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++# Test guestfish list-mddevices command
++
++set -e
++
++# Create 2 disks partitioned as:
++# sda1: 20M ext3
++# sda2: 20M MD (md127)
++#
++# sdb1: 20M PV (vg0)
++# sdb2: 20M MD (md127)
++#
++# md127 : 20M ext4
++# vg0 : 16M LV (lv0)
++# lv0 : 16M vfat
++output=$(
++../fish/guestfish <<EOF
++# Add 2 empty disks
++sparse fs-test1.img 50M
++sparse fs-test2.img 50M
++run
++
++part-init /dev/sda mbr
++part-add /dev/sda p 64 41023
++part-add /dev/sda p 41024 81983
++part-init /dev/sdb mbr
++part-add /dev/sdb p 64 41023
++part-add /dev/sdb p 41024 81983
++
++# Create vg0 and lv0 on /dev/sdb1
++pvcreate /dev/sdb1
++vgcreate vg0 /dev/sdb1
++lvcreate lv0 vg0 16
++
++# Create an md device from sda2 and sdb2
++mdadm-create test "/dev/sda2 /dev/sdb2" level:raid1
++
++# Create filesystems
++mkfs ext3 /dev/sda1
++mkfs ext4 /dev/md127
++mkfs vfat /dev/vg0/lv0
++
++list-filesystems
++EOF
++)
++
++expected="/dev/vda1: ext3
++/dev/md127: ext4
++/dev/vg0/lv0: vfat"
++
++# Check the output of list-filesystems
++if [ "$output" != "$expected" ]; then
++    echo "$0: error: output of list-filesystems did not match expected output"
++    printf "%s\n" "$output"
++    exit 1;
++fi
++
++
++rm -f fs-test1.img fs-test2.img
+diff --git a/src/listfs.c b/src/listfs.c
+index 42bbaef..0aef4f9 100644
+--- a/src/listfs.c
++++ b/src/listfs.c
+@@ -45,12 +45,13 @@ char **
+ guestfs__list_filesystems (guestfs_h *g)
+ {
+   size_t i;
+-  char **ret;
+-  size_t ret_size;
++  char **ret = NULL;
++  size_t ret_size = 0;
+ 
+-  ret = safe_malloc (g, sizeof (char *));
+-  ret[0] = NULL;
+-  ret_size = 0;
++  char **devices = NULL;
++  char **partitions = NULL;
++  char **mds = NULL;
++  char **lvs = NULL;
+ 
+   /* Look to see if any devices directly contain filesystems
+    * (RHBZ#590167).  However vfs-type will fail to tell us anything
+@@ -58,19 +59,12 @@ guestfs__list_filesystems (guestfs_h *g)
+    * get the list of partitions and exclude the corresponding devices
+    * by using part-to-dev.
+    */
+-  char **devices;
+   devices = guestfs_list_devices (g);
+-  if (devices == NULL) {
+-    guestfs___free_string_list (ret);
+-    return NULL;
+-  }
+-  char **partitions;
++  if (devices == NULL) goto error;
+   partitions = guestfs_list_partitions (g);
+-  if (partitions == NULL) {
+-    guestfs___free_string_list (devices);
+-    guestfs___free_string_list (ret);
+-    return NULL;
+-  }
++  if (partitions == NULL) goto error;
++  mds = guestfs_list_md_devices (g);
++  if (mds == NULL) goto error;
+ 
+   for (i = 0; partitions[i] != NULL; ++i) {
+     char *dev = guestfs_part_to_dev (g, partitions[i]);
+@@ -82,28 +76,37 @@ guestfs__list_filesystems (guestfs_h *g)
+   /* Use vfs-type to check for filesystems on devices. */
+   for (i = 0; devices[i] != NULL; ++i)
+     check_with_vfs_type (g, devices[i], &ret, &ret_size);
+-  guestfs___free_string_list (devices);
+ 
+   /* Use vfs-type to check for filesystems on partitions. */
+   for (i = 0; partitions[i] != NULL; ++i)
+     check_with_vfs_type (g, partitions[i], &ret, &ret_size);
+-  guestfs___free_string_list (partitions);
++
++  /* Use vfs-type to check for filesystems on md devices. */
++  for (i = 0; mds[i] != NULL; ++i)
++    check_with_vfs_type (g, mds[i], &ret, &ret_size);
+ 
+   if (guestfs___feature_available (g, "lvm2")) {
+     /* Use vfs-type to check for filesystems on LVs. */
+-    char **lvs;
+     lvs = guestfs_lvs (g);
+-    if (lvs == NULL) {
+-      guestfs___free_string_list (ret);
+-      return NULL;
+-    }
++    if (lvs == NULL) goto error;
+ 
+     for (i = 0; lvs[i] != NULL; ++i)
+       check_with_vfs_type (g, lvs[i], &ret, &ret_size);
+-    guestfs___free_string_list (lvs);
+   }
+ 
++  guestfs___free_string_list (devices);
++  guestfs___free_string_list (partitions);
++  guestfs___free_string_list (mds);
++  if (lvs) guestfs___free_string_list (lvs);
+   return ret;
++
++ error:
++  if (devices) guestfs___free_string_list (devices);
++  if (partitions) guestfs___free_string_list (partitions);
++  if (mds) guestfs___free_string_list (mds);
++  if (lvs) guestfs___free_string_list (lvs);
++  if (ret) guestfs___free_string_list (ret);
++  return NULL;
+ }
+ 
+ /* If 'item' occurs in 'list', remove and free it. */
+-- 
+1.7.6
+
diff --git a/0004-New-API-mdadm-detail.patch b/0004-New-API-mdadm-detail.patch
new file mode 100644
index 0000000..e0fc468
--- /dev/null
+++ b/0004-New-API-mdadm-detail.patch
@@ -0,0 +1,228 @@
+From 123fdc57993380c8b3fc00a0f229bef6d721819c Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Thu, 17 Nov 2011 12:43:49 +0000
+Subject: [PATCH 04/10] New API: mdadm-detail. (cherry picked from commit
+ c4bd6bba8d88ecf1ebf4a9c2c80a407d9971aaf7)
+
+---
+ daemon/md.c                    |   80 ++++++++++++++++++++++++++++++++++++++++
+ generator/generator_actions.ml |   31 +++++++++++++++
+ regressions/test-mdadm.sh      |   60 +++++++++++++++++++++++++++++-
+ src/MAX_PROC_NR                |    2 +-
+ 4 files changed, 171 insertions(+), 2 deletions(-)
+
+diff --git a/daemon/md.c b/daemon/md.c
+index 257bd0f..82ddb82 100644
+--- a/daemon/md.c
++++ b/daemon/md.c
+@@ -27,6 +27,7 @@
+ #include "daemon.h"
+ #include "actions.h"
+ #include "optgroups.h"
++#include "c-ctype.h"
+ 
+ int
+ optgroup_mdadm_available (void)
+@@ -230,3 +231,82 @@ error:
+   if (r != NULL) free_strings (r);
+   return NULL;
+ }
++
++char **
++do_mdadm_detail(const char *md)
++{
++  int r;
++
++  char *out = NULL, *err = NULL;
++  char **lines = NULL;
++
++  char **ret = NULL;
++  int size = 0, alloc = 0;
++
++  const char *mdadm[] = { "mdadm", "-DY", md, NULL };
++  r = commandv(&out, &err, mdadm);
++  if (r == -1) {
++    reply_with_error("%s", err);
++    goto error;
++  }
++
++  /* Split the command output into lines */
++  lines = split_lines(out);
++  if (lines == NULL) {
++    reply_with_perror("malloc");
++    goto error;
++  }
++
++  /* Parse the output of mdadm -DY:
++   * MD_LEVEL=raid1
++   * MD_DEVICES=2
++   * MD_METADATA=1.0
++   * MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1
++   * MD_NAME=localhost.localdomain:0
++   */
++  for (char **i = lines; *i != NULL; i++) {
++    char *line = *i;
++
++    /* Skip blank lines (shouldn't happen) */
++    if (line[0] == '\0') continue;
++
++    /* Split the line in 2 at the equals sign */
++    char *eq = strchr(line, '=');
++    if (eq) {
++      *eq = '\0'; eq++;
++
++      /* Remove the MD_ prefix from the key and translate the remainder to lower
++       * case */
++      if (STRPREFIX(line, "MD_")) {
++        line += 3;
++        for (char *j = line; *j != '\0'; j++) {
++          *j = c_tolower(*j);
++        }
++      }
++
++      /* Add the key/value pair to the output */
++      if (add_string(&ret, &size, &alloc, line) == -1 ||
++          add_string(&ret, &size, &alloc, eq) == -1) goto error;
++    } else {
++      /* Ignore lines with no equals sign (shouldn't happen). Log to stderr so
++       * it will show up in LIBGUESTFS_DEBUG. */
++      fprintf(stderr, "mdadm-detail: unexpected output ignored: %s", line);
++    }
++  }
++
++  free(out);
++  free(err);
++  free(lines); /* We freed the contained strings when we freed out */
++
++  if (add_string(&ret, &size, &alloc, NULL) == -1) return NULL;
++
++  return ret;
++
++error:
++  free(out);
++  free(err);
++  if (lines) free(lines);
++  if (ret) free_strings(ret);
++
++  return NULL;
++}
+diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
+index 9255a59..0d17044 100644
+--- a/generator/generator_actions.ml
++++ b/generator/generator_actions.ml
+@@ -6396,6 +6396,37 @@ If not set, this defaults to C<raid1>.
+    "\
+ List all Linux md devices.");
+ 
++  ("mdadm_detail", (RHashtable "info", [Device "md"], []), 301,  [Optional "mdadm"],
++   [],
++   "obtain metadata for an MD device",
++   "\
++This command exposes the output of 'mdadm -DY <md>'. The following fields are
++usually present in the returned hash. Other fields may also be present.
++
++=over
++
++=item C<level>
++
++The raid level of the MD device.
++
++=item C<devices>
++
++The number of underlying devices in the MD device.
++
++=item C<metadata>
++
++The metadata version used.
++
++=item C<uuid>
++
++The UUID of the MD device.
++
++=item C<name>
++
++The name of the MD device.
++
++=back");
++
+ ]
+ 
+ let all_functions = non_daemon_functions @ daemon_functions
+diff --git a/regressions/test-mdadm.sh b/regressions/test-mdadm.sh
+index 3ad4f22..8119561 100755
+--- a/regressions/test-mdadm.sh
++++ b/regressions/test-mdadm.sh
+@@ -92,4 +92,62 @@ write /r5t3/baz "testing"
+ 
+ EOF
+ 
+-rm -f md-test1.img md-test2.img md-test3.img md-test4.img
++eval `../fish/guestfish --listen`
++../fish/guestfish --remote add-ro md-test1.img
++../fish/guestfish --remote add-ro md-test2.img
++../fish/guestfish --remote add-ro md-test3.img
++../fish/guestfish --remote add-ro md-test4.img
++../fish/guestfish --remote run
++
++for md in `../fish/guestfish --remote list-md-devices`; do
++  ../fish/guestfish --remote mdadm-detail "${md}" > mdadm-detail.out
++
++  sed 's/:\s*/=/' mdadm-detail.out > mdadm-detail.out.sh
++  . mdadm-detail.out.sh
++  rm -f mdadm-detail.out.sh
++
++  error=0
++  case "$name" in
++    *:r1t1)
++      [ "$level" == "raid1" ] || error=1
++      [ "$devices" == "2" ] || error=1
++      ;;
++
++    *:r1t2)
++      [ "$level" == "raid1" ] || error=1
++      [ "$devices" == "2" ] || error=1
++      ;;
++
++    *:r5t1)
++      [ "$level" == "raid5" ] || error=1
++      [ "$devices" == "4" ] || error=1
++      ;;
++
++    *:r5t2)
++      [ "$level" == "raid5" ] || error=1
++      [ "$devices" == "3" ] || error=1
++      ;;
++
++    *:r5t3)
++      [ "$level" == "raid5" ] || error=1
++      [ "$devices" == "2" ] || error=1
++      ;;
++
++    *)
++      error=1
++  esac
++
++  [[ "$uuid" =~ ([0-9a-f]{8}:){3}[0-9a-f]{8} ]] || error=1
++  [ ! -z "$metadata" ] || error=1
++
++  if [ "$error" == "1" ]; then
++    echo "$0: Unexpected output from mdadm-detail for device $md"
++    cat mdadm-detail.out
++    ../fish/guestfish --remote exit
++    exit 1
++  fi
++done
++
++../fish/guestfish --remote exit
++
++rm -f mdadm-detail.out md-test1.img md-test2.img md-test3.img md-test4.img
+diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
+index 697cb3a..d8fc48a 100644
+--- a/src/MAX_PROC_NR
++++ b/src/MAX_PROC_NR
+@@ -1 +1 @@
+-300
++301
+-- 
+1.7.6
+
diff --git a/0005-fish-Add-MD-devices-to-guestfish-device-autocompleti.patch b/0005-fish-Add-MD-devices-to-guestfish-device-autocompleti.patch
new file mode 100644
index 0000000..10f159a
--- /dev/null
+++ b/0005-fish-Add-MD-devices-to-guestfish-device-autocompleti.patch
@@ -0,0 +1,28 @@
+From 84e6bab28792b44b9b42dad056b426c72c7c8fc1 Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Mon, 21 Nov 2011 15:23:18 +0000
+Subject: [PATCH 05/10] fish: Add MD devices to guestfish device
+ autocompletion. (cherry picked from commit
+ 0cdd9444744e7ae0d82fe4c94d13e9ddd00e8e2d)
+
+---
+ fish/destpaths.c |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/fish/destpaths.c b/fish/destpaths.c
+index c7b9dc5..f3cf0f2 100644
+--- a/fish/destpaths.c
++++ b/fish/destpaths.c
+@@ -158,6 +158,9 @@ complete_dest_paths_generator (const char *text, int state)
+ 
+       strs = guestfs_list_dm_devices (g);
+       APPEND_STRS_AND_FREE;
++
++      strs = guestfs_list_md_devices (g);
++      APPEND_STRS_AND_FREE;
+     }
+ 
+     if (len < 1 || text[0] == '/') {
+-- 
+1.7.6
+
diff --git a/0006-build-Create-an-MD-variant-of-the-dummy-Fedora-image.patch b/0006-build-Create-an-MD-variant-of-the-dummy-Fedora-image.patch
new file mode 100644
index 0000000..028eb43
--- /dev/null
+++ b/0006-build-Create-an-MD-variant-of-the-dummy-Fedora-image.patch
@@ -0,0 +1,398 @@
+From 328134c4597012b160b8e1a63602bbf01e477411 Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Wed, 23 Nov 2011 14:00:50 +0000
+Subject: [PATCH 06/10] build: Create an MD variant of the dummy Fedora image
+
+This change involves rewriting make-fedora-img.sh in perl. This allows the
+flexibility to write mdadm.conf containing whichever uuids where randomly
+generated when the md devices were created.
+(cherry picked from commit d3458d7bc46d4fa68acd759cf5dc308f76531fe4)
+---
+ .gitignore                          |    2 +
+ images/Makefile.am                  |   18 +++-
+ images/guest-aux/make-fedora-img.pl |  195 +++++++++++++++++++++++++++++++++++
+ images/guest-aux/make-fedora-img.sh |  110 --------------------
+ 4 files changed, 211 insertions(+), 114 deletions(-)
+ create mode 100755 images/guest-aux/make-fedora-img.pl
+ delete mode 100755 images/guest-aux/make-fedora-img.sh
+
+diff --git a/.gitignore b/.gitignore
+index ead7cbf..60ec817 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -171,6 +171,8 @@ images/10klines
+ images/abssymlink
+ images/debian.img
+ images/fedora.img
++images/fedora-md1.img
++images/fedora-md2.img
+ images/guest-aux/fedora-name.db
+ images/guest-aux/fedora-packages.db
+ images/hello.b64
+diff --git a/images/Makefile.am b/images/Makefile.am
+index 1cae8bf..e413750 100644
+--- a/images/Makefile.am
++++ b/images/Makefile.am
+@@ -39,7 +39,7 @@ EXTRA_DIST = \
+ 	test-grep.txt \
+ 	guest-aux/make-debian-img.sh \
+ 	guest-aux/debian-packages \
+-	guest-aux/make-fedora-img.sh \
++	guest-aux/make-fedora-img.pl \
+ 	guest-aux/fedora-name.db.txt \
+ 	guest-aux/fedora-name.db \
+ 	guest-aux/fedora-packages.db.txt \
+@@ -56,7 +56,7 @@ noinst_DATA = test.iso
+ 
+ # This is 'check_DATA' because we don't need it until 'make check'
+ # time and we need the tools we have built in order to make it.
+-check_DATA = debian.img fedora.img ubuntu.img windows.img
++check_DATA = debian.img fedora.img fedora-md1.img fedora-md2.img ubuntu.img windows.img
+ 
+ CLEANFILES = \
+ 	test.iso test.sqsh \
+@@ -170,12 +170,22 @@ $(builddir)/test-grep.txt.gz: test-grep.txt
+ 	mv $@-t $@
+ 
+ # Make a (dummy) Fedora image.
+-fedora.img: guest-aux/make-fedora-img.sh \
++fedora.img: guest-aux/make-fedora-img.pl \
+ 		guest-aux/fedora-name.db \
+ 		guest-aux/fedora-packages.db
+ 	TMPDIR=$(top_builddir) \
+ 	SRCDIR=$(srcdir) \
+-	bash $<
++	LAYOUT=partitions \
++	../run $<
++
++# Make a (dummy) Fedora image using md devices
++fedora-md1.img fedora-md2.img: guest-aux/make-fedora-img.pl \
++		guest-aux/fedora-name.db \
++		guest-aux/fedora-packages.db
++	TMPDIR=$(top_builddir) \
++	SRCDIR=$(srcdir) \
++	LAYOUT=partitions-md \
++	../run $<
+ 
+ guest-aux/fedora-name.db: guest-aux/fedora-name.db.txt
+ 	rm -f $@ $@-t
+diff --git a/images/guest-aux/make-fedora-img.pl b/images/guest-aux/make-fedora-img.pl
+new file mode 100755
+index 0000000..60d0aa2
+--- /dev/null
++++ b/images/guest-aux/make-fedora-img.pl
+@@ -0,0 +1,195 @@
++#!/usr/bin/perl
++# libguestfs
++# Copyright (C) 2010-2011 Red Hat Inc.
++#
++# 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 will 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 to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++# Make a standard test image which is used by all the tools test
++# scripts.  This test image is supposed to look like a Fedora
++# installation, or at least enough of one to fool the inspection API
++# heuristics.
++
++use strict;
++use warnings;
++
++use Sys::Guestfs;
++use File::Temp;
++
++my @images;
++my $g = Sys::Guestfs->new();
++
++my $bootdev;
++my $rootdev;
++
++foreach ('LAYOUT', 'SRCDIR') {
++  defined($ENV{$_}) or die "Missing environment variable: $_";
++}
++
++if ($ENV{LAYOUT} eq 'partitions') {
++  push (@images, 'fedora.img.tmp');
++
++  open(my $fstab, '>', 'fstab.tmp') or die;
++  print $fstab <<EOF;
++LABEL=BOOT /boot ext2 default 0 0
++LABEL=ROOT / ext2 default 0 0
++EOF
++  close($fstab) or die;
++
++  $bootdev = '/dev/sda1';
++  $rootdev = '/dev/sda2';
++
++  open(my $img, '>', 'fedora.img.tmp') or die;
++  truncate($img, 512*1024*1024) or die;
++  close($img) or die;
++
++  $g->add_drive('fedora.img.tmp');
++  $g->launch();
++
++  $g->part_init('/dev/sda', 'mbr');
++  $g->part_add('/dev/sda', 'p', 64, 524287);
++  $g->part_add('/dev/sda', 'p', 524288, -64);
++}
++
++elsif ($ENV{LAYOUT} eq 'partitions-md') {
++  push(@images, 'fedora-md1.img.tmp', 'fedora-md2.img.tmp');
++
++  open(my $fstab, '>', 'fstab.tmp') or die;
++  print $fstab <<EOF;
++/dev/md0 /boot ext2 default 0 0
++LABEL=ROOT / ext2 default 0 0
++EOF
++  close($fstab) or die;
++
++  $bootdev = '/dev/md/boot';
++  $rootdev = '/dev/md/root';
++
++  foreach my $img (@images) {
++    open(my $fh, '>', $img) or die;
++    truncate($fh, 512*1024*1024) or die;
++    close($fh) or die;
++
++    $g->add_drive($img);
++  }
++
++  $g->launch();
++
++  # Format the disks.
++  foreach ('a', 'b') {
++    $g->part_init("/dev/sd$_", 'mbr');
++    $g->part_add("/dev/sd$_", 'p', 64, 524287);
++    $g->part_add("/dev/sd$_", 'p', 524288, -64);
++  }
++
++  $g->mdadm_create('boot', ['/dev/sda1', '/dev/sdb1']);
++  $g->mdadm_create('root', ['/dev/sda2', '/dev/sdb2']);
++
++  open(my $mdadm, '>', 'mdadm.tmp') or die;
++  print $mdadm <<EOF;
++MAILADDR root
++AUTO +imsm +1.x -all
++EOF
++
++  my $i = 0;
++  foreach ('boot', 'root') {
++    my %detail = $g->mdadm_detail("/dev/md/$_");
++    print $mdadm "ARRAY /dev/md$i level=raid1 num-devices=2 UUID=",
++                 $detail{uuid}, "\n";
++    $i++;
++  }
++
++  close($mdadm) or die;
++}
++
++else {
++  print STDERR "$0: Unknown LAYOUT: ",$ENV{LAYOUT},"\n";
++  exit 1;
++}
++
++$g->pvcreate($rootdev);
++$g->vgcreate('VG', [$rootdev]);
++$g->lvcreate('Root', 'VG', 32);
++$g->lvcreate('LV1', 'VG', 32);
++$g->lvcreate('LV2', 'VG', 32);
++$g->lvcreate('LV3', 'VG', 64);
++
++# Phony /boot filesystem
++$g->mkfs_opts('ext2', $bootdev, blocksize => 4096);
++$g->set_e2label($bootdev, 'BOOT');
++$g->set_e2uuid($bootdev, '01234567-0123-0123-0123-012345678901');
++
++# Phony root filesystem.
++$g->mkfs_opts('ext2', '/dev/VG/Root', blocksize => 4096);
++$g->set_e2label('/dev/VG/Root', 'ROOT');
++$g->set_e2uuid('/dev/VG/Root', '01234567-0123-0123-0123-012345678902');
++
++# Enough to fool inspection API.
++$g->mount_options('', '/dev/VG/Root', '/');
++$g->mkdir('/boot');
++$g->mount_options('', $bootdev, '/boot');
++$g->mkdir('/bin');
++$g->mkdir('/etc');
++$g->mkdir('/etc/sysconfig');
++$g->mkdir('/usr');
++$g->mkdir_p('/var/lib/rpm');
++
++$g->upload('fstab.tmp', '/etc/fstab');
++$g->write('/etc/redhat-release', 'Fedora release 14 (Phony)');
++$g->write('/etc/fedora-release', 'Fedora release 14 (Phony)');
++$g->write('/etc/sysconfig/network', 'HOSTNAME=fedora.invalid');
++
++if (-f 'mdadm.tmp') {
++  $g->upload('mdadm.tmp', '/etc/mdadm.conf');
++  unlink('mdadm.tmp') or die;
++}
++
++$g->upload('guest-aux/fedora-name.db', '/var/lib/rpm/Name');
++$g->upload('guest-aux/fedora-packages.db', '/var/lib/rpm/Packages');
++
++$g->upload($ENV{SRCDIR}.'/bin-x86_64-dynamic', '/bin/ls');
++
++$g->mkdir('/boot/grub');
++$g->touch('/boot/grub/grub.conf');
++
++# Test files.
++$g->write('/etc/test1', 'abcdefg');
++$g->write('/etc/test2', '');
++$g->write('/etc/test3',
++'a
++b
++c
++d
++e
++f
++');
++$g->write('/bin/test1', 'abcdefg');
++$g->write('/bin/test2', 'zxcvbnm');
++$g->write('/bin/test3', '1234567');
++$g->write('/bin/test4', '');
++$g->ln_s('/bin/test1', '/bin/test5');
++$g->mkfifo(0777, '/bin/test6');
++$g->mknod(0777, 10, 10, '/bin/test7');
++
++# Other filesystems.
++# Note that these should be empty, for testing virt-df.
++$g->mkfs_opts('ext2', '/dev/VG/LV1', blocksize => 4096);
++$g->mkfs_opts('ext2', '/dev/VG/LV2', blocksize => 1024);
++$g->mkfs_opts('ext2', '/dev/VG/LV3', blocksize => 2048);
++
++# Cleanup
++unlink('fstab.tmp') or die;
++foreach my $img (@images) {
++  $img =~ /^(.*)\.tmp$/ or die;
++  rename($img, $1) or die;
++}
+diff --git a/images/guest-aux/make-fedora-img.sh b/images/guest-aux/make-fedora-img.sh
+deleted file mode 100755
+index b4c07e9..0000000
+--- a/images/guest-aux/make-fedora-img.sh
++++ /dev/null
+@@ -1,110 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# Copyright (C) 2010-2011 Red Hat Inc.
+-#
+-# 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 will 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 to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-# Make a standard test image which is used by all the tools test
+-# scripts.  This test image is supposed to look like a Fedora
+-# installation, or at least enough of one to fool the inspection API
+-# heuristics.
+-
+-export LANG=C
+-set -e
+-
+-# fstab file.
+-cat > fstab.tmp <<EOF
+-LABEL=BOOT /boot ext2 default 0 0
+-LABEL=ROOT / ext2 default 0 0
+-EOF
+-
+-# Create a disk image.
+-../run ../fish/guestfish <<EOF
+-sparse fedora.img.tmp 512M
+-run
+-
+-# Format the disk.
+-part-init /dev/sda mbr
+-part-add /dev/sda p 64     524287
+-part-add /dev/sda p 524288    -64
+-
+-pvcreate /dev/sda2
+-vgcreate VG /dev/sda2
+-lvcreate Root VG 32
+-lvcreate LV1 VG 32
+-lvcreate LV2 VG 32
+-lvcreate LV3 VG 64
+-
+-# Phony /boot filesystem.
+-mkfs-opts ext2 /dev/sda1 blocksize:4096
+-set-e2label /dev/sda1 BOOT
+-set-e2uuid /dev/sda1 01234567-0123-0123-0123-012345678901
+-
+-# Phony root filesystem.
+-mkfs-opts ext2 /dev/VG/Root blocksize:4096
+-set-e2label /dev/VG/Root ROOT
+-set-e2uuid /dev/VG/Root 01234567-0123-0123-0123-012345678902
+-
+-# Enough to fool inspection API.
+-mount-options "" /dev/VG/Root /
+-mkdir /boot
+-mount-options "" /dev/sda1 /boot
+-mkdir /bin
+-mkdir /etc
+-mkdir /etc/sysconfig
+-mkdir /usr
+-mkdir-p /var/lib/rpm
+-
+-upload fstab.tmp /etc/fstab
+-write /etc/redhat-release "Fedora release 14 (Phony)"
+-write /etc/fedora-release "Fedora release 14 (Phony)"
+-write /etc/sysconfig/network "HOSTNAME=fedora.invalid"
+-
+-upload guest-aux/fedora-name.db /var/lib/rpm/Name
+-upload guest-aux/fedora-packages.db /var/lib/rpm/Packages
+-
+-upload ${SRCDIR}/bin-x86_64-dynamic /bin/ls
+-
+-mkdir /boot/grub
+-touch /boot/grub/grub.conf
+-
+-# Test files.
+-write /etc/test1 "abcdefg"
+-write /etc/test2 ""
+-upload -<<__end /etc/test3
+-a
+-b
+-c
+-d
+-e
+-f
+-__end
+-write /bin/test1 "abcdefg"
+-write /bin/test2 "zxcvbnm"
+-write /bin/test3 "1234567"
+-write /bin/test4 ""
+-ln-s /bin/test1 /bin/test5
+-mkfifo 0777 /bin/test6
+-mknod 0777 10 10 /bin/test7
+-
+-# Other filesystems.
+-# Note that these should be empty, for testing virt-df.
+-mkfs-opts ext2 /dev/VG/LV1 blocksize:4096
+-mkfs-opts ext2 /dev/VG/LV2 blocksize:1024
+-mkfs-opts ext2 /dev/VG/LV3 blocksize:2048
+-EOF
+-
+-rm fstab.tmp
+-mv fedora.img.tmp fedora.img
+-- 
+1.7.6
+
diff --git a/0007-md-Inspect-MD-devices.patch b/0007-md-Inspect-MD-devices.patch
new file mode 100644
index 0000000..0388ea1
--- /dev/null
+++ b/0007-md-Inspect-MD-devices.patch
@@ -0,0 +1,40 @@
+From aad06c7955a6f8b8c49fd52b50ca88b702c01f36 Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Wed, 23 Nov 2011 14:00:53 +0000
+Subject: [PATCH 07/10] md: Inspect MD devices (cherry picked from commit
+ 454a08380d9de78448927ab77480f833342d214c)
+
+---
+ src/inspect.c |   16 ++++++++++++++++
+ 1 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/src/inspect.c b/src/inspect.c
+index e49cb1f..f9b8298 100644
+--- a/src/inspect.c
++++ b/src/inspect.c
+@@ -91,6 +91,22 @@ guestfs__inspect_os (guestfs_h *g)
+   }
+   guestfs___free_string_list (partitions);
+ 
++  /* Look at MD devices. */
++  char **mds = guestfs_list_md_devices (g);
++  if (mds == NULL) {
++    guestfs___free_inspect_info (g);
++    return NULL;
++  }
++
++  for (i = 0; mds[i] != NULL; ++i) {
++    if (guestfs___check_for_filesystem_on (g, mds[i], 0, i+1) == -1) {
++      guestfs___free_string_list (mds);
++      guestfs___free_inspect_info (g);
++      return NULL;
++    }
++  }
++  guestfs___free_string_list (mds);
++
+   /* Look at all LVs. */
+   if (guestfs___feature_available (g, "lvm2")) {
+     char **lvs;
+-- 
+1.7.6
+
diff --git a/0008-Rename-mdadm_-apis-to-md_.patch b/0008-Rename-mdadm_-apis-to-md_.patch
new file mode 100644
index 0000000..87cc52b
--- /dev/null
+++ b/0008-Rename-mdadm_-apis-to-md_.patch
@@ -0,0 +1,254 @@
+From 564a659873c51b8bb0eb59415882a536a3526c8a Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Thu, 24 Nov 2011 12:09:03 +0000
+Subject: [PATCH 08/10] Rename mdadm_ apis to md_
+
+This change renames the following 2 apis:
+* mdadm_create -> md_create
+* mdadm_detail -> md_detail
+
+This is more consistent with list_md_devices, and removes a reference to an
+implementation detail from the api.
+(cherry picked from commit 182c25b2a42e9a8f76beba440da328e37f18c9b9)
+---
+ daemon/md.c                          |   24 ++++++++++++------------
+ generator/generator_actions.ml       |    4 ++--
+ images/guest-aux/make-fedora-img.pl  |    6 +++---
+ regressions/test-list-filesystems.sh |    2 +-
+ regressions/test-list-md-devices.sh  |    2 +-
+ regressions/test-mdadm.sh            |   26 +++++++++++++-------------
+ 6 files changed, 32 insertions(+), 32 deletions(-)
+
+diff --git a/daemon/md.c b/daemon/md.c
+index 82ddb82..8e4ff88 100644
+--- a/daemon/md.c
++++ b/daemon/md.c
+@@ -50,9 +50,9 @@ count_bits (uint64_t bitmap)
+ 
+ /* Takes optional arguments, consult optargs_bitmask. */
+ int
+-do_mdadm_create (const char *name, char *const *devices,
+-                 int64_t missingbitmap, int nrdevices, int spare,
+-                 int64_t chunk, const char *level)
++do_md_create (const char *name, char *const *devices,
++              int64_t missingbitmap, int nrdevices, int spare,
++              int64_t chunk, const char *level)
+ {
+   char nrdevices_s[32];
+   char spare_s[32];
+@@ -63,10 +63,10 @@ do_mdadm_create (const char *name, char *const *devices,
+   uint64_t umissingbitmap = (uint64_t) missingbitmap;
+ 
+   /* Check the optional parameters and set defaults where appropriate. */
+-  if (!(optargs_bitmask & GUESTFS_MDADM_CREATE_MISSINGBITMAP_BITMASK))
++  if (!(optargs_bitmask & GUESTFS_MD_CREATE_MISSINGBITMAP_BITMASK))
+     umissingbitmap = 0;
+ 
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
+     if (spare < 0) {
+       reply_with_error ("spare must not be negative");
+       return -1;
+@@ -75,7 +75,7 @@ do_mdadm_create (const char *name, char *const *devices,
+   else
+     spare = 0;
+ 
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_NRDEVICES_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_NRDEVICES_BITMASK) {
+     if (nrdevices < 2) {
+       reply_with_error ("nrdevices is less than 2");
+       return -1;
+@@ -84,7 +84,7 @@ do_mdadm_create (const char *name, char *const *devices,
+   else
+     nrdevices = count_strings (devices) + count_bits (umissingbitmap);
+ 
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_LEVEL_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_LEVEL_BITMASK) {
+     if (STRNEQ (level, "linear") && STRNEQ (level, "raid0") &&
+         STRNEQ (level, "0") && STRNEQ (level, "stripe") &&
+         STRNEQ (level, "raid1") && STRNEQ (level, "1") &&
+@@ -100,7 +100,7 @@ do_mdadm_create (const char *name, char *const *devices,
+   else
+     level = "raid1";
+ 
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
+     /* chunk is bytes in the libguestfs API, but K when we pass it to mdadm */
+     if ((chunk & 1023) != 0) {
+       reply_with_error ("chunk size must be a multiple of 1024 bytes");
+@@ -131,12 +131,12 @@ do_mdadm_create (const char *name, char *const *devices,
+   ADD_ARG (argv, i, "--raid-devices");
+   snprintf (nrdevices_s, sizeof nrdevices_s, "%d", nrdevices);
+   ADD_ARG (argv, i, nrdevices_s);
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
+     ADD_ARG (argv, i, "--spare-devices");
+     snprintf (spare_s, sizeof spare_s, "%d", spare);
+     ADD_ARG (argv, i, spare_s);
+   }
+-  if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) {
++  if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
+     ADD_ARG (argv, i, "--chunk");
+     snprintf (chunk_s, sizeof chunk_s, "%" PRIi64, chunk / 1024);
+     ADD_ARG (argv, i, chunk_s);
+@@ -233,7 +233,7 @@ error:
+ }
+ 
+ char **
+-do_mdadm_detail(const char *md)
++do_md_detail(const char *md)
+ {
+   int r;
+ 
+@@ -290,7 +290,7 @@ do_mdadm_detail(const char *md)
+     } else {
+       /* Ignore lines with no equals sign (shouldn't happen). Log to stderr so
+        * it will show up in LIBGUESTFS_DEBUG. */
+-      fprintf(stderr, "mdadm-detail: unexpected output ignored: %s", line);
++      fprintf(stderr, "md-detail: unexpected mdadm output ignored: %s", line);
+     }
+   }
+ 
+diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
+index 0d17044..849db60 100644
+--- a/generator/generator_actions.ml
++++ b/generator/generator_actions.ml
+@@ -6332,7 +6332,7 @@ is for copying blocks within existing files.  See C<guestfs_cp>,
+ C<guestfs_cp_a> and C<guestfs_mv> for general file copying and
+ moving functions.");
+ 
+-  ("mdadm_create", (RErr, [String "name"; DeviceList "devices"], [Int64 "missingbitmap"; Int "nrdevices"; Int "spare"; Int64 "chunk"; String "level"]), 299, [Optional "mdadm"],
++  ("md_create", (RErr, [String "name"; DeviceList "devices"], [Int64 "missingbitmap"; Int "nrdevices"; Int "spare"; Int64 "chunk"; String "level"]), 299, [Optional "mdadm"],
+    [],
+    "create a Linux md (RAID) device",
+    "\
+@@ -6396,7 +6396,7 @@ If not set, this defaults to C<raid1>.
+    "\
+ List all Linux md devices.");
+ 
+-  ("mdadm_detail", (RHashtable "info", [Device "md"], []), 301,  [Optional "mdadm"],
++  ("md_detail", (RHashtable "info", [Device "md"], []), 301,  [Optional "mdadm"],
+    [],
+    "obtain metadata for an MD device",
+    "\
+diff --git a/images/guest-aux/make-fedora-img.pl b/images/guest-aux/make-fedora-img.pl
+index 60d0aa2..de72086 100755
+--- a/images/guest-aux/make-fedora-img.pl
++++ b/images/guest-aux/make-fedora-img.pl
+@@ -92,8 +92,8 @@ EOF
+     $g->part_add("/dev/sd$_", 'p', 524288, -64);
+   }
+ 
+-  $g->mdadm_create('boot', ['/dev/sda1', '/dev/sdb1']);
+-  $g->mdadm_create('root', ['/dev/sda2', '/dev/sdb2']);
++  $g->md_create('boot', ['/dev/sda1', '/dev/sdb1']);
++  $g->md_create('root', ['/dev/sda2', '/dev/sdb2']);
+ 
+   open(my $mdadm, '>', 'mdadm.tmp') or die;
+   print $mdadm <<EOF;
+@@ -103,7 +103,7 @@ EOF
+ 
+   my $i = 0;
+   foreach ('boot', 'root') {
+-    my %detail = $g->mdadm_detail("/dev/md/$_");
++    my %detail = $g->md_detail("/dev/md/$_");
+     print $mdadm "ARRAY /dev/md$i level=raid1 num-devices=2 UUID=",
+                  $detail{uuid}, "\n";
+     $i++;
+diff --git a/regressions/test-list-filesystems.sh b/regressions/test-list-filesystems.sh
+index 1144286..353cdd0 100755
+--- a/regressions/test-list-filesystems.sh
++++ b/regressions/test-list-filesystems.sh
+@@ -50,7 +50,7 @@ vgcreate vg0 /dev/sdb1
+ lvcreate lv0 vg0 16
+ 
+ # Create an md device from sda2 and sdb2
+-mdadm-create test "/dev/sda2 /dev/sdb2" level:raid1
++md-create test "/dev/sda2 /dev/sdb2" level:raid1
+ 
+ # Create filesystems
+ mkfs ext3 /dev/sda1
+diff --git a/regressions/test-list-md-devices.sh b/regressions/test-list-md-devices.sh
+index cd12d80..0216ca9 100755
+--- a/regressions/test-list-md-devices.sh
++++ b/regressions/test-list-md-devices.sh
+@@ -31,7 +31,7 @@ run
+ list-md-devices
+ 
+ # Create a raid1 based on the 2 disks
+-mdadm-create test "/dev/sda /dev/sdb" level:raid1
++md-create test "/dev/sda /dev/sdb" level:raid1
+ EOF
+ )
+ 
+diff --git a/regressions/test-mdadm.sh b/regressions/test-mdadm.sh
+index 8119561..e9b0db5 100755
+--- a/regressions/test-mdadm.sh
++++ b/regressions/test-mdadm.sh
+@@ -16,7 +16,7 @@
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ 
+-# Test guestfish mdadm-create command.
++# Test guestfish md-create and md-detail commands.
+ 
+ set -e
+ 
+@@ -53,16 +53,16 @@ part-add /dev/sdd p 12288 16383
+ part-add /dev/sdd p 16384 20479
+ 
+ # RAID 1.
+-mdadm-create r1t1 "/dev/sda1 /dev/sdb1"
+-mdadm-create r1t2 "/dev/sdc1 /dev/sdd1" chunk:65536
++md-create r1t1 "/dev/sda1 /dev/sdb1"
++md-create r1t2 "/dev/sdc1 /dev/sdd1" chunk:65536
+ 
+ # RAID 5.
+-mdadm-create r5t1 "/dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2" \
++md-create r5t1 "/dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2" \
+   missingbitmap:0x10 nrdevices:4 spare:1 level:5
+ 
+-mdadm-create r5t2 "/dev/sda3 /dev/sdb3" missingbitmap:0x1 level:5
++md-create r5t2 "/dev/sda3 /dev/sdb3" missingbitmap:0x1 level:5
+ 
+-mdadm-create r5t3 "/dev/sdc3 /dev/sdd3" \
++md-create r5t3 "/dev/sdc3 /dev/sdd3" \
+   missingbitmap:0x6 nrdevices:2 spare:2 level:5
+ 
+ # Make some filesystems and put some content on the
+@@ -100,11 +100,11 @@ eval `../fish/guestfish --listen`
+ ../fish/guestfish --remote run
+ 
+ for md in `../fish/guestfish --remote list-md-devices`; do
+-  ../fish/guestfish --remote mdadm-detail "${md}" > mdadm-detail.out
++  ../fish/guestfish --remote md-detail "${md}" > md-detail.out
+ 
+-  sed 's/:\s*/=/' mdadm-detail.out > mdadm-detail.out.sh
+-  . mdadm-detail.out.sh
+-  rm -f mdadm-detail.out.sh
++  sed 's/:\s*/=/' md-detail.out > md-detail.out.sh
++  . md-detail.out.sh
++  rm -f md-detail.out.sh
+ 
+   error=0
+   case "$name" in
+@@ -141,8 +141,8 @@ for md in `../fish/guestfish --remote list-md-devices`; do
+   [ ! -z "$metadata" ] || error=1
+ 
+   if [ "$error" == "1" ]; then
+-    echo "$0: Unexpected output from mdadm-detail for device $md"
+-    cat mdadm-detail.out
++    echo "$0: Unexpected output from md-detail for device $md"
++    cat md-detail.out
+     ../fish/guestfish --remote exit
+     exit 1
+   fi
+@@ -150,4 +150,4 @@ done
+ 
+ ../fish/guestfish --remote exit
+ 
+-rm -f mdadm-detail.out md-test1.img md-test2.img md-test3.img md-test4.img
++rm -f md-detail.out md-test1.img md-test2.img md-test3.img md-test4.img
+-- 
+1.7.6
+
diff --git a/0009-inspection-Cleanup-iteration-over-fstab-entries-in-i.patch b/0009-inspection-Cleanup-iteration-over-fstab-entries-in-i.patch
new file mode 100644
index 0000000..360a8fa
--- /dev/null
+++ b/0009-inspection-Cleanup-iteration-over-fstab-entries-in-i.patch
@@ -0,0 +1,115 @@
+From 6618ecf09fcaa4c21b7fabc0b2f8b56cdbd0ea0d Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Fri, 25 Nov 2011 13:16:54 +0000
+Subject: [PATCH 09/10] inspection: Cleanup iteration over fstab entries in
+ inspect_fs_unix.c
+
+Select non-comment labels using an augeas path to return the correct
+nodes in the first instance, rather than applying a regular expression
+to all results.
+
+There is no functional change to the code.
+
+RWMJ:
+ - Rebased to current HEAD.
+ - Move variable decls to top of function.
+ - Some whitespace changes.
+ - Remove check for errors from snprintf since it can never happen.
+(cherry picked from commit 35c8e4fa7f5c90cc8371028e2bfc0562272380e3)
+---
+ src/inspect_fs_unix.c |   52 ++++++++++++++++++++++--------------------------
+ 1 files changed, 24 insertions(+), 28 deletions(-)
+
+diff --git a/src/inspect_fs_unix.c b/src/inspect_fs_unix.c
+index 3046e02..caf7e48 100644
+--- a/src/inspect_fs_unix.c
++++ b/src/inspect_fs_unix.c
+@@ -107,7 +107,6 @@ compile_regexps (void)
+   COMPILE (re_scientific_linux_no_minor,
+            "Scientific Linux.*release (\\d+)", 0);
+   COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
+-  COMPILE (re_aug_seq, "/\\d+$", 0);
+   COMPILE (re_xdev, "^/dev/(h|s|v|xv)d([a-z]+)(\\d*)$", 0);
+   COMPILE (re_cciss, "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$", 0);
+   COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
+@@ -128,7 +127,6 @@ free_regexps (void)
+   pcre_free (re_scientific_linux);
+   pcre_free (re_scientific_linux_no_minor);
+   pcre_free (re_major_minor);
+-  pcre_free (re_aug_seq);
+   pcre_free (re_xdev);
+   pcre_free (re_cciss);
+   pcre_free (re_freebsd);
+@@ -688,45 +686,43 @@ check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs)
+ static int
+ check_fstab (guestfs_h *g, struct inspect_fs *fs)
+ {
+-  char **lines = guestfs_aug_ls (g, "/files/etc/fstab");
+-  if (lines == NULL) goto error;
++  char **entries, **entry;
++  char augpath[256];
++  char *spec, *mp;
++  int r;
++
++  entries = guestfs_aug_match (g, "/files/etc/fstab/*[label() != '#comment']");
++  if (entries == NULL) goto error;
+ 
+-  if (lines[0] == NULL) {
++  if (entries[0] == NULL) {
+     error (g, _("could not parse /etc/fstab or empty file"));
+     goto error;
+   }
+ 
+-  size_t i;
+-  char augpath[256];
+-  for (i = 0; lines[i] != NULL; ++i) {
+-    /* Ignore comments.  Only care about sequence lines which
+-     * match m{/\d+$}.
+-     */
+-    if (match (g, lines[i], re_aug_seq)) {
+-      snprintf (augpath, sizeof augpath, "%s/spec", lines[i]);
+-      char *spec = guestfs_aug_get (g, augpath);
+-      if (spec == NULL) goto error;
+-
+-      snprintf (augpath, sizeof augpath, "%s/file", lines[i]);
+-      char *mp = guestfs_aug_get (g, augpath);
+-      if (mp == NULL) {
+-        free (spec);
+-        goto error;
+-      }
++  for (entry = entries; *entry != NULL; entry++) {
++    snprintf (augpath, sizeof augpath, "%s/spec", *entry);
++    spec = guestfs_aug_get (g, augpath);
++    if (spec == NULL) goto error;
+ 
+-      int r = add_fstab_entry (g, fs, spec, mp);
++    snprintf (augpath, sizeof augpath, "%s/file", *entry);
++    mp = guestfs_aug_get (g, augpath);
++    if (mp == NULL) {
+       free (spec);
+-      free (mp);
+-
+-      if (r == -1) goto error;
++      goto error;
+     }
++
++    r = add_fstab_entry (g, fs, spec, mp);
++    free (spec);
++    free (mp);
++
++    if (r == -1) goto error;
+   }
+ 
+-  guestfs___free_string_list (lines);
++  guestfs___free_string_list (entries);
+   return 0;
+ 
+ error:
+-  if (lines) guestfs___free_string_list (lines);
++  if (entries) guestfs___free_string_list (entries);
+   return -1;
+ }
+ 
+-- 
+1.7.6
+
diff --git a/0010-inspection-Handle-MD-devices-in-fstab.patch b/0010-inspection-Handle-MD-devices-in-fstab.patch
new file mode 100644
index 0000000..d42c401
--- /dev/null
+++ b/0010-inspection-Handle-MD-devices-in-fstab.patch
@@ -0,0 +1,456 @@
+From 47d97c057665bac8997936a7f81f5e4e1f88ecca Mon Sep 17 00:00:00 2001
+From: Matthew Booth <mbooth at redhat.com>
+Date: Fri, 2 Dec 2011 14:04:19 +0000
+Subject: [PATCH 10/10] inspection: Handle MD devices in fstab
+
+This patch fixes inspection when fstab contains devices md devices
+specified as /dev/mdN. The appliance creates these devices without reference to
+the guest's mdadm.conf so, for e.g. /dev/md0 in the guest will often be created
+as /dev/md127 in the appliance. With this patch, we match the uuids of detected
+md devices against uuids specified in mdadm.conf, and map them appropriately
+when we encounter them in fstab.
+(cherry picked from commit 922c3623c63b137ce940c574791104744e716c4a)
+---
+ src/inspect_fs_unix.c |  330 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 323 insertions(+), 7 deletions(-)
+
+diff --git a/src/inspect_fs_unix.c b/src/inspect_fs_unix.c
+index caf7e48..b343d44 100644
+--- a/src/inspect_fs_unix.c
++++ b/src/inspect_fs_unix.c
+@@ -38,6 +38,8 @@
+ #include "c-ctype.h"
+ #include "ignore-value.h"
+ #include "xstrtol.h"
++#include "hash.h"
++#include "hash-pjw.h"
+ 
+ #include "guestfs.h"
+ #include "guestfs-internal.h"
+@@ -65,6 +67,7 @@ static pcre *re_major_minor;
+ static pcre *re_aug_seq;
+ static pcre *re_xdev;
+ static pcre *re_cciss;
++static pcre *re_mdN;
+ static pcre *re_first_partition;
+ static pcre *re_freebsd;
+ static pcre *re_netbsd;
+@@ -109,6 +112,7 @@ compile_regexps (void)
+   COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
+   COMPILE (re_xdev, "^/dev/(h|s|v|xv)d([a-z]+)(\\d*)$", 0);
+   COMPILE (re_cciss, "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$", 0);
++  COMPILE (re_mdN, "^(/dev/md\\d+)$", 0);
+   COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
+   COMPILE (re_netbsd, "^NetBSD (\\d+)\\.(\\d+)", 0);
+ }
+@@ -129,6 +133,7 @@ free_regexps (void)
+   pcre_free (re_major_minor);
+   pcre_free (re_xdev);
+   pcre_free (re_cciss);
++  pcre_free (re_mdN);
+   pcre_free (re_freebsd);
+   pcre_free (re_netbsd);
+ }
+@@ -139,10 +144,37 @@ static int check_hostname_redhat (guestfs_h *g, struct inspect_fs *fs);
+ static int check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs);
+ static int check_fstab (guestfs_h *g, struct inspect_fs *fs);
+ static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
+-                            const char *spec, const char *mp);
+-static char *resolve_fstab_device (guestfs_h *g, const char *spec);
++                            const char *spec, const char *mp,
++                            Hash_table *md_map);
++static char *resolve_fstab_device (guestfs_h *g, const char *spec,
++                                   Hash_table *md_map);
+ static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char **configfiles, int (*f) (guestfs_h *, struct inspect_fs *));
+ 
++/* Hash structure for uuid->path lookups */
++typedef struct md_uuid {
++  uint32_t uuid[4];
++  char *path;
++} md_uuid;
++
++static size_t uuid_hash(const void *x, size_t table_size);
++static bool uuid_cmp(const void *x, const void *y);
++static void md_uuid_free(void *x);
++
++static int parse_uuid(const char *str, uint32_t *uuid);
++
++/* Hash structure for path(mdadm)->path(appliance) lookup */
++typedef struct {
++  char *mdadm;
++  char *app;
++} mdadm_app;
++
++static size_t mdadm_app_hash(const void *x, size_t table_size);
++static bool mdadm_app_cmp(const void *x, const void *y);
++static void mdadm_app_free(void *x);
++
++static int map_app_md_devices (guestfs_h *g, Hash_table **map);
++static int map_md_devices(guestfs_h *g, Hash_table **map);
++
+ /* Set fs->product_name to the first line of the release file. */
+ static int
+ parse_release_file (guestfs_h *g, struct inspect_fs *fs,
+@@ -444,7 +476,7 @@ guestfs___check_linux_root (guestfs_h *g, struct inspect_fs *fs)
+    * which filesystems are used by the operating system and how they
+    * are mounted.
+    */
+-  const char *configfiles[] = { "/etc/fstab", NULL };
++  const char *configfiles[] = { "/etc/fstab", "/etc/mdadm.conf", NULL };
+   if (inspect_with_augeas (g, fs, configfiles, check_fstab) == -1)
+     return -1;
+ 
+@@ -691,6 +723,11 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
+   char *spec, *mp;
+   int r;
+ 
++  /* Generate a map of MD device paths listed in /etc/mdadm.conf to MD device
++   * paths in the guestfs appliance */
++  Hash_table *md_map;
++  if (map_md_devices (g, &md_map) == -1) return -1;
++
+   entries = guestfs_aug_match (g, "/files/etc/fstab/*[label() != '#comment']");
+   if (entries == NULL) goto error;
+ 
+@@ -711,17 +748,19 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
+       goto error;
+     }
+ 
+-    r = add_fstab_entry (g, fs, spec, mp);
++    r = add_fstab_entry (g, fs, spec, mp, md_map);
+     free (spec);
+     free (mp);
+ 
+     if (r == -1) goto error;
+   }
+ 
++  if (md_map) hash_free (md_map);
+   guestfs___free_string_list (entries);
+   return 0;
+ 
+ error:
++  if (md_map) hash_free (md_map);
+   if (entries) guestfs___free_string_list (entries);
+   return -1;
+ }
+@@ -736,7 +775,7 @@ error:
+  */
+ static int
+ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
+-                 const char *spec, const char *mp)
++                 const char *spec, const char *mp, Hash_table *md_map)
+ {
+   /* Ignore certain mountpoints. */
+   if (STRPREFIX (mp, "/dev/") ||
+@@ -768,7 +807,7 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
+     device = safe_strdup (g, fs->device);
+   else if (STRPREFIX (spec, "/dev/"))
+     /* Resolve guest block device names. */
+-    device = resolve_fstab_device (g, spec);
++    device = resolve_fstab_device (g, spec, md_map);
+ 
+   /* If we haven't resolved the device successfully by this point,
+    * we don't care, just ignore it.
+@@ -805,6 +844,274 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
+   return 0;
+ }
+ 
++/* Compute a uuid hash as a simple xor of of its 4 32bit components */
++static size_t
++uuid_hash(const void *x, size_t table_size)
++{
++  const md_uuid *a = x;
++
++  size_t h = a->uuid[0];
++  for (size_t i = 1; i < 4; i++) {
++    h ^= a->uuid[i];
++  }
++
++  return h % table_size;
++}
++
++static bool
++uuid_cmp(const void *x, const void *y)
++{
++  const md_uuid *a = x;
++  const md_uuid *b = y;
++
++  for (size_t i = 0; i < 1; i++) {
++    if (a->uuid[i] != b->uuid[i]) return false;
++  }
++
++  return true;
++}
++
++static void
++md_uuid_free(void *x)
++{
++  md_uuid *a = x;
++  free(a->path);
++  free(a);
++}
++
++/* Taken from parse_uuid in mdadm */
++static int
++parse_uuid(const char *str, uint32_t *uuid)
++{
++  for (size_t i = 0; i < 4; i++) uuid[i] = 0;
++
++  int hit = 0; /* number of Hex digIT */
++  char c;
++  while ((c = *str++)) {
++    int n;
++    if (c >= '0' && c <= '9')
++      n = c - '0';
++    else if (c >= 'a' && c <= 'f')
++      n = 10 + c - 'a';
++    else if (c >= 'A' && c <= 'F')
++      n = 10 + c - 'A';
++    else if (strchr(":. -", c))
++      continue;
++    else return false;
++
++    if (hit < 32) {
++      uuid[hit / 8] <<= 4;
++      uuid[hit / 8] += n;
++    }
++    hit++;
++  }
++  if (hit == 32) return 0;
++
++  return -1;
++}
++
++/* Create a mapping of uuids to appliance md device names */
++static int
++map_app_md_devices (guestfs_h *g, Hash_table **map)
++{
++  char **mds = NULL;
++  int n = 0;
++
++  /* A hash mapping uuids to md device names */
++  *map = hash_initialize(16, NULL, uuid_hash, uuid_cmp, md_uuid_free);
++  if (*map == NULL) g->abort_cb();
++
++  mds = guestfs_list_md_devices(g);
++  if (mds == NULL) goto error;
++
++  for (char **md = mds; *md != NULL; md++) {
++    char **detail = guestfs_md_detail(g, *md);
++    if (detail == NULL) goto error;
++
++    /* Iterate over keys until we find uuid */
++    char **i;
++    for (i = detail; *i != NULL; i += 2) {
++      if (STREQ(*i, "uuid")) break;
++    }
++
++    /* We found it */
++    if (*i) {
++      /* Next item is the uuid value */
++      i++;
++
++      md_uuid *entry = safe_malloc(g, sizeof(md_uuid));
++      entry->path = safe_strdup(g, *md);
++
++      if (parse_uuid(*i, entry->uuid) == -1) {
++        /* Invalid UUID is weird, but not fatal. */
++        debug(g, "inspect-os: guestfs_md_detail returned invalid "
++                 "uuid for %s: %s", *md, *i);
++        guestfs___free_string_list(detail);
++        md_uuid_free(entry);
++        continue;
++      }
++
++      const void *matched = NULL;
++      switch (hash_insert_if_absent(*map, entry, &matched)) {
++        case -1:
++          g->abort_cb();
++
++        case 0:
++          /* Duplicate uuid in for md device is weird, but not fatal. */
++          debug(g, "inspect-os: md devices %s and %s have the same uuid",
++                ((md_uuid *)matched)->path, entry->path);
++          md_uuid_free(entry);
++          break;
++
++        default:
++          n++;
++      }
++    }
++
++    guestfs___free_string_list(detail);
++  }
++
++  guestfs___free_string_list(mds);
++
++  return n;
++
++error:
++  hash_free(*map); *map = NULL;
++  guestfs___free_string_list(mds);
++
++  return -1;
++}
++
++static size_t
++mdadm_app_hash(const void *x, size_t table_size)
++{
++  const mdadm_app *a = x;
++  return hash_pjw(a->mdadm, table_size);
++}
++
++static bool
++mdadm_app_cmp(const void *x, const void *y)
++{
++  const mdadm_app *a = x;
++  const mdadm_app *b = y;
++
++  return strcmp(a->mdadm, b->mdadm) == 0;
++}
++
++static void
++mdadm_app_free(void *x)
++{
++  mdadm_app *a = x;
++  free(a->mdadm);
++  free(a->app);
++  free(a);
++}
++
++/* Get a map of md device names in mdadm.conf to their device names in the
++ * appliance */
++static int
++map_md_devices(guestfs_h *g, Hash_table **map)
++{
++  Hash_table *app_map = NULL;
++  char **matches = NULL;
++  *map = NULL;
++
++  /* Get a map of md device uuids to their device names in the appliance */
++  int n_app_md_devices = map_app_md_devices(g, &app_map);
++  if (n_app_md_devices == -1) goto error;
++
++  /* Nothing to do if there are no md devices */
++  if (n_app_md_devices == 0) {
++    hash_free(app_map);
++    return 0;
++  }
++
++  /* Get all arrays listed in mdadm.conf */
++  matches = guestfs_aug_match(g, "/files/etc/mdadm.conf/array");
++  if (!matches) goto error;
++
++  /* Log a debug message if we've got md devices, but nothing in mdadm.conf */
++  if (matches[0] == NULL) {
++    debug(g, "Appliance has MD devices, but augeas returned no array matches "
++             "in mdadm.conf");
++    guestfs___free_string_list(matches);
++    hash_free(app_map);
++    return 0;
++  }
++
++  *map = hash_initialize(16, NULL, mdadm_app_hash, mdadm_app_cmp,
++                                   mdadm_app_free);
++  if (!*map) g->abort_cb();
++
++  for (char **match = matches; *match != NULL; match++) {
++    /* Get device name and uuid for each array */
++    char *dev_path = safe_asprintf(g, "%s/devicename", *match);
++    char *dev = guestfs_aug_get(g, dev_path);
++    free(dev_path);
++    if (!dev) goto error;
++
++    char *uuid_path = safe_asprintf(g, "%s/uuid", *match);
++    char *uuid = guestfs_aug_get(g, uuid_path);
++    free(uuid_path);
++    if (!uuid) {
++      free(dev);
++      goto error;
++    }
++
++    /* Parse the uuid into an md_uuid structure so we can look it up in the
++     * uuid->appliance device map */
++    md_uuid mdadm;
++    mdadm.path = dev;
++    if (parse_uuid(uuid, mdadm.uuid) == -1) {
++      /* Invalid uuid. Weird, but not fatal. */
++      debug(g, "inspect-os: mdadm.conf contains invalid uuid for %s: %s",
++            dev, uuid);
++      free(dev);
++      free(uuid);
++      continue;
++    }
++    free(uuid);
++
++    /* If there's a corresponding uuid in the appliance, create a new
++     * entry in the transitive map */
++    md_uuid *app = hash_lookup(app_map, &mdadm);
++    if (app) {
++      mdadm_app *entry = safe_malloc(g, sizeof(mdadm_app));
++      entry->mdadm = dev;
++      entry->app = safe_strdup(g, app->path);
++
++      switch (hash_insert_if_absent(*map, entry, NULL)) {
++        case -1:
++          g->abort_cb();
++
++        case 0:
++          /* Duplicate uuid in for md device is weird, but not fatal. */
++          debug(g, "inspect-os: mdadm.conf contains multiple entries for %s",
++                app->path);
++          mdadm_app_free(entry);
++          continue;
++
++        default:
++          ;;
++      }
++    } else {
++      free(dev);
++    }
++  }
++
++  hash_free(app_map);
++  guestfs___free_string_list(matches);
++
++  return 0;
++
++error:
++  if (app_map) hash_free(app_map);
++  if (matches) guestfs___free_string_list(matches);
++  if (*map) hash_free(*map);
++
++  return -1;
++}
++
+ /* Resolve block device name to the libguestfs device name, eg.
+  * /dev/xvdb1 => /dev/vdb1; and /dev/mapper/VG-LV => /dev/VG/LV.  This
+  * assumes that disks were added in the same order as they appear to
+@@ -812,7 +1119,7 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
+  * anything we don't recognize unchanged.
+  */
+ static char *
+-resolve_fstab_device (guestfs_h *g, const char *spec)
++resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map)
+ {
+   char *device = NULL;
+   char *type, *slice, *disk, *part;
+@@ -907,6 +1214,15 @@ resolve_fstab_device (guestfs_h *g, const char *spec)
+     free (part);
+     guestfs___free_string_list (devices);
+   }
++  else if (md_map && (disk = match1 (g, spec, re_mdN)) != NULL) {
++    mdadm_app entry;
++    entry.mdadm = disk;
++
++    mdadm_app *app = hash_lookup (md_map, &entry);
++    if (app) device = safe_strdup (g, app->app);
++
++    free(disk);
++  }
+   else if (match3 (g, spec, re_freebsd, &disk, &slice, &part)) {
+     /* FreeBSD disks are organized quite differently.  See:
+      * http://www.freebsd.org/doc/handbook/disk-organization.html
+-- 
+1.7.6
+
diff --git a/libguestfs.spec b/libguestfs.spec
index 34a77e5..171af10 100644
--- a/libguestfs.spec
+++ b/libguestfs.spec
@@ -29,7 +29,7 @@
 Summary:       Access and modify virtual machine disk images
 Name:          libguestfs
 Epoch:         1
-Version:       1.14.5
+Version:       1.14.6
 Release:       1%{?dist}
 License:       LGPLv2+
 Group:         Development/Libraries
@@ -37,6 +37,17 @@ URL:           http://libguestfs.org/
 Source0:       http://libguestfs.org/download/1.14-development/%{name}-%{version}.tar.gz
 BuildRoot:     %{_tmppath}/%{name}-%{version}-%{release}-root
 
+Patch0001:     0001-New-API-mdadm-create-for-creating-MD-devices.patch
+Patch0002:     0002-New-API-list-md-devices.patch
+Patch0003:     0003-Update-list-filesystems-to-check-md-devices.patch
+Patch0004:     0004-New-API-mdadm-detail.patch
+Patch0005:     0005-fish-Add-MD-devices-to-guestfish-device-autocompleti.patch
+Patch0006:     0006-build-Create-an-MD-variant-of-the-dummy-Fedora-image.patch
+Patch0007:     0007-md-Inspect-MD-devices.patch
+Patch0008:     0008-Rename-mdadm_-apis-to-md_.patch
+Patch0009:     0009-inspection-Cleanup-iteration-over-fstab-entries-in-i.patch
+Patch0010:     0010-inspection-Handle-MD-devices-in-fstab.patch
+
 %if 0%{?rhel} >= 7
 ExclusiveArch: x86_64
 %endif
@@ -67,6 +78,9 @@ BuildRequires: ocaml
 BuildRequires: ocaml-findlib-devel
 BuildRequires: systemd-units
 
+# Use git + autotools when applying patches.
+BuildRequires: git, automake, autoconf, libtool, gettext
+
 # This is only needed for RHEL 5 because readline-devel doesn't
 # properly depend on it, but doesn't do any harm on other platforms:
 BuildRequires: ncurses-devel
@@ -588,6 +602,17 @@ for %{name}.
 %prep
 %setup -q
 
+git init
+git config user.email "libguestfs at redhat.com"
+git config user.name "libguestfs developers"
+git add .
+git commit -a -q -m "%{name} %{version}"
+git am --whitespace=nowarn %{patches}
+
+# Patches affect Makefile.am and configure.ac, so rerun autotools.
+autoreconf
+autoconf
+
 mkdir -p daemon/m4
 
 # Replace developer-specific README that ships with libguestfs, with
@@ -963,6 +988,11 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %changelog
+* Tue Dec  6 2011 Richard W.M. Jones <rjones at redhat.com> - 1:1.14.6-1
+- New upstream stable version 1.14.6.
+- Add support for inspection of MD devices (RHBZ#760245).
+- Use git to manage patches.
+
 * Fri Dec  2 2011 Richard W.M. Jones <rjones at redhat.com> - 1:1.14.5-1
 - New upstream stable version 1.14.5.
 
diff --git a/sources b/sources
index 097ce00..7977844 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-45546f996600bb2644ebdde4142c34dc  libguestfs-1.14.5.tar.gz
+86fe8a0d54712426f202854eb9e4a63b  libguestfs-1.14.6.tar.gz


More information about the scm-commits mailing list