/* Decrement pdev and free allocated space. */
int
dm_target_snapshot_orig_destroy(dm_table_entry_t * table_en)
{
	dm_target_snapshot_origin_config_t *tsoc;

	/*
	 * Destroy function is called for every target even if it
	 * doesn't have target_config.
	 */

	if (table_en->target_config == NULL)
		return 0;

	tsoc = table_en->target_config;

	/* Decrement pdev ref counter if 0 remove it */
	dm_pdev_decr(tsoc->tsoc_real_dev);

	/* Unbusy target so we can unload it */
	dm_target_unbusy(table_en->target);

	kmem_free(table_en->target_config, sizeof(dm_target_snapshot_origin_config_t));

	table_en->target_config = NULL;

	return 0;
}
/* Doesn't do anything here. */
int
dm_target_snapshot_destroy(dm_table_entry_t * table_en)
{
	dm_target_snapshot_config_t *tsc;

	/*
	 * Destroy function is called for every target even if it
	 * doesn't have target_config.
	 */

	if (table_en->target_config == NULL)
		return 0;

	printf("Snapshot target destroy function called\n");

	tsc = table_en->target_config;

	/* Decrement pdev ref counter if 0 remove it */
	dm_pdev_decr(tsc->tsc_snap_dev);

	if (tsc->tsc_persistent_dev)
		dm_pdev_decr(tsc->tsc_cow_dev);

	/* Unbusy target so we can unload it */
	dm_target_unbusy(table_en->target);

	kmem_free(table_en->target_config, sizeof(dm_target_snapshot_config_t));

	table_en->target_config = NULL;

	return 0;
}
예제 #3
0
/*
 * Destroy target specific data. Decrement table pdevs.
 */
