struct dm_list *tag_list_copy(struct dm_pool *p, struct dm_list *tag_list)
{
	struct dm_list *list;
	lvm_str_list_t *lsl;
	struct str_list *sl;

	if (!(list = dm_pool_zalloc(p, sizeof(*list)))) {
		log_errno(ENOMEM, "Memory allocation fail for dm_list.");
		return NULL;
	}
	dm_list_init(list);

	dm_list_iterate_items(sl, tag_list) {
		if (!(lsl = dm_pool_zalloc(p, sizeof(*lsl)))) {
			log_errno(ENOMEM,
				"Memory allocation fail for lvm_lv_list.");
			return NULL;
		}
		if (!(lsl->str = dm_pool_strdup(p, sl->str))) {
			log_errno(ENOMEM,
				"Memory allocation fail for lvm_lv_list->str.");
			return NULL;
		}
		dm_list_add(list, &lsl->list);
	}
	return list;
}
Ejemplo n.º 2
0
static int _detach_pvmove_mirror(struct cmd_context *cmd,
				 struct logical_volume *lv_mirr)
{
	uint32_t mimage_to_remove = 0;
	struct dm_list lvs_completed;
	struct lv_list *lvl;

	/* Update metadata to remove mirror segments and break dependencies */
	dm_list_init(&lvs_completed);

	if (arg_is_set(cmd, abort_ARG) &&
	    (seg_type(first_seg(lv_mirr), 0) == AREA_LV))
		mimage_to_remove = 1; /* remove the second mirror leg */

	if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, _is_pvmove_image_removable, &mimage_to_remove, PVMOVE) ||
	    !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
					    &lvs_completed)) {
		return 0;
	}

	dm_list_iterate_items(lvl, &lvs_completed)
		/* FIXME Assumes only one pvmove at a time! */
		lvl->lv->status &= ~LOCKED;

	return 1;
}
Ejemplo n.º 3
0
int pvremove(struct cmd_context *cmd, int argc, char **argv)
{
	int i;
	unsigned force_count;
	unsigned prompt;
	struct dm_list pv_names;

	if (!argc) {
		log_error("Please enter a physical volume path");
		return EINVALID_CMD_LINE;
	}

	force_count = arg_count(cmd, force_ARG);
	prompt = arg_count(cmd, yes_ARG);

	dm_list_init(&pv_names);

	/* Needed to change the set of orphan PVs. */
	if (!lockd_gl(cmd, "ex", 0))
		return_ECMD_FAILED;

	for (i = 0; i < argc; i++) {
		dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
		if (!str_list_add(cmd->mem, &pv_names, argv[i]))
			return_ECMD_FAILED;
	}

	if (!pvremove_many(cmd, &pv_names, force_count, prompt))
		return_ECMD_FAILED;

	return ECMD_PROCESSED;
}
Ejemplo n.º 4
0
static struct cb_set *_cb_set_create(unsigned nr)
{
	int i;
	struct cb_set *cbs = malloc(sizeof(*cbs));

	if (!cbs)
		return NULL;

	cbs->vec = malloc(nr * sizeof(*cbs->vec));
	if (!cbs->vec) {
		free(cbs);
		return NULL;
	}

	dm_list_init(&cbs->free);
	dm_list_init(&cbs->allocated);

	for (i = 0; i < nr; i++)
		dm_list_add(&cbs->free, &cbs->vec[i].list);

	return cbs;
}
Ejemplo n.º 5
0
static void __update_lvmcache(const struct format_type *fmt,
			      struct disk_list *dl,
			      struct device *dev, const char *vgid,
			      unsigned exported)
{
	struct lvmcache_info *info;
	const char *vgname = *((char *)dl->pvd.vg_name) ?
			     (char *)dl->pvd.vg_name : fmt->orphan_vg_name;

	if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
				  vgname, vgid, exported ? EXPORTED_VG : 0))) {
		stack;
		return;
	}

	info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
	dm_list_init(&info->mdas);
	info->status &= ~CACHE_INVALID;
}
Ejemplo n.º 6
0
static struct replicator_site *_get_site(struct logical_volume *replicator,
					 const char *key)
{
	struct dm_pool *mem = replicator->vg->vgmem;
	struct replicator_site *rsite;

	dm_list_iterate_items(rsite, &replicator->rsites)
		if (strcasecmp(rsite->name, key) == 0)
			return rsite;

	if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
		return_NULL;

	if (!(rsite->name = dm_pool_strdup(mem, key)))
		return_NULL;

	rsite->replicator = replicator;
	dm_list_init(&rsite->rdevices);
	dm_list_add(&replicator->rsites, &rsite->list);

	return rsite;
}
Ejemplo n.º 7
0
/* Allocate/free the status structure for a monitoring thread. */
static struct thread_status *_alloc_thread_status(struct message_data *data,
						  struct dso_data *dso_data)
{
	struct thread_status *ret = (typeof(ret)) dm_malloc(sizeof(*ret));

