예제 #1
0
파일: lvscan.c 프로젝트: ErisBlastar/osfree
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)) {
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
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;
}
예제 #6
0
/* 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;
}
예제 #7
0
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;
}
예제 #8
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);
}
예제 #9
0
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);
}