void dm_lib_exit(void) { dm_lib_release(); dm_dump_memory(); _version_ok = 1; _version_checked = 0; }
/* Cleanup at exit. */ static void _exit_dm(struct dm_task *dmt) { if (dmt) dm_task_destroy(dmt); dm_lib_release(); dm_lib_exit(); }
void dm_exit(void) { if (_dm_use_count && (!--_dm_use_count)) { log_dbg("Releasing device-mapper backend."); dm_log_init_verbose(0); dm_log_init(NULL); dm_lib_release(); _context = NULL; } }
void grub_util_devmapper_cleanup (void) { dm_lib_release (); }
/* Cleanup at exit. */ static void _exit_dm_lib(void) { dm_lib_release(); dm_lib_exit(); }
void dev_manager_release(void) { dm_lib_release(); }
void era_dm_exit(void) { dm_lib_release(); dm_lib_exit(); }
int main(int argc, char **argv){ int fd, i, j, m, n, op, off, arg, c, d; struct slice all; struct pt *ptp; enum action what = LIST; char *type, *diskdevice, *device, *progname; int verbose = 0; char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16]; char * loopdev = NULL; char * delim = NULL; char *uuid = NULL; char *mapname = NULL; int loopro = 0; int hotplug = 0; int loopcreated = 0; int sync = 0; struct stat buf; uint32_t cookie = 0; initpts(); init_crc32(); type = device = diskdevice = NULL; memset(&all, 0, sizeof(all)); memset(&partname, 0, sizeof(partname)); /* Check whether hotplug mode. */ progname = strrchr(argv[0], '/'); if (!progname) progname = argv[0]; else progname++; if (!strcmp(progname, "kpartx.dev")) { /* Hotplug mode */ hotplug = 1; /* Setup for original kpartx variables */ if (!(device = get_hotplug_device())) exit(1); diskdevice = device; what = ADD; } else if (argc < 2) { usage(); exit(1); } while ((arg = getopt(argc, argv, short_opts)) != EOF) switch(arg) { case 'g': force_gpt=1; break; case 't': type = optarg; break; case 'v': verbose = 1; break; case 'p': delim = optarg; break; case 'l': what = LIST; break; case 'a': what = ADD; break; case 'd': what = DELETE; break; case 's': sync = 1; break; default: usage(); exit(1); } if (!sync) dm_udev_set_sync_support(0); if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) { fprintf(stderr, "device mapper prerequisites not met\n"); exit(1); } if (hotplug) { /* already got [disk]device */ } else if (optind == argc-2) { device = argv[optind]; diskdevice = argv[optind+1]; } else if (optind == argc-1) { diskdevice = device = argv[optind]; } else { usage(); exit(1); } if (stat(device, &buf)) { printf("failed to stat() %s\n", device); exit (1); } if (S_ISREG (buf.st_mode)) { /* already looped file ? */ loopdev = find_loop_by_file(device); if (!loopdev && what == DELETE) exit (0); if (!loopdev) { loopdev = find_unused_loop_device(); if (set_loop(loopdev, device, 0, &loopro)) { fprintf(stderr, "can't set up loop\n"); exit (1); } loopcreated = 1; } device = loopdev; } if (delim == NULL) { delim = malloc(DELIM_SIZE); memset(delim, 0, DELIM_SIZE); set_delimiter(device, delim); } off = find_devname_offset(device); if (!loopdev) { uuid = dm_mapuuid((unsigned int)MAJOR(buf.st_rdev), (unsigned int)MINOR(buf.st_rdev)); mapname = dm_mapname((unsigned int)MAJOR(buf.st_rdev), (unsigned int)MINOR(buf.st_rdev)); } if (!uuid) uuid = device + off; if (!mapname) mapname = device + off; fd = open(device, O_RDONLY); if (fd == -1) { perror(device); exit(1); } /* add/remove partitions to the kernel devmapper tables */ int r = 0; for (i = 0; i < ptct; i++) { ptp = &pts[i]; if (type && strcmp(type, ptp->type)) continue; /* here we get partitions */ n = ptp->fn(fd, all, slices, SIZE(slices)); #ifdef DEBUG if (n >= 0) printf("%s: %d slices\n", ptp->type, n); #endif if (n > 0) close(fd); else continue; switch(what) { case LIST: for (j = 0, c = 0, m = 0; j < n; j++) { if (slices[j].size == 0) continue; if (slices[j].container > 0) { c++; continue; } slices[j].minor = m++; printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", mapname, delim, j+1, slices[j].size, device, slices[j].start); } /* Loop to resolve contained slices */ d = c; while (c) { for (j = 0; j < n; j++) { uint64_t start; int k = slices[j].container - 1; if (slices[j].size == 0) continue; if (slices[j].minor > 0) continue; if (slices[j].container == 0) continue; slices[j].minor = m++; start = slices[j].start - slices[k].start; printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", mapname, delim, j+1, slices[j].size, slices[k].minor, start); c--; } /* Terminate loop if nothing more to resolve */ if (d == c) break; } if (loopcreated && S_ISREG (buf.st_mode)) { if (del_loop(device)) { if (verbose) printf("can't del loop : %s\n", device); exit(1); } printf("loop deleted : %s\n", device); } break; case DELETE: for (j = n-1; j >= 0; j--) { if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); if (!slices[j].size || !dm_map_present(partname)) continue; if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, 0, &cookie)) { r++; continue; } if (verbose) printf("del devmap : %s\n", partname); } if (S_ISREG (buf.st_mode)) { if (del_loop(device)) { if (verbose) printf("can't del loop : %s\n", device); exit(1); } printf("loop deleted : %s\n", device); } break; case ADD: for (j = 0, c = 0; j < n; j++) { if (slices[j].size == 0) continue; /* Skip all contained slices */ if (slices[j].container > 0) { c++; continue; } if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); if (safe_sprintf(params, "%s %" PRIu64 , device, slices[j].start)) { fprintf(stderr, "params too small\n"); exit(1); } op = (dm_map_present(partname) ? DM_DEVICE_RELOAD : DM_DEVICE_CREATE); if (!dm_addmap(op, partname, DM_TARGET, params, slices[j].size, uuid, j+1, buf.st_mode & 0777, buf.st_uid, buf.st_gid, &cookie)) { fprintf(stderr, "create/reload failed on %s\n", partname); r++; } if (op == DM_DEVICE_RELOAD && !dm_simplecmd(DM_DEVICE_RESUME, partname, 1, &cookie)) { fprintf(stderr, "resume failed on %s\n", partname); r++; } dm_devn(partname, &slices[j].major, &slices[j].minor); if (verbose) printf("add map %s (%d:%d): 0 %" PRIu64 " %s %s\n", partname, slices[j].major, slices[j].minor, slices[j].size, DM_TARGET, params); } /* Loop to resolve contained slices */ d = c; while (c) { for (j = 0; j < n; j++) { uint64_t start; int k = slices[j].container - 1; if (slices[j].size == 0) continue; /* Skip all existing slices */ if (slices[j].minor > 0) continue; /* Skip all simple slices */ if (slices[j].container == 0) continue; /* Check container slice */ if (slices[k].size == 0) fprintf(stderr, "Invalid slice %d\n", k); if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); start = slices[j].start - slices[k].start; if (safe_sprintf(params, "%d:%d %" PRIu64, slices[k].major, slices[k].minor, start)) { fprintf(stderr, "params too small\n"); exit(1); } op = (dm_map_present(partname) ? DM_DEVICE_RELOAD : DM_DEVICE_CREATE); dm_addmap(op, partname, DM_TARGET, params, slices[j].size, uuid, j+1, buf.st_mode & 0777, buf.st_uid, buf.st_gid, &cookie); if (op == DM_DEVICE_RELOAD) dm_simplecmd(DM_DEVICE_RESUME, partname, 1, &cookie); dm_devn(partname, &slices[j].major, &slices[j].minor); if (verbose) printf("add map %s : 0 %" PRIu64 " %s %s\n", partname, slices[j].size, DM_TARGET, params); c--; } /* Terminate loop */ if (d == c) break; } break; default: break; } if (n > 0) break; } dm_udev_wait(cookie); dm_lib_release(); dm_lib_exit(); return r; }
/* * This function is heart of NetBSD libdevmapper-> device-mapper kernel protocol * It creates proplib_dictionary from dm task structure and sends it to NetBSD * kernel driver. After succesfull ioctl it create dmi structure from returned * proplib dictionary. This way I keep number of changes in NetBSD version of * libdevmapper as small as posible. */ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command) { struct dm_ioctl *dmi; prop_dictionary_t dm_dict_in, dm_dict_out; uint32_t flags; dm_dict_in = NULL; dm_dict_in = prop_dictionary_create(); /* Dictionary send to kernel */ dm_dict_out = prop_dictionary_create(); /* Dictionary received from kernel */ /* Set command name to dictionary */ prop_dictionary_set_cstring(dm_dict_in, DM_IOCTL_COMMAND, _cmd_data_v4[dmt->type].name); /* Parse dmi from libdevmapper to dictionary */ if (_flatten(dmt, dm_dict_in) < 0) goto bad; prop_dictionary_get_uint32(dm_dict_in, DM_IOCTL_FLAGS, &flags); if (dmt->type == DM_DEVICE_TABLE) flags |= DM_STATUS_TABLE_FLAG; if (dmt->no_open_count) flags |= DM_SKIP_BDGET_FLAG; flags |= DM_EXISTS_FLAG; /* Set flags to dictionary. */ prop_dictionary_set_uint32(dm_dict_in,DM_IOCTL_FLAGS,flags); prop_dictionary_externalize_to_file(dm_dict_in,"/tmp/test_in"); log_very_verbose("Ioctl type %s --- flags %d",_cmd_data_v4[dmt->type].name,flags); //printf("name %s, major %d minor %d\n uuid %s\n", //dm_task_get_name(dmt), dmt->minor, dmt->major, dm_task_get_uuid(dmt)); /* Send dictionary to kernel and wait for reply. */ #ifdef RUMP_ACTION struct plistref prefp; int err; prop_dictionary_externalize_to_pref(dm_dict_in, &prefp); if (rump_sys_ioctl(_control_fd, NETBSD_DM_IOCTL, &prefp) != 0) { dm_dict_out = prop_dictionary_internalize(prefp.pref_plist); #else if (prop_dictionary_sendrecv_ioctl(dm_dict_in,_control_fd, NETBSD_DM_IOCTL,&dm_dict_out) != 0) { #endif if (errno == ENOENT && ((dmt->type == DM_DEVICE_INFO) || (dmt->type == DM_DEVICE_MKNODES) || (dmt->type == DM_DEVICE_STATUS))) { /* * Linux version doesn't fail when ENOENT is returned * for nonexisting device after info, deps, mknodes call. * It returns dmi sent to kernel with DM_EXISTS_FLAG = 0; */ dmi = nbsd_dm_dict_to_dmi(dm_dict_in,_cmd_data_v4[dmt->type].cmd); dmi->flags &= ~DM_EXISTS_FLAG; prop_object_release(dm_dict_in); prop_object_release(dm_dict_out); goto out; } else { log_error("ioctl %s call failed with errno %d\n", _cmd_data_v4[dmt->type].name, errno); prop_object_release(dm_dict_in); prop_object_release(dm_dict_out); goto bad; } } #ifdef RUMP_ACTION dm_dict_out = prop_dictionary_internalize(prefp.pref_plist); #endif prop_dictionary_externalize_to_file(dm_dict_out,"/tmp/test_out"); /* Parse kernel dictionary to dmi structure and return it to libdevmapper. */ dmi = nbsd_dm_dict_to_dmi(dm_dict_out,_cmd_data_v4[dmt->type].cmd); prop_object_release(dm_dict_in); prop_object_release(dm_dict_out); out: return dmi; bad: return NULL; } /* Create new edvice nodes in mapper/ dir. */ void dm_task_update_nodes(void) { update_devs(); } /* Run dm command which is descirbed in dm_task structure. */ int dm_task_run(struct dm_task *dmt) { struct dm_ioctl *dmi; unsigned command; if ((unsigned) dmt->type >= (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) { log_error("Internal error: unknown device-mapper task %d", dmt->type); return 0; } command = _cmd_data_v4[dmt->type].cmd; /* Old-style creation had a table supplied */ if (dmt->type == DM_DEVICE_CREATE && dmt->head) return _create_and_load_v4(dmt); if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name && !dmt->uuid && dmt->major <= 0) return _mknodes_v4(dmt); if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload) return _reload_with_suppression_v4(dmt); if (!_open_control()) return 0; if (!(dmi = _do_dm_ioctl(dmt, command))) return 0; switch (dmt->type) { case DM_DEVICE_CREATE: add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev), dmt->uid, dmt->gid, dmt->mode, 0); break; case DM_DEVICE_REMOVE: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) rm_dev_node(dmt->dev_name, 0); break; case DM_DEVICE_RENAME: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) rename_dev_node(dmt->dev_name, dmt->newname, 0); break; case DM_DEVICE_RESUME: /* FIXME Kernel needs to fill in dmi->name */ set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead, dmt->read_ahead_flags); break; case DM_DEVICE_MKNODES: if (dmi->flags & DM_EXISTS_FLAG) add_dev_node(dmi->name, MAJOR(dmi->dev), MINOR(dmi->dev), dmt->uid, dmt->gid, dmt->mode, 0); else if (dmt->dev_name) rm_dev_node(dmt->dev_name, 0); break; case DM_DEVICE_STATUS: case DM_DEVICE_TABLE: case DM_DEVICE_WAITEVENT: if (!_unmarshal_status(dmt, dmi)) goto bad; break; } /* Was structure reused? */ if (dmt->dmi.v4) dm_free(dmt->dmi.v4); dmt->dmi.v4 = dmi; return 1; bad: dm_free(dmi); return 0; } void dm_lib_release(void) { if (_control_fd != -1) { close(_control_fd); _control_fd = -1; } update_devs(); } void dm_lib_exit(void) { dm_lib_release(); dm_dump_memory(); _version_ok = 1; _version_checked = 0; }