void dm_lib_exit(void)
{
	dm_lib_release();
	dm_dump_memory();
	_version_ok = 1;
	_version_checked = 0;
}
Esempio n. 2
0
/* Cleanup at exit. */
static void
_exit_dm(struct dm_task *dmt)
{
	if (dmt)
		dm_task_destroy(dmt);

	dm_lib_release();
	dm_lib_exit();
}
Esempio n. 3
0
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;
	}
}
Esempio n. 4
0
void
grub_util_devmapper_cleanup (void)
{
  dm_lib_release ();
}
Esempio n. 5
0
/* Cleanup at exit. */
static void _exit_dm_lib(void)
{
	dm_lib_release();
	dm_lib_exit();
}
Esempio n. 6
0
void dev_manager_release(void)
{
	dm_lib_release();
}
Esempio n. 7
0
void era_dm_exit(void)
{
	dm_lib_release();
	dm_lib_exit();
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
/*
 * 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;
}