static int
dm_target_linear_destroy(dm_table_entry_t * table_en)
{
	dm_target_linear_config_t *tlc;

	/*
	 * Destroy function is called for every target even if it
	 * doesn't have target_config.
	 */

	if (table_en->target_config == NULL)
		return 0;

	tlc = table_en->target_config;

	/* Decrement pdev ref counter if 0 remove it */
	dm_pdev_decr(tlc->pdev);

	/* Unbusy target so we can unload it */
	dm_target_unbusy(table_en->target);

	kfree(table_en->target_config, M_DMLINEAR);

	table_en->target_config = NULL;

	return 0;
}
예제 #4
0
static int
dmtz_mod_handler(module_t mod, int type, void *unused)
{
	dm_target_t *dmt = NULL;
	int err = 0;

	switch(type) {
	case MOD_LOAD:
		if ((dmt = dm_target_lookup("zero")) != NULL) {
			dm_target_unbusy(dmt);
			return EEXIST;
		}
		dmt = dm_target_alloc("zero");
		dmt->version[0] = 1;
		dmt->version[1] = 0;
		dmt->version[2] = 0;
		dmt->strategy = &dm_target_zero_strategy;

		err = dm_target_insert(dmt);
		if (err == 0)
			kprintf("dm_target_zero: Successfully initialized\n");
		break;

	case MOD_UNLOAD:
		err = dm_target_remove("zero");
		if (err == 0)
			kprintf("dm_target_zero: unloaded\n");
		break;
	}

	return err;
}
예제 #5
0
/* Doesn't do anything here. */
static int
dm_target_error_destroy(dm_table_entry_t * table_en)
{
	table_en->target_config = NULL;

	/* Unbusy target so we can unload it */
	dm_target_unbusy(table_en->target);

	return 0;
}
예제 #6
0
static int
dmte_mod_handler(module_t mod, int type, void *unused)
{
	dm_target_t *dmt = NULL;
	int err = 0;

	switch(type) {
	case MOD_LOAD:
		if ((dmt = dm_target_lookup("error")) != NULL) {
			dm_target_unbusy(dmt);
			return EEXIST;
		}
		dmt = dm_target_alloc("error");
		dmt->version[0] = 1;
		dmt->version[1] = 0;
		dmt->version[2] = 0;
		strlcpy(dmt->name, "error", DM_MAX_TYPE_NAME);
		dmt->init = &dm_target_error_init;
		dmt->status = &dm_target_error_status;
		dmt->strategy = &dm_target_error_strategy;
		dmt->deps = &dm_target_error_deps;
		dmt->destroy = &dm_target_error_destroy;
		dmt->upcall = &dm_target_error_upcall;
		dmt->dump = NULL;

		err = dm_target_insert(dmt);
		if (err == 0)
			kprintf("dm_target_error: Successfully initialized\n");
		break;

	case MOD_UNLOAD:
		err = dm_target_rem("error");
		if (err == 0)
			kprintf("dm_target_error: unloaded\n");
		break;

	default:
		break;
	}

	return err;
}
static int
dm_target_snapshot_modcmd(modcmd_t cmd, void *arg)
{
	dm_target_t *dmt, *dmt1;
	int r;

	dmt = NULL;
	dmt1 = NULL;

	switch (cmd) {
	case MODULE_CMD_INIT:
		if (((dmt = dm_target_lookup("snapshot")) != NULL)) {
			dm_target_unbusy(dmt);
			return EEXIST;
		}
		if (((dmt = dm_target_lookup("snapshot-origin")) != NULL)) {
			dm_target_unbusy(dmt);
			return EEXIST;
		}
		dmt = dm_target_alloc("snapshot");
		dmt1 = dm_target_alloc("snapshot-origin");

		dmt->version[0] = 1;
		dmt->version[1] = 0;
		dmt->version[2] = 5;
		strlcpy(dmt->name, "snapshot", DM_MAX_TYPE_NAME);
		dmt->init = &dm_target_snapshot_init;
		dmt->status = &dm_target_snapshot_status;
		dmt->strategy = &dm_target_snapshot_strategy;
		dmt->deps = &dm_target_snapshot_deps;
		dmt->destroy = &dm_target_snapshot_destroy;
		dmt->upcall = &dm_target_snapshot_upcall;

		r = dm_target_insert(dmt);

		dmt1->version[0] = 1;
		dmt1->version[1] = 0;
		dmt1->version[2] = 5;
		strlcpy(dmt1->name, "snapshot-origin", DM_MAX_TYPE_NAME);
		dmt1->init = &dm_target_snapshot_orig_init;
		dmt1->status = &dm_target_snapshot_orig_status;
		dmt1->strategy = &dm_target_snapshot_orig_strategy;
		dmt1->sync = &dm_target_snapshot_orig_sync;
		dmt1->deps = &dm_target_snapshot_orig_deps;
		dmt1->destroy = &dm_target_snapshot_orig_destroy;
		dmt1->upcall = &dm_target_snapshot_orig_upcall;

		r = dm_target_insert(dmt1);
		break;

	case MODULE_CMD_FINI:
		/*
		 * Try to remove snapshot target if it works remove snap-origin
		 * it is not possible to remove snapshot and do not remove
		 * snap-origin because they are used together.
		 */
		if ((r = dm_target_rem("snapshot")) == 0)
			r = dm_target_rem("snapshot-origin");

		break;

	case MODULE_CMD_STAT:
		return ENOTTY;

	default:
		return ENOTTY;
	}

	return r;
}
예제 #8
0
/*
 * Load new table/tables to device.
 * Call apropriate target init routine open all physical pdev's and
 * link them to device. For other targets mirror, strip, snapshot
 * etc. also add dependency devices to upcalls list.
 *
 * Load table to inactive slot table are switched in dm_device_resume_ioctl.
 * This simulates Linux behaviour better there should not be any difference.
 *
 */
