void storage_volume_group_update (StorageVolumeGroup *self, gboolean ignore_locks, StorageVolumeGroupCallback *done, gpointer done_user_data) { struct UpdateData *data; const gchar *args[6]; int i; i = 0; args[i++] = STORAGED_HELPER_EXEC_NAME; args[i++] = "-b"; if (ignore_locks) args[i++] = "-f"; args[i++] = "show"; args[i++] = self->name; args[i++] = NULL; data = g_new0 (struct UpdateData, 1); data->self = g_object_ref (self); data->done = done; data->done_user_data = done_user_data; storage_daemon_spawn_for_variant (storage_daemon_get (), args, G_VARIANT_TYPE ("a{sv}"), update_with_variant, data); }
void storage_block_update_pv (StorageBlock *self, StorageVolumeGroup *group, GVariant *pv_info) { StorageDaemon *daemon; g_return_if_fail (STORAGE_IS_BLOCK (self)); daemon = storage_daemon_get (); if (group) { if (self->iface_physical_volume == NULL) { self->iface_physical_volume = storage_physical_volume_new (); storage_physical_volume_update (self->iface_physical_volume, group, pv_info); storage_daemon_publish (daemon, storage_block_get_object_path (self), FALSE, self->iface_physical_volume); } else { storage_physical_volume_update (self->iface_physical_volume, group, pv_info); } } else { if (self->iface_physical_volume != NULL) { storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_physical_volume); g_object_unref (self->iface_physical_volume); self->iface_physical_volume = NULL; } } }
static void storage_volume_group_dispose (GObject *obj) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (obj); GHashTableIter iter; const gchar *path; gpointer value; self->need_publish = FALSE; /* Dispose all the volumes, should unpublish */ g_hash_table_iter_init (&iter, self->logical_volumes); while (g_hash_table_iter_next (&iter, NULL, &value)) g_object_run_dispose (value); g_hash_table_remove_all (self->logical_volumes); g_hash_table_remove_all (self->physical_volumes); if (self->info) { g_variant_unref (self->info); self->info = NULL; } update_all_blocks (self); path = storage_volume_group_get_object_path (self); if (path != NULL) storage_daemon_unpublish (storage_daemon_get (), path, self); G_OBJECT_CLASS (storage_volume_group_parent_class)->dispose (obj); }
static gboolean handle_create_thin_volume (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *arg_name, guint64 arg_size, const gchar *arg_pool, GVariant *options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); CompleteClosure *complete; StorageJob *job; StorageDaemon *daemon; StorageLogicalVolume *pool; gchar *size; daemon = storage_daemon_get (); pool = storage_daemon_find_thing (daemon, arg_pool, STORAGE_TYPE_LOGICAL_VOLUME); if (pool == NULL) { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "Not a valid logical volume"); return TRUE; } arg_size -= arg_size % 512; size = g_strdup_printf ("%" G_GUINT64_FORMAT "b", arg_size); job = storage_daemon_launch_spawned_job (daemon, self, "lvm-vg-create-volume", storage_invocation_get_caller_uid (invocation), NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ NULL, /* input_string */ "lvcreate", storage_volume_group_get_name (self), "--thinpool", storage_logical_volume_get_name (pool), "-V", size, "-n", arg_name, NULL); complete = g_new0 (CompleteClosure, 1); complete->invocation = g_object_ref (invocation); complete->wait_thing = g_object_ref (self); complete->wait_name = g_strdup (arg_name); /* Wait for the job to finish */ g_signal_connect (job, "completed", G_CALLBACK (on_create_complete), complete); /* Wait for the object to appear */ complete->wait_sig = g_signal_connect_data (daemon, "published::StorageLogicalVolume", G_CALLBACK (on_create_logical_volume), complete, complete_closure_free, 0); g_free (size); g_object_unref (pool); return TRUE; }
static gboolean handle_add_device (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *new_member_device_objpath, GVariant *options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); StorageJob *job; StorageDaemon *daemon; StorageManager *manager; GError *error = NULL; StorageBlock *new_member_device = NULL; daemon = storage_daemon_get (); manager = storage_daemon_get_manager (daemon); new_member_device = storage_manager_find_block (manager, new_member_device_objpath); if (new_member_device == NULL) { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "The given object is not a valid block"); } else if (!storage_block_is_unused (new_member_device, &error)) { g_dbus_method_invocation_take_error (invocation, error); } else if (!storage_util_wipe_block (storage_block_get_device (new_member_device), &error)) { g_dbus_method_invocation_take_error (invocation, error); } else { job = storage_daemon_launch_spawned_job (daemon, self, "lvm-vg-add-device", storage_invocation_get_caller_uid (invocation), NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ NULL, /* input_string */ "vgextend", storage_volume_group_get_name (self), storage_block_get_device (new_member_device), NULL); g_signal_connect_data (job, "completed", G_CALLBACK (on_adddev_complete), g_object_ref (invocation), (GClosureNotify)g_object_unref, 0); } g_clear_object (&new_member_device); return TRUE; /* returning TRUE means that we handled the method invocation */ }
static gboolean handle_create_plain_volume (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *arg_name, guint64 arg_size, GVariant *options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); CompleteClosure *complete; StorageJob *job; StorageDaemon *daemon; GPtrArray *argv; daemon = storage_daemon_get (); arg_size -= arg_size % 512; argv = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (argv, g_strdup ("lvcreate")); g_ptr_array_add (argv, g_strdup (storage_volume_group_get_name (self))); g_ptr_array_add (argv, g_strdup_printf ("-L%" G_GUINT64_FORMAT "b", arg_size)); g_ptr_array_add (argv, g_strdup ("-n")); g_ptr_array_add (argv, g_strdup (arg_name)); g_ptr_array_add (argv, NULL); job = storage_daemon_launch_spawned_jobv (daemon, self, "lvm-vg-create-volume", storage_invocation_get_caller_uid (invocation), NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ NULL, /* input_string */ (const gchar **)argv->pdata); complete = g_new0 (CompleteClosure, 1); complete->invocation = g_object_ref (invocation); complete->wait_thing = g_object_ref (self); complete->wait_name = g_strdup (arg_name); /* Wait for the job to finish */ g_signal_connect (job, "completed", G_CALLBACK (on_create_complete), complete); /* Wait for the object to appear */ complete->wait_sig = g_signal_connect_data (daemon, "published::StorageLogicalVolume", G_CALLBACK (on_create_logical_volume), complete, complete_closure_free, 0); g_ptr_array_free (argv, TRUE); return TRUE; }
static gboolean handle_delete (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, gboolean arg_wipe, GVariant *arg_options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); VolumeGroupDeleteJobData *data; StorageDaemon *daemon; StorageJob *job; GList *l; daemon = storage_daemon_get (); data = g_new0 (VolumeGroupDeleteJobData, 1); data->vgname = g_strdup (storage_volume_group_get_name (self)); /* Find physical volumes to wipe. */ if (arg_wipe) { GPtrArray *devices = g_ptr_array_new (); GList *blocks = storage_manager_get_blocks (storage_daemon_get_manager (daemon)); for (l = blocks; l; l = l->next) { LvmPhysicalVolumeBlock *physical_volume; physical_volume = storage_block_get_physical_volume_block (l->data); if (physical_volume && g_strcmp0 (lvm_physical_volume_block_get_volume_group (physical_volume), storage_volume_group_get_object_path (self)) == 0) g_ptr_array_add (devices, g_strdup (storage_block_get_device (l->data))); } g_list_free_full (blocks, g_object_unref); g_ptr_array_add (devices, NULL); data->devices = (gchar **)g_ptr_array_free (devices, FALSE); } job = storage_daemon_launch_threaded_job (daemon, self, "lvm-vg-delete", storage_invocation_get_caller_uid (invocation), volume_group_delete_job_thread, data, volume_group_delete_job_free, NULL); g_signal_connect_data (job, "completed", G_CALLBACK (on_delete_complete), g_object_ref (invocation), (GClosureNotify)g_object_unref, 0); return TRUE; }
static void on_rename_complete (UDisksJob *job, gboolean success, gchar *message, gpointer user_data) { CompleteClosure *complete = user_data; if (success) return; g_dbus_method_invocation_return_error (complete->invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "Error renaming volume group: %s", message); g_signal_handler_disconnect (storage_daemon_get (), complete->wait_sig); }
static void poll_now (StorageVolumeGroup *self) { const gchar *args[] = { STORAGED_HELPER_EXEC_NAME, "-b", "show", self->name, NULL }; self->poll_timeout_id = g_timeout_add (5000, poll_timeout, g_object_ref (self)); if (self->poll_pid) kill (self->poll_pid, SIGINT); self->poll_pid = storage_daemon_spawn_for_variant (storage_daemon_get (), args, G_VARIANT_TYPE ("a{sv}"), poll_with_variant, g_object_ref (self)); }
static gboolean handle_remove_device (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *member_device_objpath, gboolean wipe, GVariant *options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); VolumeGroupRemdevJobData *data; StorageDaemon *daemon; StorageManager *manager; StorageBlock *member_device; StorageJob *job; daemon = storage_daemon_get (); manager = storage_daemon_get_manager (daemon); member_device = storage_manager_find_block (manager, member_device_objpath); if (member_device == NULL) { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "The given object is not a valid block"); return TRUE; } data = g_new0 (VolumeGroupRemdevJobData, 1); data->wipe = wipe; data->vgname = g_strdup (storage_volume_group_get_name (self)); data->pvname = g_strdup (storage_block_get_device (member_device)); job = storage_daemon_launch_threaded_job (daemon, self, "lvm-vg-rem-device", storage_invocation_get_caller_uid (invocation), volume_group_remdev_job_thread, data, volume_group_remdev_job_free, NULL); g_signal_connect_data (job, "completed", G_CALLBACK (on_remdev_complete), g_object_ref (invocation), (GClosureNotify)g_object_unref, 0); g_object_unref (member_device); return TRUE; /* returning TRUE means that we handled the method invocation */ }
static gboolean handle_empty_device (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *member_device_objpath, GVariant *options) { StorageJob *job; StorageDaemon *daemon; StorageManager *manager; const gchar *member_device_file = NULL; StorageBlock *member_device = NULL; daemon = storage_daemon_get (); manager = storage_daemon_get_manager (daemon); member_device = storage_manager_find_block (manager, member_device_objpath); if (member_device == NULL) { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "The given object is not a valid block"); return TRUE; } member_device_file = storage_block_get_device (member_device); job = storage_daemon_launch_spawned_job (daemon, member_device, "lvm-vg-empty-device", storage_invocation_get_caller_uid (invocation), NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ NULL, /* input_string */ "pvmove", member_device_file, NULL); g_signal_connect_data (job, "completed", G_CALLBACK (on_empty_complete), g_object_ref (invocation), (GClosureNotify)g_object_unref, 0); g_object_unref (member_device); return TRUE; /* returning TRUE means that we handled the method invocation */ }
static gboolean handle_rename (LvmVolumeGroup *group, GDBusMethodInvocation *invocation, const gchar *new_name, GVariant *options) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); CompleteClosure *complete; StorageJob *job; StorageDaemon *daemon; daemon = storage_daemon_get (); job = storage_daemon_launch_spawned_job (daemon, self, "lvm-vg-rename", storage_invocation_get_caller_uid (invocation), NULL, /* GCancellable */ 0, /* uid_t run_as_uid */ 0, /* uid_t run_as_euid */ NULL, /* input_string */ "vgrename", storage_volume_group_get_name (self), new_name, NULL); complete = g_new0 (CompleteClosure, 1); complete->invocation = g_object_ref (invocation); complete->wait_name = g_strdup (new_name); /* Wait for the job to finish */ g_signal_connect (job, "completed", G_CALLBACK (on_rename_complete), complete); /* Wait for the object to appear */ complete->wait_sig = g_signal_connect_data (daemon, "published::StorageVolumeGroup", G_CALLBACK (on_rename_volume_group), complete, complete_closure_free, 0); return TRUE; }
void storage_block_update_lv (StorageBlock *self, StorageLogicalVolume *lv) { const gchar *logical_volume_path; StorageDaemon *daemon; g_return_if_fail (STORAGE_IS_BLOCK (self)); daemon = storage_daemon_get (); if (lv == NULL) { if (self->iface_logical_volume) { storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_logical_volume); g_object_unref (self->iface_logical_volume); self->iface_logical_volume = NULL; } } else { logical_volume_path = storage_logical_volume_get_object_path (lv); if (self->iface_logical_volume) { lvm_logical_volume_block_set_logical_volume (self->iface_logical_volume, logical_volume_path); } else { self->iface_logical_volume = lvm_logical_volume_block_skeleton_new (); lvm_logical_volume_block_set_logical_volume (self->iface_logical_volume, logical_volume_path); storage_daemon_publish (daemon, storage_block_get_object_path (self), FALSE, self->iface_logical_volume); } } }
static void storage_block_dispose (GObject *object) { StorageBlock *self = STORAGE_BLOCK (object); StorageDaemon *daemon; daemon = storage_daemon_get (); if (self->iface_physical_volume) { storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_physical_volume); g_object_unref (self->iface_physical_volume); self->iface_physical_volume = NULL; } if (self->iface_logical_volume) { storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_logical_volume); g_object_unref (self->iface_logical_volume); self->iface_logical_volume = NULL; } G_OBJECT_CLASS (storage_block_parent_class)->dispose (object); }
static void update_with_variant (GPid pid, GVariant *info, GError *error, gpointer user_data) { struct UpdateData *data = user_data; StorageVolumeGroup *self = data->self; GVariantIter *iter; GHashTableIter volume_iter; gpointer key, value; GHashTable *new_lvs; gboolean needs_polling = FALSE; StorageDaemon *daemon; gchar *path; daemon = storage_daemon_get (); if (!error) volume_group_update_props (self, info, &needs_polling); /* After basic props, publish group, if not already done */ if (self->need_publish) { self->need_publish = FALSE; path = storage_util_build_object_path ("/org/freedesktop/UDisks2/lvm", storage_volume_group_get_name (self), NULL); storage_daemon_publish (daemon, path, FALSE, self); g_free (path); } if (error) { g_message ("Failed to update LVM volume group %s: %s", storage_volume_group_get_name (self), error->message); g_object_unref (self); return; } if (self->info && g_variant_equal (self->info, info)) { g_debug ("%s updated without changes", self->name); g_object_unref (self); return; } if (self->info) g_variant_unref (self->info); self->info = g_variant_ref (info); new_lvs = g_hash_table_new (g_str_hash, g_str_equal); if (g_variant_lookup (info, "lvs", "aa{sv}", &iter)) { GVariant *lv_info = NULL; while (g_variant_iter_loop (iter, "@a{sv}", &lv_info)) { const gchar *name; StorageLogicalVolume *volume; g_variant_lookup (lv_info, "name", "&s", &name); update_operations (name, lv_info, &needs_polling); if (lv_is_pvmove_volume (name)) needs_polling = TRUE; if (!lv_is_visible (name)) continue; volume = g_hash_table_lookup (self->logical_volumes, name); if (volume == NULL) { volume = storage_logical_volume_new (self, name); storage_logical_volume_update (volume, self, lv_info, &needs_polling); g_hash_table_insert (self->logical_volumes, g_strdup (name), g_object_ref (volume)); } else storage_logical_volume_update (volume, self, lv_info, &needs_polling); g_hash_table_insert (new_lvs, (gchar *)name, volume); } g_variant_iter_free (iter); } g_hash_table_iter_init (&volume_iter, self->logical_volumes); while (g_hash_table_iter_next (&volume_iter, &key, &value)) { const gchar *name = key; StorageLogicalVolume *volume = value; if (!g_hash_table_contains (new_lvs, name)) { /* Volume unpublishes itself */ g_object_run_dispose (G_OBJECT (volume)); g_hash_table_iter_remove (&volume_iter); } } lvm_volume_group_set_needs_polling (LVM_VOLUME_GROUP (self), needs_polling); /* Update physical volumes. */ g_hash_table_remove_all (self->physical_volumes); if (g_variant_lookup (info, "pvs", "aa{sv}", &iter)) { const gchar *name; GVariant *pv_info; while (g_variant_iter_next (iter, "@a{sv}", &pv_info)) { if (g_variant_lookup (pv_info, "device", "&s", &name)) g_hash_table_insert (self->physical_volumes, g_strdup (name), pv_info); else g_variant_unref (pv_info); } } /* Make sure above is published before updating blocks to point at volume group */ update_all_blocks (self); if (data->done) data->done (self, data->done_user_data); g_hash_table_destroy (new_lvs); g_object_unref (self); g_free (data); }
static void update_progress_for_device (const gchar *operation, const gchar *dev, double progress) { StorageDaemon *daemon; StorageManager *manager; GList *jobs, *l; daemon = storage_daemon_get (); manager = storage_daemon_get_manager (daemon); jobs = storage_daemon_get_jobs (daemon); for (l = jobs; l; l = g_list_next (l)) { UDisksJob *job = l->data; const gchar *const *job_objects; int i; if (g_strcmp0 (udisks_job_get_operation (job), operation) != 0) continue; job_objects = udisks_job_get_objects (job); for (i = 0; job_objects[i]; i++) { StorageBlock *block; gboolean found = FALSE; block = storage_manager_find_block (manager, job_objects[i]); if (block) { if (g_strcmp0 (storage_block_get_device (block), dev) == 0) { found = TRUE; } else { const gchar **symlinks; int j; symlinks = storage_block_get_symlinks (block); for (j = 0; symlinks[j]; j++) { if (g_strcmp0 (symlinks[j], dev) == 0) { found = TRUE; break; } } } } if (found) { udisks_job_set_progress (job, progress); udisks_job_set_progress_valid (job, TRUE); } } } g_list_free_full (jobs, g_object_unref); }