[gnome-disk-utility] handle inactive and partitioned md devices
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-disk-utility] handle inactive and partitioned md devices
- Date: Sun, 15 Mar 2009 17:05:33 -0400 (EDT)
commit 816e1b3f0af2b52a0a2c19f6092d836da7944ffe
Author: David Zeuthen <davidz redhat com>
Date: Sun Mar 15 16:57:43 2009 -0400
handle inactive and partitioned md devices
See
http://cgit.freedesktop.org/DeviceKit/DeviceKit-disks/commit/?id=1c6e690dcdc5f31d69d39fc89a9db035802febcc
for the 'inactive' bits. Basically we need this to cope with the current way
autoassembly is handled by Fedora. E.g. if you put in half a mirror and then
remove it again, there's an inactive array with a dangling symlink in sysfs.
For partitioned md devices, this was introduced in the kernel with
this commit
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=92850bbd71228730c80efd491e7427650188d359
Note that there's a bug in current udev (version 140ish) that prevents
probing the partions of a md device. This will get fixed soon.
To make it possible to partition an md device, we have moved the
"Create partition table" section so it's only visible for a completely
unrecognized device (e.g. when we only see a top-level block device
with no partitions or no recognizable signature).
The move of "Create partition table" makes the UI look a bit empty for
disks that don't report SMART status; there's no sections at all. It
also makes it a bit harder to completely format a disk. The former
should be fixed by having some graphical representation of the
partitions/content, the latter by having a File->New menu that
launches a wizard to prepare formatting the disk.
---
src/gdu/gdu-linux-md-drive.c | 148 +++++++------------
src/gdu/gdu-pool.c | 33 +++--
src/gdu/gdu-private.h | 3 +-
src/gdu/gdu-volume-hole.c | 8 +-
.../gdu-section-create-partition-table.c | 4 +-
src/palimpsest/gdu-section-linux-md-drive.c | 26 +++-
src/palimpsest/gdu-shell.c | 22 +++-
7 files changed, 131 insertions(+), 113 deletions(-)
diff --git a/src/gdu/gdu-linux-md-drive.c b/src/gdu/gdu-linux-md-drive.c
index 0e0bb33..ae14dc2 100644
--- a/src/gdu/gdu-linux-md-drive.c
+++ b/src/gdu/gdu-linux-md-drive.c
@@ -58,6 +58,8 @@ struct _GduLinuxMdDrivePrivate
gchar *uuid;
+ gchar *device_file;
+
gchar *id;
};
@@ -93,13 +95,15 @@ gdu_linux_md_drive_finalize (GObject *object)
//g_debug ("##### finalized linux-md drive '%s' %p", drive->priv->id, drive);
- if (drive->priv->pool != NULL) {
+ if (drive->priv->uuid != NULL) {
g_signal_handlers_disconnect_by_func (drive->priv->pool, device_added, drive);
g_signal_handlers_disconnect_by_func (drive->priv->pool, device_removed, drive);
g_signal_handlers_disconnect_by_func (drive->priv->pool, device_changed, drive);
- g_object_unref (drive->priv->pool);
}
+ if (drive->priv->pool != NULL)
+ g_object_unref (drive->priv->pool);
+
if (drive->priv->device != NULL) {
g_object_unref (drive->priv->device);
}
@@ -109,6 +113,9 @@ gdu_linux_md_drive_finalize (GObject *object)
g_free (drive->priv->id);
+ g_free (drive->priv->uuid);
+ g_free (drive->priv->device_file);
+
if (G_OBJECT_CLASS (parent_class)->finalize)
(* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (drive));
}
@@ -266,22 +273,37 @@ device_changed (GduPool *pool, GduDevice *device, gpointer user_data)
}
}
+/**
+ * _gdu_linux_md_drive_new:
+ * @pool: A #GduPool.
+ * @uuid: The UUID for the array.
+ * @device_file: The device file for the array.
+ *
+ * Creates a new #GduLinuxMdDrive. Note that only one of @uuid and
+ * @device_file may be %NULL.
+ */
GduLinuxMdDrive *
_gdu_linux_md_drive_new (GduPool *pool,
- const gchar *uuid)
+ const gchar *uuid,
+ const gchar *device_file)
{
GduLinuxMdDrive *drive;
drive = GDU_LINUX_MD_DRIVE (g_object_new (GDU_TYPE_LINUX_MD_DRIVE, NULL));
drive->priv->pool = g_object_ref (pool);
drive->priv->uuid = g_strdup (uuid);
- drive->priv->id = g_strdup_printf ("linux_md_%s", uuid);
-
- g_signal_connect (drive->priv->pool, "device-added", G_CALLBACK (device_added), drive);
- g_signal_connect (drive->priv->pool, "device-removed", G_CALLBACK (device_removed), drive);
- g_signal_connect (drive->priv->pool, "device-changed", G_CALLBACK (device_changed), drive);
-
- prime_devices (drive);
+ drive->priv->device_file = g_strdup (device_file);
+
+ if (uuid != NULL) {
+ drive->priv->id = g_strdup_printf ("linux_md_%s", uuid);
+ g_signal_connect (drive->priv->pool, "device-added", G_CALLBACK (device_added), drive);
+ g_signal_connect (drive->priv->pool, "device-removed", G_CALLBACK (device_removed), drive);
+ g_signal_connect (drive->priv->pool, "device-changed", G_CALLBACK (device_changed), drive);
+ prime_devices (drive);
+ } else {
+ drive->priv->id = g_strdup_printf ("linux_md_%s", device_file);
+ drive->priv->device = gdu_pool_get_by_device_file (pool, device_file);
+ }
return drive;
}
@@ -412,28 +434,36 @@ gdu_linux_md_drive_get_name (GduPresentable *presentable)
ret = NULL;
- if (drive->priv->slaves == NULL)
- goto out;
+ if (drive->priv->slaves != NULL) {
+ device = GDU_DEVICE (drive->priv->slaves->data);
- device = GDU_DEVICE (drive->priv->slaves->data);
+ level = gdu_device_linux_md_component_get_level (device);
+ name = gdu_device_linux_md_component_get_name (device);
+ num_raid_devices = gdu_device_linux_md_component_get_num_raid_devices (device);
+ num_slaves = g_list_length (drive->priv->slaves);
+ component_size = gdu_device_get_size (device);
- level = gdu_device_linux_md_component_get_level (device);
- name = gdu_device_linux_md_component_get_name (device);
- num_raid_devices = gdu_device_linux_md_component_get_num_raid_devices (device);
- num_slaves = g_list_length (drive->priv->slaves);
- component_size = gdu_device_get_size (device);
+ level_str = gdu_linux_md_get_raid_level_for_display (level);
- level_str = gdu_linux_md_get_raid_level_for_display (level);
+ if (name == NULL || strlen (name) == 0) {
+ ret = g_strdup_printf (_("%s Drive"), level_str);
+ } else {
+ ret = g_strdup_printf (_("%s (%s)"), name, level_str);
+ }
+
+ g_free (level_str);
+
+ } else if (drive->priv->device != NULL) {
+ ret = g_strdup_printf (_("RAID device %s (%s)"),
+ gdu_device_get_device_file (drive->priv->device),
+ gdu_device_linux_md_get_state (drive->priv->device));
- if (name == NULL || strlen (name) == 0) {
- ret = g_strdup_printf (_("%s Drive"), level_str);
} else {
- ret = g_strdup_printf (_("%s (%s)"), name, level_str);
- }
+ g_warn_if_fail (drive->priv->device_file != NULL);
- g_free (level_str);
+ ret = g_strdup_printf (_("RAID device %s"), drive->priv->device_file);
+ }
-out:
return ret;
}
@@ -677,74 +707,6 @@ out:
return ret;
}
-#if 0
-static gboolean
-gdu_linux_md_drive_can_activate_degraded (GduDrive *_drive)
-{
- GduLinuxMdDrive *drive = GDU_LINUX_MD_DRIVE (_drive);
- GduDevice *device;
- gboolean can_activate_degraded;
- int num_ready_slaves;
- int num_raid_devices;
- const char *raid_level;
-
- device = NULL;
-
- can_activate_degraded = FALSE;
-
- /* can't activated what's already activated */
- if (drive->priv->device != NULL)
- goto out;
-
- /* we might even be able to activate in non-degraded mode */
- if (gdu_linux_md_drive_can_activate (_drive))
- goto out;
-
- device = gdu_linux_md_drive_get_first_slave (drive);
- if (device == NULL)
- goto out;
-
- num_ready_slaves = gdu_linux_md_drive_get_num_ready_slaves (drive);
- num_raid_devices = gdu_device_linux_md_component_get_num_raid_devices (device);
- raid_level = gdu_device_linux_md_component_get_level (device);
-
- /* this depends on the raid level... */
- if (strcmp (raid_level, "raid1") == 0) {
- if (num_ready_slaves >= 1) {
- can_activate_degraded = TRUE;
- }
- } else if (strcmp (raid_level, "raid4") == 0) {
- if (num_ready_slaves >= num_raid_devices - 1) {
- can_activate_degraded = TRUE;
- }
- } else if (strcmp (raid_level, "raid5") == 0) {
- if (num_ready_slaves >= num_raid_devices - 1) {
- can_activate_degraded = TRUE;
- }
- } else if (strcmp (raid_level, "raid6") == 0) {
- if (num_ready_slaves >= num_raid_devices - 2) {
- can_activate_degraded = TRUE;
- }
- } else if (strcmp (raid_level, "raid10") == 0) {
- /* TODO: This is not necessarily correct; it depends on which
- * slaves have failed... Right now we err on the side
- * of saying the array can be activated even when sometimes
- * it can't
- */
- if (num_ready_slaves >= num_raid_devices / 2) {
- can_activate_degraded = TRUE;
- }
- }
-
-
-out:
- if (device != NULL)
- g_object_unref (device);
- return can_activate_degraded;
- return FALSE;
-}
-#endif
-
typedef struct
{
GduLinuxMdDrive *drive;
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index 00aa228..c1cfd2b 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -554,7 +554,7 @@ recompute_presentables (GduPool *pool)
*
* The reason for this brute-force approach is that the GduPresentable entities are
* somewhat complicated since the whole process involves synthesizing GduVolumeHole and
- * GduActivatableDrive objects.
+ * GduLinuxMdDrive objects.
*/
new_presentables = NULL;
@@ -595,16 +595,29 @@ recompute_presentables (GduPool *pool)
const gchar *uuid;
uuid = gdu_device_linux_md_get_uuid (device);
- drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid));
- /* Due to the topological sorting of devices, we are guaranteed that
- * that running Linux MD arrays come before the slaves.
- */
- g_warn_if_fail (g_hash_table_lookup (hash_map_from_linux_md_uuid_to_drive, uuid) == NULL);
+ /* 'clear' and 'inactive' devices may not have an uuid */
+ if (uuid != NULL && strlen (uuid) == 0)
+ uuid = NULL;
+
+ if (uuid != NULL) {
+ drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid, NULL));
+
+ /* Due to the topological sorting of devices, we are guaranteed that
+ * that running Linux MD arrays come before the slaves.
+ */
+ g_warn_if_fail (g_hash_table_lookup (hash_map_from_linux_md_uuid_to_drive, uuid) == NULL);
+
+ g_hash_table_insert (hash_map_from_linux_md_uuid_to_drive,
+ (gpointer) uuid,
+ drive);
+ } else {
+ drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool,
+ NULL,
+ gdu_device_get_device_file (device)));
+ }
+
- g_hash_table_insert (hash_map_from_linux_md_uuid_to_drive,
- (gpointer) uuid,
- drive);
} else {
drive = _gdu_drive_new_from_device (pool, device);
}
@@ -709,7 +722,7 @@ recompute_presentables (GduPool *pool)
if (g_hash_table_lookup (hash_map_from_linux_md_uuid_to_drive, uuid) == NULL) {
GduDrive *drive;
- drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid));
+ drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid, NULL));
new_presentables = g_list_prepend (new_presentables, drive);
g_hash_table_insert (hash_map_from_linux_md_uuid_to_drive,
diff --git a/src/gdu/gdu-private.h b/src/gdu/gdu-private.h
index 96e7510..2beaa9f 100644
--- a/src/gdu/gdu-private.h
+++ b/src/gdu/gdu-private.h
@@ -94,7 +94,8 @@ GduVolumeHole *_gdu_volume_hole_new (GduPool *pool, guint64 offset, guin
GduLinuxMdDrive *_gdu_linux_md_drive_new (GduPool *pool,
- const gchar *uuid);
+ const gchar *uuid,
+ const gchar *device_file);
gboolean _gdu_linux_md_drive_has_uuid (GduLinuxMdDrive *drive,
const gchar *uuid);
diff --git a/src/gdu/gdu-volume-hole.c b/src/gdu/gdu-volume-hole.c
index af8141e..6d77fca 100644
--- a/src/gdu/gdu-volume-hole.c
+++ b/src/gdu/gdu-volume-hole.c
@@ -31,6 +31,7 @@
#include "gdu-device.h"
#include "gdu-volume-hole.h"
#include "gdu-presentable.h"
+#include "gdu-linux-md-drive.h"
/**
* SECTION:gdu-volume-hole
@@ -183,8 +184,13 @@ gdu_volume_hole_get_icon (GduPresentable *presentable)
drive_media = gdu_device_drive_get_media (d);
+ /* Linux MD devices can be partitioned */
+ if (GDU_IS_LINUX_MD_DRIVE (p)) {
+ name = "gdu-raid-array";
+ }
+
/* first try the media */
- if (drive_media != NULL) {
+ if (name == NULL && drive_media != NULL) {
if (strcmp (drive_media, "flash_cf") == 0) {
name = "media-flash-cf";
} else if (strcmp (drive_media, "flash_ms") == 0) {
diff --git a/src/palimpsest/gdu-section-create-partition-table.c b/src/palimpsest/gdu-section-create-partition-table.c
index 4bd3f87..bbabc7f 100644
--- a/src/palimpsest/gdu-section-create-partition-table.c
+++ b/src/palimpsest/gdu-section-create-partition-table.c
@@ -205,7 +205,7 @@ gdu_section_create_partition_table_init (GduSectionCreatePartitionTable *section
section->priv->create_part_table_action = polkit_gnome_action_new_default (
"create-part-table",
section->priv->pk_change_action,
- _("_Create"),
+ _("C_reate"),
_("Create"));
g_object_set (section->priv->create_part_table_action,
"auth-label", _("_Create..."),
@@ -244,7 +244,7 @@ gdu_section_create_partition_table_init (GduSectionCreatePartitionTable *section
/* partition table type */
label = gtk_label_new (NULL);
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
- gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("_Type:"));
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("Ty_pe:"));
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
combo_box = gdu_util_part_table_type_combo_box_create ();
diff --git a/src/palimpsest/gdu-section-linux-md-drive.c b/src/palimpsest/gdu-section-linux-md-drive.c
index a1195b9..90a6fd5 100644
--- a/src/palimpsest/gdu-section-linux-md-drive.c
+++ b/src/palimpsest/gdu-section-linux-md-drive.c
@@ -571,13 +571,33 @@ update (GduSectionLinuxMdDrive *section)
slaves = gdu_linux_md_drive_get_slaves (linux_md_drive);
num_slaves = g_list_length (slaves);
+
if (num_slaves == 0) {
- /* this fine; happens when the last component is yanked
- * since remove_slave() emits "changed".
+ /* This happens for 'clear' arrays or for arrays with stale symlinks
+ * to devices that has been yanked.
+ *
+ * - Ideally Linux MD / mdadm wouldn't have stale symlinks in sysfs but
+ * that is not how things currently work (2.6.29).
+ *
+ * - Also sometimes when stopping an array the md device is still around
+ *
+ * So we only offer to stop such arrays since the software beneath us
+ * is unstable. In an ideal world we wouldn't show them.
*/
- /*g_warning ("%s: no slaves for linux_md drive", __FUNCTION__);*/
+
+ gtk_label_set_text (GTK_LABEL (section->priv->linux_md_name_label), _("-"));
+ gtk_label_set_text (GTK_LABEL (section->priv->linux_md_home_host_label), _("-"));
+ gtk_label_set_text (GTK_LABEL (section->priv->linux_md_type_label), _("-"));
+ gtk_label_set_text (GTK_LABEL (section->priv->linux_md_size_label), _("-"));
+ gtk_label_set_text (GTK_LABEL (section->priv->linux_md_components_label), _("-"));
+ gtk_label_set_markup (GTK_LABEL (section->priv->linux_md_state_label), _("-"));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (section), FALSE);
goto out;
}
+
+ gtk_widget_set_sensitive (GTK_WIDGET (section), TRUE);
+
component = GDU_DEVICE (slaves->data);
if (!gdu_device_is_linux_md_component (component)) {
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index 8a0da93..324f57c 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -522,9 +522,6 @@ compute_sections_to_show (GduShell *shell, gboolean showing_job)
(gpointer) GDU_TYPE_SECTION_HEALTH);
}
- sections_to_show = g_list_append (sections_to_show,
- (gpointer) GDU_TYPE_SECTION_CREATE_PARTITION_TABLE);
-
}
} else if (GDU_IS_VOLUME (shell->priv->presentable_now_showing) && device != NULL) {
@@ -551,11 +548,30 @@ compute_sections_to_show (GduShell *shell, gboolean showing_job)
sections_to_show, (gpointer) GDU_TYPE_SECTION_SWAPSPACE);
}
} else {
+ GduPresentable *toplevel_presentable;
+ GduDevice *toplevel_device;
+
sections_to_show = g_list_append (
sections_to_show, (gpointer) GDU_TYPE_SECTION_UNRECOGNIZED);
+
+ /* Also show a "Create partition table" section for a volume if the drive isn't partitioned */
+ toplevel_presentable = gdu_presentable_get_toplevel (shell->priv->presentable_now_showing);
+ if (toplevel_presentable != NULL) {
+ toplevel_device = gdu_presentable_get_device (toplevel_presentable);
+
+ if (toplevel_device != NULL) {
+ if (!gdu_device_is_partition_table (toplevel_device)) {
+ sections_to_show = g_list_append (
+ sections_to_show, (gpointer) GDU_TYPE_SECTION_CREATE_PARTITION_TABLE);
+ }
+ g_object_unref (toplevel_device);
+ }
+ g_object_unref (toplevel_presentable);
+ }
}
} else if (GDU_IS_VOLUME_HOLE (shell->priv->presentable_now_showing)) {
+
sections_to_show = g_list_append (sections_to_show,
(gpointer) GDU_TYPE_SECTION_UNALLOCATED);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]