xref: /dragonfly/contrib/lvm2/dist/test/api/test.c (revision 91dc43dd)
1 /*	$NetBSD: test.c,v 1.1.1.2 2009/12/02 00:26:03 haad Exp $	*/
2 
3 /*
4  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6  *
7  * This file is part of LVM2.
8  *
9  * This copyrighted material is made available to anyone wishing to use,
10  * modify, copy, or redistribute it subject to the terms and conditions
11  * of the GNU Lesser General Public License v.2.1.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <readline/readline.h>
21 
22 #include "lvm2app.h"
23 
24 #define MAX_ARGS 64
25 
26 static int lvm_split(char *str, int *argc, char **argv, int max)
27 {
28 	char *b = str, *e;
29 	*argc = 0;
30 
31 	while (*b) {
32 		while (*b && isspace(*b))
33 			b++;
34 
35 		if ((!*b) || ((*argc == 0)&&(*b == '#')))
36 			break;
37 
38 		e = b;
39 		while (*e && !isspace(*e))
40 			e++;
41 
42 		argv[(*argc)++] = b;
43 		if (!*e)
44 			break;
45 		*e++ = '\0';
46 		b = e;
47 		if (*argc == max)
48 			break;
49 	}
50 
51 	return *argc;
52 }
53 
54 static void _show_help(void)
55 {
56 	printf("'lv_activate vgname lvname: "
57 	       "Activate an LV\n");
58 	printf("'lv_deactivate vgname lvname: "
59 	       "Deactivate an LV\n");
60 	printf("'vg_remove_lv vgname lvname': "
61 	       "Remove a LV\n");
62 	printf("'vg_create_lv_linear vgname lvname size_in_bytes': "
63 	       "Create a linear LV\n");
64 	printf("'scan_vgs': "
65 	       "Scan the system for LVM metadata\n");
66 	printf("'list_vg_names': "
67 	       "List the names of the VGs that exist in the system\n");
68 	printf("'list_vg_ids': "
69 	       "List the uuids of the VGs that exist in the system\n");
70 	printf("'vg_list_pvs vgname': "
71 	       "List the PVs that exist in VG vgname\n");
72 	printf("'vg_list_lvs vgname': "
73 	       "List the LVs that exist in VG vgname\n");
74 	printf("'vgs_open': "
75 	       "List the VGs that are currently open\n");
76 	printf("'vgs': "
77 	       "List all VGs known to the system\n");
78 	printf("'vg_extend vgname device: "
79 	       "Issue a lvm_vg_extend() API call on VG 'vgname'\n");
80 	printf("'vg_reduce vgname device: "
81 	       "Issue a lvm_vg_reduce() API call on VG 'vgname'\n");
82 	printf("'vg_open vgname ['r' | 'w']': "
83 	       "Issue a lvm_vg_open() API call on VG 'vgname'\n");
84 	printf("'vg_close vgname': "
85 	       "Issue a lvm_vg_close() API call on VG 'vgname'\n");
86 	printf("'vg_create vgname: "
87 	       "Issue a lvm_vg_create() to create VG 'vgname'\n");
88 	printf("'vg_remove vgname: "
89 	       "Issue a lvm_vg_remove() to remove VG 'vgname'\n");
90 	printf("'config_reload': "
91 	       "Issue a lvm_config_reload() API to reload LVM config\n");
92 	printf("'config_override' device: "
93 	       "Issue a lvm_config_override() with accept device filter\n");
94 	printf("'quit': exit the program\n");
95 }
96 
97 static struct dm_hash_table *_vgid_hash = NULL;
98 static struct dm_hash_table *_vgname_hash = NULL;
99 static struct dm_hash_table *_pvname_hash = NULL;
100 static struct dm_hash_table *_lvname_hash = NULL;
101 
102 static void _hash_destroy_single(struct dm_hash_table **htable)
103 {
104 	if (htable && *htable) {
105 		dm_hash_destroy(*htable);
106 		*htable = NULL;
107 	}
108 }
109 
110 static void _hash_destroy(void)
111 {
112 	_hash_destroy_single(&_vgname_hash);
113 	_hash_destroy_single(&_vgid_hash);
114 	_hash_destroy_single(&_pvname_hash);
115 	_hash_destroy_single(&_lvname_hash);
116 }
117 
118 static int _hash_create(void)
119 {
120 	if (!(_vgname_hash = dm_hash_create(128)))
121 		return 0;
122 	if (!(_pvname_hash = dm_hash_create(128))) {
123 		_hash_destroy_single(&_vgname_hash);
124 		return 0;
125 	}
126 	if (!(_lvname_hash = dm_hash_create(128))) {
127 		_hash_destroy_single(&_vgname_hash);
128 		_hash_destroy_single(&_pvname_hash);
129 		return 0;
130 	}
131 	if (!(_vgid_hash = dm_hash_create(128))) {
132 		_hash_destroy_single(&_vgname_hash);
133 		_hash_destroy_single(&_pvname_hash);
134 		_hash_destroy_single(&_lvname_hash);
135 		return 0;
136 	}
137 	return 1;
138 }
139 
140 /* FIXME: this should be per vg */
141 static lv_t _lookup_lv_by_name(const char *name)
142 {
143 	lv_t lv;
144 
145 	if (!name) {
146 		printf ("Invalid LV name\n");
147 		return NULL;
148 	}
149 	if (!(lv = dm_hash_lookup(_lvname_hash, name))) {
150 		printf ("Can't find %s in LVs - run vg_create_lv first\n",
151 			name);
152 		return NULL;
153 	}
154 	return lv;
155 }
156 
157 static vg_t _lookup_vg_by_name(char **argv, int argc)
158 {
159 	vg_t vg;
160 
161 	if (argc < 2) {
162 		printf ("Please enter vg_name\n");
163 		return NULL;
164 	}
165 	if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
166 	    !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
167 		printf ("Can't find %s in open VGs - run vg_open first\n",
168 			argv[1]);
169 		return NULL;
170 	}
171 	return vg;
172 }
173 static void _add_lvs_to_lvname_hash(struct dm_list *lvs)
174 {
175 	struct lvm_lv_list *lvl;
176 	dm_list_iterate_items(lvl, lvs) {
177 		/* Concatenate VG name with LV name */
178 		dm_hash_insert(_lvname_hash, lvm_lv_get_name(lvl->lv), lvl->lv);
179 	}
180 }
181 
182 static void _add_pvs_to_pvname_hash(struct dm_list *pvs)
183 {
184 	struct lvm_pv_list *pvl;
185 	dm_list_iterate_items(pvl, pvs) {
186 		dm_hash_insert(_pvname_hash, lvm_pv_get_name(pvl->pv), pvl->pv);
187 	}
188 }
189 
190 static void _remove_device_from_pvname_hash(struct dm_list *pvs, const char *name)
191 {
192 	struct lvm_pv_list *pvl;
193 	dm_list_iterate_items(pvl, pvs) {
194 		if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
195 			dm_hash_remove(_pvname_hash, name);
196 	}
197 }
198 static void _add_device_to_pvname_hash(struct dm_list *pvs, const char *name)
199 {
200 	struct lvm_pv_list *pvl;
201 	dm_list_iterate_items(pvl, pvs) {
202 		if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
203 			dm_hash_insert(_pvname_hash, name, pvl->pv);
204 	}
205 }
206 static void _vg_reduce(char **argv, int argc, lvm_t libh)
207 {
208 	vg_t vg;
209 	struct dm_list *pvs;
210 
211 	if (argc < 2) {
212 		printf ("Please enter vg_name\n");
213 		return;
214 	}
215 	if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
216 	    !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
217 		printf ("VG not open\n");
218 		return;
219 	}
220 	if (lvm_vg_reduce(vg, argv[2])) {
221 		printf("Error reducing %s by %s\n", argv[1], argv[2]);
222 		return;
223 	}
224 
225 	printf("Success reducing vg %s by %s\n", argv[1], argv[2]);
226 
227 	/*
228 	 * Add the device into the hashes for lookups
229 	 */
230 	pvs = lvm_vg_list_pvs(vg);
231 	if (pvs && !dm_list_empty(pvs))
232 		_remove_device_from_pvname_hash(pvs, argv[2]);
233 }
234 
235 /* Print "Error" or "Success" depending on lvm status */
236 static int _lvm_status_to_pass_fail(int rc)
237 {
238 	if (rc)
239 		printf("Error ");
240 	else
241 		printf("Success ");
242 	return rc;
243 }
244 static void _config_override(char **argv, int argc, lvm_t libh)
245 {
246 	int rc;
247 	char tmp[64];
248 
249 	if (argc < 2) {
250 		printf ("Please enter device\n");
251 		return;
252 	}
253 	snprintf(tmp, 63, "devices{filter=[\"a|%s|\", \"r|.*|\"]}", argv[1]);
254 	rc = lvm_config_override(libh, tmp);
255 	_lvm_status_to_pass_fail(rc);
256 	printf("overriding LVM configuration\n");
257 }
258 
259 static void _config_reload(char **argv, int argc, lvm_t libh)
260 {
261 	int rc;
262 	rc = lvm_config_reload(libh);
263 	_lvm_status_to_pass_fail(rc);
264 	printf("reloading LVM configuration\n");
265 }
266 
267 static void _vg_extend(char **argv, int argc, lvm_t libh)
268 {
269 	vg_t vg;
270 	struct dm_list *pvs;
271 
272 	if (argc < 2) {
273 		printf ("Please enter vg_name\n");
274 		return;
275 	}
276 	if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
277 	    !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
278 		printf ("VG not open\n");
279 		return;
280 	}
281 	if (lvm_vg_extend(vg, argv[2])) {
282 		printf("Error extending %s with %s\n", argv[1], argv[2]);
283 		return;
284 	}
285 
286 	printf("Success extending vg %s with %s\n", argv[1], argv[2]);
287 
288 	/*
289 	 * Add the device into the hashes for lookups
290 	 */
291 	pvs = lvm_vg_list_pvs(vg);
292 	if (pvs && !dm_list_empty(pvs))
293 		_add_device_to_pvname_hash(pvs, argv[2]);
294 }
295 
296 static void _vg_open(char **argv, int argc, lvm_t libh)
297 {
298 	vg_t vg;
299 	struct dm_list *lvs;
300 	struct dm_list *pvs;
301 
302 	if (argc < 2) {
303 		printf ("Please enter vg_name\n");
304 		return;
305 	}
306 	if ((vg = dm_hash_lookup(_vgid_hash, argv[1])) ||
307 	    (vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
308 		printf ("VG already open\n");
309 		return;
310 	}
311 	if (argc < 3)
312 		vg = lvm_vg_open(libh, argv[1], "r", 0);
313 	else
314 		vg = lvm_vg_open(libh, argv[1], argv[2], 0);
315 	if (!vg || !lvm_vg_get_name(vg)) {
316 		printf("Error opening %s\n", argv[1]);
317 		return;
318 	}
319 
320 	printf("Success opening vg %s\n", argv[1]);
321 	dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
322 	dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
323 
324 	/*
325 	 * Add the LVs and PVs into the hashes for lookups
326 	 */
327 	lvs = lvm_vg_list_lvs(vg);
328 	if (lvs && !dm_list_empty(lvs))
329 		_add_lvs_to_lvname_hash(lvs);
330 	pvs = lvm_vg_list_pvs(vg);
331 	if (pvs && !dm_list_empty(pvs))
332 		_add_pvs_to_pvname_hash(pvs);
333 }
334 /* Lookup the vg and remove it from the vgname and vgid hashes */
335 static vg_t _lookup_and_remove_vg(const char *vgname)
336 {
337 	vg_t vg=NULL;
338 
339 	if ((vg = dm_hash_lookup(_vgname_hash, vgname))) {
340 		dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
341 		dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
342 	}
343 	if (!vg && (vg = dm_hash_lookup(_vgid_hash, vgname))) {
344 		dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
345 		dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
346 	}
347 	return vg;
348 }
349 
350 static void _vg_write(char **argv, int argc)
351 {
352 	vg_t vg;
353 	int rc = 0;
354 
355 	if (argc < 2) {
356 		printf ("Please enter vg_name\n");
357 		return;
358 	}
359 	vg = _lookup_vg_by_name(argv, argc);
360 	if (!vg) {
361 		printf("Can't find vg_name %s\n", argv[1]);
362 		return;
363 	}
364 	rc = lvm_vg_write(vg);
365 	_lvm_status_to_pass_fail(rc);
366 	printf("writing VG %s\n", lvm_vg_get_name(vg));
367 }
368 
369 static void _vg_create(char **argv, int argc, lvm_t libh)
370 {
371 	vg_t vg;
372 
373 	if (argc < 2) {
374 		printf ("Please enter vg_name\n");
375 		return;
376 	}
377 	vg = lvm_vg_create(libh, argv[1]);
378 	if (!vg || !lvm_vg_get_name(vg)) {
379 		printf("Error creating %s\n", argv[1]);
380 		return;
381 	}
382 
383 	printf("Success creating vg %s\n", argv[1]);
384 	dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
385 	dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
386 }
387 
388 static void _vg_remove(char **argv, int argc)
389 {
390 	vg_t vg;
391 	int rc = 0;
392 
393 	if (argc < 2) {
394 		printf ("Please enter vg_name\n");
395 		return;
396 	}
397 	vg = _lookup_vg_by_name(argv, argc);
398 	if (!vg) {
399 		printf("Can't find vg_name %s\n", argv[1]);
400 		return;
401 	}
402 	rc = lvm_vg_remove(vg);
403 	_lvm_status_to_pass_fail(rc);
404 	printf("removing VG\n");
405 }
406 
407 static void _vg_close(char **argv, int argc)
408 {
409 	vg_t vg;
410 	int rc = 0;
411 
412 	if (argc < 2) {
413 		printf ("Please enter vg_name\n");
414 		return;
415 	}
416 	vg = _lookup_and_remove_vg(argv[1]);
417 	if (!vg) {
418 		printf("Can't find vg_name %s\n", argv[1]);
419 		return;
420 	}
421 	rc = lvm_vg_close(vg);
422 	_lvm_status_to_pass_fail(rc);
423 	printf("closing VG\n");
424 }
425 
426 static void _show_one_vg(vg_t vg)
427 {
428 	printf("%s (%s): sz=%"PRIu64", free=%"PRIu64", #pv=%"PRIu64
429 		", seq#=%"PRIu64"\n",
430 		lvm_vg_get_name(vg), lvm_vg_get_uuid(vg),
431 		lvm_vg_get_size(vg), lvm_vg_get_free_size(vg),
432 		lvm_vg_get_pv_count(vg), lvm_vg_get_seqno(vg));
433 }
434 
435 static void _list_open_vgs(void)
436 {
437 	dm_hash_iter(_vgid_hash, (dm_hash_iterate_fn) _show_one_vg);
438 }
439 
440 static void _pvs_in_vg(char **argv, int argc)
441 {
442 	struct dm_list *pvs;
443 	struct lvm_pv_list *pvl;
444 	vg_t vg;
445 
446 	if (!(vg = _lookup_vg_by_name(argv, argc)))
447 		return;
448 	pvs = lvm_vg_list_pvs(vg);
449 	if (!pvs || dm_list_empty(pvs)) {
450 		printf("No PVs in VG %s\n", lvm_vg_get_name(vg));
451 		return;
452 	}
453 	printf("PVs in VG %s:\n", lvm_vg_get_name(vg));
454 	dm_list_iterate_items(pvl, pvs) {
455 		printf("%s (%s): mda_count=%"PRIu64"\n",
456 		       lvm_pv_get_name(pvl->pv), lvm_pv_get_uuid(pvl->pv),
457 			lvm_pv_get_mda_count(pvl->pv));
458 	}
459 }
460 
461 static void _scan_vgs(lvm_t libh)
462 {
463 	lvm_scan(libh);
464 }
465 
466 static void _list_vg_names(lvm_t libh)
467 {
468 	struct dm_list *list;
469 	struct lvm_str_list *strl;
470 	const char *tmp;
471 
472 	list = lvm_list_vg_names(libh);
473 	printf("VG names:\n");
474 	dm_list_iterate_items(strl, list) {
475 		tmp = strl->str;
476 		printf("%s\n", tmp);
477 	}
478 }
479 
480 static void _list_vg_ids(lvm_t libh)
481 {
482 	struct dm_list *list;
483 	struct lvm_str_list *strl;
484 	const char *tmp;
485 
486 	list = lvm_list_vg_uuids(libh);
487 	printf("VG uuids:\n");
488 	dm_list_iterate_items(strl, list) {
489 		tmp = strl->str;
490 		printf("%s\n", tmp);
491 	}
492 }
493 
494 
495 static void _lvs_in_vg(char **argv, int argc)
496 {
497 	struct dm_list *lvs;
498 	struct lvm_lv_list *lvl;
499 	vg_t vg;
500 
501 	if (!(vg = _lookup_vg_by_name(argv, argc)))
502 		return;
503 	lvs = lvm_vg_list_lvs(vg);
504 	if (!lvs || dm_list_empty(lvs)) {
505 		printf("No LVs in VG %s\n", lvm_vg_get_name(vg));
506 		return;
507 	}
508 	printf("LVs in VG %s:\n", lvm_vg_get_name(vg));
509 	dm_list_iterate_items(lvl, lvs) {
510 		printf("%s/%s (%s): size=%"PRIu64", %sACTIVE / %sSUSPENDED\n",
511 			lvm_vg_get_name(vg),
512 			lvm_lv_get_name(lvl->lv), lvm_lv_get_uuid(lvl->lv),
513 			lvm_lv_get_size(lvl->lv),
514 			lvm_lv_is_active(lvl->lv) ? "" : "IN",
515 			lvm_lv_is_suspended(lvl->lv) ? "" : "NOT ");
516 	}
517 }
518 
519 static void _lv_deactivate(char **argv, int argc)
520 {
521 	lv_t lv;
522 	int rc=0;
523 
524 	if (argc < 3) {
525 		printf("Please enter vgname, lvname\n");
526 		return;
527 	}
528 	if (!(lv = _lookup_lv_by_name(argv[2])))
529 		return;
530 	rc = lvm_lv_deactivate(lv);
531 	_lvm_status_to_pass_fail(rc);
532 	printf("De-activating LV %s in VG %s\n",
533 		argv[2], argv[1]);
534 }
535 static void _lv_activate(char **argv, int argc)
536 {
537 	lv_t lv;
538 	int rc=0;
539 
540 	if (argc < 3) {
541 		printf("Please enter vgname, lvname\n");
542 		return;
543 	}
544 	if (!(lv = _lookup_lv_by_name(argv[2])))
545 		return;
546 	rc = lvm_lv_activate(lv);
547 	_lvm_status_to_pass_fail(rc);
548 	printf("activating LV %s in VG %s\n",
549 		argv[2], argv[1]);
550 }
551 static void _vg_remove_lv(char **argv, int argc)
552 {
553 	lv_t lv;
554 
555 	if (argc < 3) {
556 		printf("Please enter vgname, lvname\n");
557 		return;
558 	}
559 	if (!(lv = _lookup_lv_by_name(argv[2])))
560 		return;
561 	if (lvm_vg_remove_lv(lv))
562 		printf("Error ");
563 	else {
564 		printf("Success ");
565 		dm_hash_remove(_lvname_hash, argv[2]);
566 	}
567 	printf("removing LV %s in VG %s\n",
568 		argv[2], argv[1]);
569 }
570 
571 static void _vg_create_lv_linear(char **argv, int argc)
572 {
573 	vg_t vg;
574 	lv_t lv;
575 
576 	if (argc < 4) {
577 		printf("Please enter vgname, lvname, and size\n");
578 		return;
579 	}
580 	if (!(vg = _lookup_vg_by_name(argv, argc)))
581 		return;
582 	lv = lvm_vg_create_lv_linear(vg, argv[2], atol(argv[3]));
583 	if (!lv)
584 		printf("Error ");
585 	else {
586 		printf("Success ");
587 		dm_hash_insert(_lvname_hash, argv[2], lv);
588 	}
589 	printf("creating LV %s in VG %s\n",
590 		argv[2], argv[1]);
591 }
592 
593 static int lvmapi_test_shell(lvm_t libh)
594 {
595 	int argc;
596 	char *input = NULL, *args[MAX_ARGS], **argv;
597 
598 	_hash_create();
599 	argc=0;
600 	while (1) {
601 		free(input);
602 		input = readline("liblvm> ");
603 
604 		/* EOF */
605 		if (!input) {
606 			printf("\n");
607 			break;
608 		}
609 
610 		/* empty line */
611 		if (!*input)
612 			continue;
613 
614 		argv = args;
615 
616 		if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
617 			printf("Too many arguments, sorry.");
618 			continue;
619 		}
620 
621 		if (!strcmp(argv[0], "lvm")) {
622 			argv++;
623 			argc--;
624 		}
625 
626 		if (!argc)
627 			continue;
628 
629 		if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
630 			printf("Exiting.\n");
631 			break;
632 		} else if (!strcmp(argv[0], "?") || !strcmp(argv[0], "help")) {
633 			_show_help();
634 		} else if (!strcmp(argv[0], "config_reload")) {
635 			_config_reload(argv, argc, libh);
636 		} else if (!strcmp(argv[0], "config_override")) {
637 			_config_override(argv, argc, libh);
638 		} else if (!strcmp(argv[0], "vg_extend")) {
639 			_vg_extend(argv, argc, libh);
640 		} else if (!strcmp(argv[0], "vg_reduce")) {
641 			_vg_reduce(argv, argc, libh);
642 		} else if (!strcmp(argv[0], "vg_write")) {
643 			_vg_write(argv, argc);
644 		} else if (!strcmp(argv[0], "vg_open")) {
645 			_vg_open(argv, argc, libh);
646 		} else if (!strcmp(argv[0], "vg_close")) {
647 			_vg_close(argv, argc);
648 		} else if (!strcmp(argv[0], "vg_create")) {
649 			_vg_create(argv, argc, libh);
650 		} else if (!strcmp(argv[0], "vg_remove")) {
651 			_vg_remove(argv, argc);
652 		} else if (!strcmp(argv[0], "lv_activate")) {
653 			_lv_activate(argv, argc);
654 		} else if (!strcmp(argv[0], "lv_deactivate")) {
655 			_lv_deactivate(argv, argc);
656 		} else if (!strcmp(argv[0], "vg_remove_lv")) {
657 			_vg_remove_lv(argv, argc);
658 		} else if (!strcmp(argv[0], "vgs_open")) {
659 			_list_open_vgs();
660 		} else if (!strcmp(argv[0], "vg_list_pvs")) {
661 			_pvs_in_vg(argv, argc);
662 		} else if (!strcmp(argv[0], "vg_list_lvs")) {
663 			_lvs_in_vg(argv, argc);
664 		} else if (!strcmp(argv[0], "list_vg_names")) {
665 			_list_vg_names(libh);
666 		} else if (!strcmp(argv[0], "list_vg_ids")) {
667 			_list_vg_ids(libh);
668 		} else if (!strcmp(argv[0], "scan_vgs")) {
669 			_scan_vgs(libh);
670 		} else if (!strcmp(argv[0], "vg_create_lv_linear")) {
671 			_vg_create_lv_linear(argv, argc);
672 		} else {
673 			printf ("Unrecognized command %s\n", argv[0]);
674 		}
675 	}
676 
677 	dm_hash_iter(_vgname_hash, (dm_hash_iterate_fn) lvm_vg_close);
678 	_hash_destroy();
679 	free(input);
680 	return 0;
681 }
682 
683 int main (int argc, char *argv[])
684 {
685 	lvm_t libh;
686 
687 	libh = lvm_init(NULL);
688 	if (!libh) {
689 		printf("Unable to open lvm library instance\n");
690 		return 1;
691 	}
692 
693 	printf("Library version: %s\n", lvm_library_get_version());
694 	lvmapi_test_shell(libh);
695 
696 	lvm_quit(libh);
697 	return 0;
698 }
699 
700