Richard W.M. Jones
2011-Nov-11 12:58 UTC
[Libguestfs] [PATCH v2] Add mdadm-create, list-md-devices APIs.
This adds the mdadm-create API for creating RAID devices, and includes various fixes for the other two patches. Rich.
Richard W.M. Jones
2011-Nov-11 12:58 UTC
[Libguestfs] [PATCH 1/3] New API: mdadm-create for creating MD devices.
From: "Richard W.M. Jones" <rjones at redhat.com> --- 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 7757067..c4a30bc 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 fe40fbf..4b18aa1 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -6432,6 +6432,64 @@ To get the current values of filesystem parameters, see C<guestfs_tune2fs_l>. For precise details of how tune2fs works, see the L<tune2fs(8)> man page."); + ("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<lt>]>. + +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 a1f7f63..03a5b41 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -298 +299 -- 1.7.6
Richard W.M. Jones
2011-Nov-11 12:58 UTC
[Libguestfs] [PATCH 2/3] New API: list-md-devices.
From: Matthew Booth <mbooth at redhat.com> Return a list of Linux MD devices detected in the guest. This API complements list_devices, list_partitions, list_lvs and list_dm_devices. --- 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 4b18aa1..0500d54 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -6490,6 +6490,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
Richard W.M. Jones
2011-Nov-11 12:58 UTC
[Libguestfs] [PATCH 3/3] Update list-filesystems to check md devices.
From: Matthew Booth <mbooth at redhat.com> --- 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