static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) // __attribute((unused))) { struct lvinfo info; int lv_total = 0; uint64_t lv_capacity_total = 0; int inkernel, snap_active = 1; struct lv_segment *snap_seg = NULL; float snap_percent; /* fused, fsize; */ const char *active_str, *snapshot_str; if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) return ECMD_PROCESSED; inkernel = lv_info(cmd, lv, &info, 1) && info.exists; if (lv_is_origin(lv)) { list_iterate_items_gen(snap_seg, struct lv_segment, &lv->snapshot_segs, origin_list) { if (inkernel && (snap_active = lv_snapshot_percent(snap_seg->cow, &snap_percent))) if (snap_percent < 0 || snap_percent >= 100) snap_active = 0; } snap_seg = NULL; } else if (lv_is_cow(lv)) {
static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) return ECMD_PROCESSED; return process_each_segment_in_lv(cmd, lv, handle, _segs_single); }
static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) return ECMD_PROCESSED; if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL)) return ECMD_FAILED; return ECMD_PROCESSED; }
int lv_is_visible(const struct logical_volume *lv) { if (lv->status & SNAPSHOT) return 0; if (lv_is_cow(lv)) { if (lv_is_virtual_origin(origin_from_cow(lv))) return 1; return lv_is_visible(origin_from_cow(lv)); } return lv->status & VISIBLE_LV ? 1 : 0; }
static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) return ECMD_PROCESSED; if (arg_count(cmd, colon_ARG)) lvdisplay_colons(lv); else { lvdisplay_full(cmd, lv, handle); if (arg_count(cmd, maps_ARG)) lvdisplay_segments(lv); } return ECMD_PROCESSED; }
/* Check if given LV is usable as snapshot origin LV */ int validate_snapshot_origin(const struct logical_volume *origin_lv) { const char *err = NULL; /* For error string */ if (lv_is_cow(origin_lv)) err = "snapshots"; else if (lv_is_locked(origin_lv)) err = "locked volumes"; else if (lv_is_pvmove(origin_lv)) err = "pvmoved volumes"; else if (!lv_is_visible(origin_lv)) err = "hidden volumes"; else if (lv_is_merging_origin(origin_lv)) err = "an origin that has a merging snapshot"; else if (lv_is_cache_type(origin_lv) && !lv_is_cache(origin_lv)) err = "cache type volumes"; else if (lv_is_thin_type(origin_lv) && !lv_is_thin_volume(origin_lv)) err = "thin pool type volumes"; else if (lv_is_mirror_type(origin_lv)) { if (!lv_is_mirror(origin_lv)) err = "mirror subvolumes"; else { log_warn("WARNING: Snapshots of mirrors can deadlock under rare device failures."); log_warn("WARNING: Consider using the raid1 mirror type to avoid this."); log_warn("WARNING: See global/mirror_segtype_default in lvm.conf."); } } else if (lv_is_raid_type(origin_lv) && !lv_is_raid(origin_lv)) err = "raid subvolumes"; if (err) { log_error("Snapshots of %s are not supported.", err); return 0; } if (vg_is_clustered(origin_lv->vg) && lv_is_active(origin_lv) && !lv_is_active_exclusive_locally(origin_lv)) { log_error("Snapshot origin must be active exclusively."); return 0; } return 1; }
int lv_is_visible(const struct logical_volume *lv) { if (lv_is_historical(lv)) return 1; if (lv_is_snapshot(lv)) return 0; if (lv_is_cow(lv)) { if (lv_is_virtual_origin(origin_from_cow(lv))) return 1; if (lv_is_merging_cow(lv)) return 0; return lv_is_visible(origin_from_cow(lv)); } return lv->status & VISIBLE_LV ? 1 : 0; }
void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin, struct logical_volume *cow, uint32_t chunk_size) { seg->chunk_size = chunk_size; seg->origin = origin; seg->cow = cow; lv_set_hidden(cow); cow->snapshot = seg; origin->origin_count++; /* FIXME Assumes an invisible origin belongs to a sparse device */ if (!lv_is_visible(origin)) origin->status |= VIRTUAL_ORIGIN; seg->lv->status |= (SNAPSHOT | VIRTUAL); dm_list_add(&origin->snapshot_segs, &seg->origin_list); }
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); }