/* 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; }
/* * 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; }
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; }
/* 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; }
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; }
/* * 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; }