	if (!ret)
		return NULL;

	memset(ret, 0, sizeof(*ret));
	if (!(ret->device.uuid = dm_strdup(data->device_uuid))) {
		dm_free(ret);
		return NULL;
	}

	ret->current_task = NULL;
	ret->device.name = NULL;
	ret->device.major = ret->device.minor = 0;
	ret->dso_data = dso_data;
	ret->events = data->events.field;
	ret->timeout = data->timeout.secs;
	dm_list_init(&ret->timeout_list);

	return ret;
}
Ejemplo n.º 8
0
void internal_filter_clear(void)
{
	dm_list_init(&_allow_devs);
}
Ejemplo n.º 9
0
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
	      struct device *dev, struct volume_group *vg,
	      struct physical_volume *pv, struct pv_disk *pvd,
	      struct vg_disk *vgd)
{
	uint64_t size;

	memset(pv, 0, sizeof(*pv));
	memcpy(&pv->id, pvd->pv_uuid, ID_LEN);

	pv->dev = dev;
	if (!*pvd->vg_name)
		pv->vg_name = fmt->orphan_vg_name;
	else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
		log_error("Volume Group name allocation failed.");
		return 0;
	}

	memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));

	/* Store system_id from first PV if PV belongs to a VG */
	if (vg && !*vg->lvm1_system_id)
		strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN);

	if (vg &&
	    strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
		    log_very_verbose("System ID %s on %s differs from %s for "
				     "volume group", pvd->system_id,
				     pv_dev_name(pv), vg->lvm1_system_id);

	/*
	 * If exported, we still need to flag in pv->status too because
	 * we don't always have a struct volume_group when we need this.
	 */
	if (pvd->pv_status & VG_EXPORTED)
		pv->status |= EXPORTED_VG;

	if (pvd->pv_allocatable)
		pv->status |= ALLOCATABLE_PV;

	pv->size = pvd->pv_size;
	pv->pe_size = pvd->pe_size;
	pv->pe_start = pvd->pe_start;
	pv->pe_count = pvd->pe_total;
	pv->pe_alloc_count = 0;
	pv->pe_align = 0;
        pv->is_labelled = 0; /* format1 PVs have no label */
        pv->label_sector = 0;

	/* Fix up pv size if missing or impossibly large */
	if (!pv->size || pv->size > (1ULL << 62)) {
		if (!dev_get_size(dev, &pv->size)) {
			log_error("%s: Couldn't get size.", pv_dev_name(pv));
			return 0;
		}
		log_verbose("Fixing up missing format1 size (%s) "
			    "for PV %s", display_size(fmt->cmd, pv->size),
			    pv_dev_name(pv));
		if (vg) {
			size = pv->pe_count * (uint64_t) vg->extent_size +
			       pv->pe_start;
			if (size > pv->size)
				log_warn("WARNING: Physical Volume %s is too "
					 "large for underlying device",
					 pv_dev_name(pv));
		}
	}

	dm_list_init(&pv->tags);
	dm_list_init(&pv->segments);

	if (!alloc_pv_segment_whole_pv(mem, pv))
		return_0;

	return 1;
}
Ejemplo n.º 10
0
static int _pv_resize_single(struct cmd_context *cmd,
			     struct volume_group *vg,
			     struct physical_volume *pv,
			     const uint64_t new_size)
{
	struct pv_list *pvl;
	uint64_t size = 0;
	uint32_t new_pe_count = 0;
	int r = 0;
	struct dm_list mdas;
	const char *pv_name = pv_dev_name(pv);
	const char *vg_name;
	struct lvmcache_info *info;
	int mda_count = 0;
	struct volume_group *old_vg = vg;

	dm_list_init(&mdas);

	if (is_orphan_vg(pv_vg_name(pv))) {
		vg_name = VG_ORPHANS;
		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
			log_error("Can't get lock for orphans");
			return 0;
		}

		if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
			unlock_vg(cmd, vg_name);
			log_error("Unable to read PV \"%s\"", pv_name);
			return 0;
		}

		mda_count = dm_list_size(&mdas);
	} else {
		vg_name = pv_vg_name(pv);

		vg = vg_read_for_update(cmd, vg_name, NULL, 0);

		if (vg_read_error(vg))
			goto bad;

		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
			log_error("Unable to find \"%s\" in volume group \"%s\"",
				  pv_name, vg->name);
			goto bad;
		}

		pv = pvl->pv;

		if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
			log_error("Can't get info for PV %s in volume group %s",
				  pv_name, vg->name);
			goto bad;
		}

		mda_count = dm_list_size(&info->mdas);

		if (!archive(vg))
			goto bad;
	}

	/* FIXME Create function to test compatibility properly */
	if (mda_count > 1) {
		log_error("%s: too many metadata areas for pvresize", pv_name);
		goto bad;
	}

	if (!(pv->fmt->features & FMT_RESIZE_PV)) {
		log_error("Physical volume %s format does not support resizing.",
			  pv_name);
		goto bad;
	}

	/* Get new size */
	if (!dev_get_size(pv_dev(pv), &size)) {
		log_error("%s: Couldn't get size.", pv_name);
		goto bad;
	}

	if (new_size) {
		if (new_size > size)
			log_warn("WARNING: %s: Overriding real size. "
				  "You could lose data.", pv_name);
		log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
			    " sectors.", pv_name, new_size, pv_size(pv));
		size = new_size;
	}

	if (size < PV_MIN_SIZE) {
		log_error("%s: Size must exceed minimum of %ld sectors.",
			  pv_name, PV_MIN_SIZE);
		goto bad;
	}

	if (size < pv_pe_start(pv)) {
		log_error("%s: Size must exceed physical extent start of "
			  "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv));
		goto bad;
	}

	pv->size = size;

	if (vg) {
		pv->size -= pv_pe_start(pv);
		new_pe_count = pv_size(pv) / vg->extent_size;

 		if (!new_pe_count) {
			log_error("%s: Size must leave space for at "
				  "least one physical extent of "
				  "%" PRIu32 " sectors.", pv_name,
				  pv_pe_size(pv));
			goto bad;
		}

		if (!pv_resize(pv, vg, new_pe_count))
			goto_bad;
	}

	log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
		    pv_name, pv_size(pv));

	log_verbose("Updating physical volume \"%s\"", pv_name);
	if (!is_orphan_vg(pv_vg_name(pv))) {
		if (!vg_write(vg) || !vg_commit(vg)) {
			log_error("Failed to store physical volume \"%s\" in "
				  "volume group \"%s\"", pv_name, vg->name);
			goto bad;
		}
		backup(vg);
	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
		log_error("Failed to store physical volume \"%s\"",
			  pv_name);
		goto bad;;
	}

	log_print("Physical volume \"%s\" changed", pv_name);
	r = 1;