int
dm_table_load_ioctl(prop_dictionary_t dm_dict)
{
	dm_dev_t *dmv;
	dm_table_entry_t *table_en, *last_table;
	dm_table_t *tbl;
	dm_target_t *target;

	prop_object_iterator_t iter;
	prop_array_t cmd_array;
	prop_dictionary_t target_dict;

	const char *name, *uuid, *type;

	uint32_t flags, ret, minor;

	char *str;

	ret = 0;
	flags = 0;
	name = NULL;
	uuid = NULL;
	dmv = NULL;
	last_table = NULL;
	str = NULL;

	/*
	 * char *xml; xml = prop_dictionary_externalize(dm_dict);
	 * printf("%s\n",xml);
	 */

	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name);
	prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor);

	cmd_array = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA);
	iter = prop_array_iterator(cmd_array);
	dm_dbg_print_flags(flags);

	if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) {
		DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG);
		return ENOENT;
	}
	aprint_debug("Loading table to device: %s--%d\n", name,
	    dmv->table_head.cur_active_table);

	/*
	 * I have to check if this table slot is not used by another table list.
	 * if it is used I should free them.
	 */
	if (dmv->flags & DM_INACTIVE_PRESENT_FLAG)
		dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);

	dm_dbg_print_flags(dmv->flags);
	tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_INACTIVE);

	aprint_debug("dmv->name = %s\n", dmv->name);

	prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);

	while ((target_dict = prop_object_iterator_next(iter)) != NULL) {
		prop_dictionary_get_cstring_nocopy(target_dict,
		    DM_TABLE_TYPE, &type);
		/*
		 * If we want to deny table with 2 or more different
		 * target we should do it here
		 */
		if (((target = dm_target_lookup(type)) == NULL) &&
		    ((target = dm_target_autoload(type)) == NULL)) {
			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_dev_unbusy(dmv);
			return ENOENT;
		}
		if ((table_en = kmalloc(sizeof(dm_table_entry_t),
			    M_DM, M_WAITOK)) == NULL) {
			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_dev_unbusy(dmv);
			dm_target_unbusy(target);
			return ENOMEM;
		}
		prop_dictionary_get_uint64(target_dict, DM_TABLE_START,
		    &table_en->start);
		prop_dictionary_get_uint64(target_dict, DM_TABLE_LENGTH,
		    &table_en->length);

		aprint_debug("dm_ioctl.c... table_en->start = %ju, "
			     "table_en->length = %ju\n",
			     (uintmax_t)table_en->start,
			     (uintmax_t)table_en->length);

		table_en->target = target;
		table_en->dm_dev = dmv;
		table_en->target_config = NULL;

		/*
		 * There is a parameter string after dm_target_spec
		 * structure which  points to /dev/wd0a 284 part of
		 * table. String str points to this text. This can be
		 * null and therefore it should be checked before we try to
		 * use it.
		 */
		prop_dictionary_get_cstring(target_dict,
		    DM_TABLE_PARAMS, &str);

		if (SLIST_EMPTY(tbl))
			/* insert this table to head */
			SLIST_INSERT_HEAD(tbl, table_en, next);
		else
			SLIST_INSERT_AFTER(last_table, table_en, next);

		/*
		 * Params string is different for every target,
		 * therfore I have to pass it to target init
		 * routine and parse parameters there.
		 */
		aprint_debug("DM: str passed in is: %s", str);
		if ((ret = target->init(dmv, &table_en->target_config,
			    str)) != 0) {

			dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);
			dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
			kfree(str, M_TEMP);

			dm_dev_unbusy(dmv);
			dm_target_unbusy(target);
			return ret;
		}
		last_table = table_en;
		kfree(str, M_TEMP);
	}
	prop_object_iterator_release(iter);

	DM_ADD_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
	atomic_set_int(&dmv->flags, DM_INACTIVE_PRESENT_FLAG);

	dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE);

	dm_dev_unbusy(dmv);
#if 0
	dmsetdiskinfo(dmv->diskp, &dmv->table_head);
#endif
	return 0;
}