diff options
| author | David Zeuthen <davidz@redhat.com> | 2009-03-15 16:57:43 -0400 |
|---|---|---|
| committer | David Zeuthen <davidz@redhat.com> | 2009-03-15 16:57:43 -0400 |
| commit | 816e1b3f0af2b52a0a2c19f6092d836da7944ffe (patch) | |
| tree | 3e0b0011fbd0d1ef42331492b05557de08715b94 /src | |
| parent | 8db46a12062bdf7ec85807965b3cbf6a1fc98a94 (diff) | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/gdu/gdu-linux-md-drive.c | 148 | ||||
| -rw-r--r-- | src/gdu/gdu-pool.c | 33 | ||||
| -rw-r--r-- | src/gdu/gdu-private.h | 3 | ||||
| -rw-r--r-- | src/gdu/gdu-volume-hole.c | 8 | ||||
| -rw-r--r-- | src/palimpsest/gdu-section-create-partition-table.c | 4 | ||||
| -rw-r--r-- | src/palimpsest/gdu-section-linux-md-drive.c | 26 | ||||
| -rw-r--r-- | 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); } |