bad:
	unlock_vg(cmd, vg_name);
	if (!old_vg)
		vg_release(vg);
	return r;
}
Ejemplo n.º 11
0
/* Real locking */
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
{
	/* DLM table of allowed transition states */
	static const int _dlm_table[6][6] = {
	/* Mode	   NL	CR	CW	PR	PW	EX */
	/* NL */ { 1,	 1,	 1,	 1,	 1,	 1},
	/* CR */ { 1,	 1,	 1,	 1,	 1,	 0},
	/* CW */ { 1,	 1,	 1,	 0,	 0,	 0},
	/* PR */ { 1,	 1,	 0,	 1,	 0,	 0},
	/* PW */ { 1,	 1,	 0,	 0,	 0,	 0},
	/* EX */ { 1,	 0,	 0,	 0,	 0,	 0}
	};

	struct lock *lck = NULL, *lckt;
	struct dm_list *head;

	DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
		 resource, flags,
		 (flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
		 ((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
		  (LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
		 (flags & LCKF_CONVERT) ? "CONVERT" : "",
		 _get_mode(mode), mode);

	mode &= LCK_TYPE_MASK;
	pthread_mutex_lock(&_lock_mutex);

retry:
	pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */

	if (!(head = dm_hash_lookup(_locks, resource))) {
		if (flags & LCKF_CONVERT) {
			/* In real DLM, lock is identified only by lockid, resource is not used */
			DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
			goto_bad;
		}
		/* Add new locked resource */
		if (!(head = dm_malloc(sizeof(struct dm_list))) ||
		    !dm_hash_insert(_locks, resource, head)) {
			dm_free(head);
			goto_bad;
		}

		dm_list_init(head);
	} else	/* Update/convert locked resource */
		dm_list_iterate_items(lck, head) {
			/* Check is all locks are compatible with requested lock */
			if (flags & LCKF_CONVERT) {
				if (lck->lockid != *lockid)
					continue;

				DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
					 resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
				dm_list_iterate_items(lckt, head) {
					if ((lckt->lockid != *lockid) &&
					    !_dlm_table[mode][lckt->mode]) {
						if (!(flags & LCKF_NOQUEUE) &&
						    /* TODO: Real dlm uses here conversion queues */
						    !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
						    _locks) /* End of the game? */
							goto retry;
						goto bad;
					}
				}
				lck->mode = mode; /* Lock is now converted */
				goto out;
			} else if (!_dlm_table[mode][lck->mode]) {
				DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
					 resource, lck->lockid, _get_mode(lck->mode));
				if (!(flags & LCKF_NOQUEUE) &&
				    !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
				    _locks) { /* End of the game? */
					DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
						 resource, _get_mode(mode));
					goto retry;
				}
				goto bad;
			}
		}
Ejemplo n.º 12
0
/*
 * Decide whether it is "safe" to wipe the labels on this device.
 * 0 indicates we may not.
 */
static int pvremove_check(struct cmd_context *cmd, const char *name)
{
	struct physical_volume *pv;
	struct dm_list mdas;

	dm_list_init(&mdas);

	/* FIXME Check partition type is LVM unless --force is given */

	/* Is there a pv here already? */
	/* If not, this is an error unless you used -f. */
	if (!(pv = pv_read(cmd, name, &mdas, NULL, 1, 0))) {
		if (arg_count(cmd, force_ARG))
			return 1;
		log_error("Physical Volume %s not found", name);
		return 0;
	}

	/*
	 * If a PV has no MDAs it may appear to be an
	 * orphan until the metadata is read off
	 * another PV in the same VG.  Detecting this
	 * means checking every VG by scanning every
	 * PV on the system.
	 */
	if (is_orphan(pv) && !dm_list_size(&mdas)) {
		if (!scan_vgs_for_pvs(cmd)) {
			log_error("Rescan for PVs without metadata areas "
				  "failed.");
			return 0;
		}
		if (!(pv = pv_read(cmd, name, NULL, NULL, 1, 0))) {
			log_error("Failed to read physical volume %s", name);
			return 0;
		}
	}

	/* orphan ? */
	if (is_orphan(pv))
		return 1;

	/* Allow partial & exported VGs to be destroyed. */
	/* we must have -ff to overwrite a non orphan */
	if (arg_count(cmd, force_ARG) < 2) {
		log_error("Can't pvremove physical volume \"%s\" of "
			  "volume group \"%s\" without -ff", name, pv_vg_name(pv));
		return 0;
	}

	/* prompt */
	if (!arg_count(cmd, yes_ARG) &&
	    yes_no_prompt(_really_wipe, name, pv_vg_name(pv)) == 'n') {
		log_error("%s: physical volume label not removed", name);
		return 0;
	}

	if (arg_count(cmd, force_ARG)) {
		log_warn("WARNING: Wiping physical volume label from "
			  "%s%s%s%s", name,
			  !is_orphan(pv) ? " of volume group \"" : "",
			  !is_orphan(pv) ? pv_vg_name(pv) : "",
			  !is_orphan(pv) ? "\"" : "");
	}

	return 1;
}
Ejemplo n.º 13
0
static struct disk_list *__read_disk(const struct format_type *fmt,
				     struct device *dev, struct dm_pool *mem,
				     const char *vg_name)
{
	struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
	const char *name = dev_name(dev);

	if (!dl)
		return_NULL;

	dl->dev = dev;
	dl->mem = mem;
	dm_list_init(&dl->uuids);
	dm_list_init(&dl->lvds);

	if (!_read_pvd(dev, &dl->pvd))
		goto_bad;

	/*
	 * is it an orphan ?
	 */
	if (!*dl->pvd.vg_name) {
		log_very_verbose("%s is not a member of any format1 VG", name);

		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
		return (vg_name) ? NULL : dl;
	}

	if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
		log_error("Failed to read VG data from PV (%s)", name);
		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
		goto bad;
	}

	if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
		log_very_verbose("%s is not a member of the VG %s",
				 name, vg_name);
		__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
		goto bad;
	}

	__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
			  dl->vgd.vg_status & VG_EXPORTED);

	if (!_read_uuids(dl)) {
		log_error("Failed to read PV uuid list from %s", name);
		goto bad;
	}

	if (!_read_lvs(dl)) {
		log_error("Failed to read LV's from %s", name);
		goto bad;
	}

	if (!_read_extents(dl)) {
		log_error("Failed to read extents from %s", name);
		goto bad;
	}

	log_very_verbose("Found %s in %sVG %s", name,
			 (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
			 dl->pvd.vg_name);

	return dl;

      bad:
	dm_pool_free(dl->mem, dl);
	return NULL;
}