r383 - in devmapper/trunk: . dmsetup include kernel/common kernel/fs kernel/ioctl lib lib/ioctl lib/mm man patches

Bastian Blank waldi at costa.debian.org
Mon Oct 23 08:43:06 UTC 2006


Author: waldi
Date: Mon Oct 23 08:43:05 2006
New Revision: 383

Added:
   devmapper/trunk/lib/libdm-string.c
Removed:
   devmapper/trunk/kernel/common/
   devmapper/trunk/kernel/fs/
   devmapper/trunk/kernel/ioctl/dm-ioctl.c
   devmapper/trunk/patches/
Modified:
   devmapper/trunk/   (props changed)
   devmapper/trunk/VERSION
   devmapper/trunk/WHATS_NEW
   devmapper/trunk/configure
   devmapper/trunk/configure.in
   devmapper/trunk/dmsetup/dmsetup.c
   devmapper/trunk/include/configure.h.in
   devmapper/trunk/kernel/ioctl/dm-ioctl.h
   devmapper/trunk/lib/.exported_symbols
   devmapper/trunk/lib/Makefile.in
   devmapper/trunk/lib/ioctl/libdm-iface.c
   devmapper/trunk/lib/ioctl/libdm-targets.h
   devmapper/trunk/lib/libdevmapper.h
   devmapper/trunk/lib/libdm-deptree.c
   devmapper/trunk/lib/mm/dbg_malloc.c
   devmapper/trunk/man/dmsetup.8

Log:
Merge /devmapper/upstream/current (1.02.12).


Modified: devmapper/trunk/VERSION
==============================================================================
--- devmapper/trunk/VERSION	(original)
+++ devmapper/trunk/VERSION	Mon Oct 23 08:43:05 2006
@@ -1 +1 @@
-1.02.08 (2006-07-17)
+1.02.12 (2006-10-13)

Modified: devmapper/trunk/WHATS_NEW
==============================================================================
--- devmapper/trunk/WHATS_NEW	(original)
+++ devmapper/trunk/WHATS_NEW	Mon Oct 23 08:43:05 2006
@@ -1,3 +1,24 @@
+Version 1.02.12 - 13 Oct 2006
+=============================
+  Avoid deptree attempting to suspend a device that's already suspended.
+
+Version 1.02.11 -  12 Oct 2006
+==============================
+  Add suspend noflush support.
+  Add basic dmsetup loop support.
+  Switch dmsetup to use dm_malloc and dm_free.
+
+Version 1.02.10 - 19 Sep 2006
+=============================
+  Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
+  Reorder mm bounds_check code to reduce window for a dmeventd race.
+
+Version 1.02.09 - 15 Aug 2006
+=============================
+  Add --table argument to dmsetup for a one-line table.
+  Abort if errors are found during cmdline option processing.
+  Add lockfs indicator to debug output.
+
 Version 1.02.08 - 17 July 2006
 ==============================
   Append full patch to check in emails.

Modified: devmapper/trunk/configure
==============================================================================
--- devmapper/trunk/configure	(original)
+++ devmapper/trunk/configure	Mon Oct 23 08:43:05 2006
@@ -3735,7 +3735,8 @@
 
 
 
-for ac_header in termios.h
+
+for ac_header in termios.h sys/statvfs.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -5445,6 +5446,81 @@
 
 
 ################################################################################
+
+echo "$as_me:$LINENO: checking for canonicalize_file_name in -lc" >&5
+echo $ECHO_N "checking for canonicalize_file_name in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_canonicalize_file_name+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char canonicalize_file_name ();
+int
+main ()
+{
+canonicalize_file_name ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_canonicalize_file_name=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_canonicalize_file_name=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_canonicalize_file_name" >&5
+echo "${ECHO_T}$ac_cv_lib_c_canonicalize_file_name" >&6
+if test $ac_cv_lib_c_canonicalize_file_name = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CANONICALIZE_FILE_NAME 1
+_ACEOF
+
+fi
+
+
+################################################################################
 echo "$as_me:$LINENO: checking whether to enable selinux support" >&5
 echo $ECHO_N "checking whether to enable selinux support... $ECHO_C" >&6
 # Check whether --enable-selinux or --disable-selinux was given.

Modified: devmapper/trunk/configure.in
==============================================================================
--- devmapper/trunk/configure.in	(original)
+++ devmapper/trunk/configure.in	Mon Oct 23 08:43:05 2006
@@ -71,7 +71,7 @@
 
 AC_CHECK_HEADERS(ctype.h dirent.h errno.h fcntl.h getopt.h inttypes.h limits.h stdarg.h stdio.h stdlib.h string.h sys/ioctl.h sys/param.h sys/stat.h sys/types.h unistd.h,,AC_MSG_ERROR(bailing out))
 
-AC_CHECK_HEADERS(termios.h)
+AC_CHECK_HEADERS(termios.h sys/statvfs.h)
 ################################################################################
 dnl -- Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
@@ -210,6 +210,11 @@
 AC_CHECK_LIB(c, getline, AC_DEFINE([HAVE_GETLINE], 1, [Define to 1 if getline is available.]))
 
 ################################################################################
+dnl -- canonicalize_file_name included in recent libc
+
+AC_CHECK_LIB(c, canonicalize_file_name, AC_DEFINE([HAVE_CANONICALIZE_FILE_NAME], 1, [Define to 1 if canonicalize_file_name is available.]))
+
+################################################################################
 dnl -- Disable selinux
 AC_MSG_CHECKING(whether to enable selinux support)
 AC_ARG_ENABLE(selinux, [  --disable-selinux       Disable selinux support],

Modified: devmapper/trunk/dmsetup/dmsetup.c
==============================================================================
--- devmapper/trunk/dmsetup/dmsetup.c	(original)
+++ devmapper/trunk/dmsetup/dmsetup.c	Mon Oct 23 08:43:05 2006
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
  * Copyright (C) 2005 NEC Corperation
  *
  * This file is part of the device-mapper userspace tools.
@@ -38,6 +38,16 @@
 #include <locale.h>
 #include <langinfo.h>
 
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* FIXME Unused so far */
+#undef HAVE_SYS_STATVFS_H
+
+#ifdef HAVE_SYS_STATVFS_H
+#  include <sys/statvfs.h>
+#endif
+
 #ifdef HAVE_SYS_IOCTL_H
 #  include <sys/ioctl.h>
 #endif
@@ -78,6 +88,11 @@
 
 #define LINE_SIZE 4096
 #define ARGS_MAX 256
+#define LOOP_TABLE_SIZE (PATH_MAX + 255)
+
+/* FIXME Should be elsewhere */
+#define SECTOR_SHIFT 9L
+#define DEV_PATH "/dev/"
 
 #define err(msg, x...) fprintf(stderr, msg "\n", ##x)
 
@@ -93,11 +108,13 @@
 	MAJOR_ARG,
 	MINOR_ARG,
 	MODE_ARG,
+	NOFLUSH_ARG,
 	NOHEADINGS_ARG,
 	NOLOCKFS_ARG,
 	NOOPENCOUNT_ARG,
 	NOTABLE_ARG,
 	OPTIONS_ARG,
+	TABLE_ARG,
 	TARGET_ARG,
 	TREE_ARG,
 	UID_ARG,
@@ -112,6 +129,7 @@
 static int _num_devices;
 static char *_uuid;
 static char *_fields;
+static char *_table;
 static char *_target;
 static char *_command;
 static struct dm_tree *_dtree;
@@ -119,17 +137,55 @@
 /*
  * Commands
  */
+static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,
+		       int line)
+{
+	char ttype[LINE_SIZE], *ptr, *comment;
+	unsigned long long start, size;
+	int n;
+
+	/* trim trailing space */
+	for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)
+		if (!isspace((int) *ptr))
+			break;
+	ptr++;
+	*ptr = '\0';
+
+	/* trim leading space */
+	for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++)
+		;
+
+	if (!*ptr || *ptr == '#')
+		return 1;
+
+	if (sscanf(ptr, "%llu %llu %s %n",
+		   &start, &size, ttype, &n) < 3) {
+		err("Invalid format on line %d of table %s", line, file);
+		return 0;
+	}
+
+	ptr += n;
+	if ((comment = strchr(ptr, (int) '#')))
+		*comment = '\0';
+
+	if (!dm_task_add_target(dmt, start, size, ttype, ptr))
+		return 0;
+
+	return 1;
+}
+
 static int _parse_file(struct dm_task *dmt, const char *file)
 {
 	char *buffer = NULL;
 	size_t buffer_size = 0;
-	char ttype[LINE_SIZE], *ptr, *comment;
 	FILE *fp;
-	unsigned long long start, size;
-	int r = 0, n, line = 0;
+	int r = 0, line = 0;
 
-	/* OK for empty stdin */
+	/* one-line table on cmdline */
+	if (_table)
+		return _parse_line(dmt, _table, "", ++line);
 
+	/* OK for empty stdin */
 	if (file) {
 		if (!(fp = fopen(file, "r"))) {
 			err("Couldn't open '%s' for reading", file);
@@ -140,47 +196,22 @@
 
 #ifndef HAVE_GETLINE
 	buffer_size = LINE_SIZE;
-	if (!(buffer = malloc(buffer_size))) {
+	if (!(buffer = dm_malloc(buffer_size))) {
 		err("Failed to malloc line buffer.");
 		return 0;
 	}
 
-	while (fgets(buffer, (int) buffer_size, fp)) {
+	while (fgets(buffer, (int) buffer_size, fp))
 #else
-	while (getline(&buffer, &buffer_size, fp) > 0) {
+	while (getline(&buffer, &buffer_size, fp) > 0)
 #endif
-		line++;
-
-		/* trim trailing space */
-		for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)
-			if (!isspace((int) *ptr))
-				break;
-		ptr++;
-		*ptr = '\0';
-
-		/* trim leading space */
-		for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++) ;
-
-		if (!*ptr || *ptr == '#')
-			continue;
-
-		if (sscanf(ptr, "%llu %llu %s %n",
-			   &start, &size, ttype, &n) < 3) {
-			err("%s:%d Invalid format", file, line);
+		if (!_parse_line(dmt, buffer, file ? : "on stdin", ++line))
 			goto out;
-		}
 
-		ptr += n;
-		if ((comment = strchr(ptr, (int) '#')))
-			*comment = '\0';
-
-		if (!dm_task_add_target(dmt, start, size, ttype, ptr))
-			goto out;
-	}
 	r = 1;
 
       out:
-	free(buffer);
+	dm_free(buffer);
 	if (file)
 		fclose(fp);
 	return r;
@@ -497,7 +528,7 @@
 	for (i = 0; i < argc; i++)
 		sz += strlen(argv[i]) + 1;
 
-	str = malloc(sz);
+	str = dm_malloc(sz);
 	memset(str, 0, sz);
 
 	for (i = 0; i < argc; i++) {
@@ -509,7 +540,7 @@
 	if (!dm_task_set_message(dmt, str))
 		goto out;
 
-	free(str);
+	dm_free(str);
 
 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
 		goto out;
@@ -588,6 +619,9 @@
 	if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
 		goto out;
 
+	if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
+		goto out;
+
 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
 		goto out;
 
@@ -725,32 +759,32 @@
 
 	size = _get_device_size(name);
 
-        if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
-                return 0;
+	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+		return 0;
 
 	if (!_set_task_device(dmt, name, 0))
-		goto err;
+		goto error;
 
-        if (!dm_task_add_target(dmt, 0, size, "error", ""))
-		goto err;
+	if (!dm_task_add_target(dmt, 0, size, "error", ""))
+		goto error;
 
-        if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
-                goto err;
+	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
+		goto error;
 
-        if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
-                goto err;
+	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+		goto error;
 
-        if (!dm_task_run(dmt))
-                goto err;
+	if (!dm_task_run(dmt))
+		goto error;
 
 	if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
 		_simple(DM_DEVICE_CLEAR, name, 0, 0);
-		goto err;
+		goto error;
 	}
 
 	r = 1;
 
-err:
+error:
 	dm_task_destroy(dmt);
 	return r;
 }
@@ -1472,11 +1506,12 @@
 static struct command _commands[] = {
 	{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
 	  "\t                  [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
-	  "\t                  [-u|uuid <uuid>] [--notable] [<table_file>]",
+	  "\t                  [-u|uuid <uuid>]\n"
+	  "\t                  [--notable | --table <table> | <table_file>]",
 	 1, 2, _create},
 	{"remove", "[-f|--force] <device>", 0, 1, _remove},
 	{"remove_all", "[-f|--force]", 0, 0, _remove_all},
-	{"suspend", "<device>", 0, 1, _suspend},
+	{"suspend", "[--noflush] <device>", 0, 1, _suspend},
 	{"resume", "<device>", 0, 1, _resume},
 	{"load", "<device> [<table_file>]", 0, 2, _load},
 	{"clear", "<device>", 0, 1, _clear},
@@ -1513,6 +1548,13 @@
 	return;
 }
 
+static void _losetup_usage(FILE *out)
+{
+	fprintf(out, "Usage:\n\n");
+	fprintf(out, "losetup [-d|-a] [-e encryption] "
+		     "[-o offset] [-f|loop_device] [file]\n\n");
+}
+
 static struct command *_find_command(const char *name)
 {
 	int i;
@@ -1590,11 +1632,225 @@
 	return 1;
 }
 
+/*
+ * Returns the full absolute path, or NULL if the path could
+ * not be resolved.
+ */
+static char *_get_abspath(char *path)
+{
+	char *_path;
+
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+	_path = canonicalize_file_name(path);
+#else
+	/* FIXME Provide alternative */
+#endif
+	return _path;
+}
+
+static char *parse_loop_device_name(char *dev)
+{
+	char *buf;
+	char *device;
+
+	if (!(buf = dm_malloc(PATH_MAX)));
+		return NULL;
+
+	if (dev[0] == '/') {
+		if (!(device = _get_abspath(dev)))
+			goto error;
+
+		if (strncmp(device, DEV_PATH, strlen(DEV_PATH)))
+			goto error;
+
+		strncpy(buf, strrchr(device, '/') + 1, PATH_MAX);
+		dm_free(device);
+
+	} else {
+		/* check for device number */
+		if (!strncmp(dev, "loop", strlen("loop")))
+			strncpy(buf, dev, PATH_MAX);
+		else
+			goto error;
+	}
+
+	return buf;
+
+error:
+	return NULL;
+}
+
+/*
+ *  create a table for a mapped device using the loop target.
+ */
+static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t off)
+{
+	struct stat fbuf;
+	off_t size, sectors;
+	int fd = -1;
+#ifdef HAVE_SYS_STATVFS_H
+	struct statvfs fsbuf;
+	off_t blksize;
+#endif
+
+	if (!_switches[READ_ONLY])
+		fd = open(file, O_RDWR);
+
+	if (fd < 0) {
+		_switches[READ_ONLY]++;
+		fd = open(file, O_RDONLY);
+	}
+
+	if (fd < 0)
+		goto error;
+
+	if (fstat(fd, &fbuf))
+		goto error;
+
+	size = (fbuf.st_size - off);
+	sectors = size >> SECTOR_SHIFT;
+
+	if (_switches[VERBOSE_ARG])
+		fprintf(stderr, "losetup: set loop size to %llukB (%llu sectors)\n",
+			sectors >> 1, sectors);
+
+#ifdef HAVE_SYS_STATVFS_H
+	if (fstatvfs(fd, &fsbuf))
+		goto error;       
+
+	/* FIXME Fragment size currently unused */
+	blksize = fsbuf.f_frsize;
+#endif
+
+	close(fd);
+
+	if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL, 
+			(long long unsigned)sectors, file, off) < 0)
+		return 0;
+
+	if (_switches[VERBOSE_ARG] > 1)
+		fprintf(stderr, "Table: %s\n", table);
+
+	return 1;
+
+error:
+	if (fd > -1)
+		close(fd);
+	return 0;
+}
+
+static int _process_losetup_switches(const char *base, int *argc, char ***argv)
+{
+	static int ind;
+	int c;
+	int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
+	char *device_name = NULL;
+	char *loop_file = NULL;
+	off_t offset = 0;
+
+#ifdef HAVE_GETOPTLONG
+	static struct option long_options[] = {
+		{0, 0, 0, 0}
+	};
+#endif
+
+	optarg = 0;
+	optind = OPTIND_INIT;
+	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
+					    long_options, NULL)) != -1 ) {
+		if (c == ':' || c == '?')
+			return 0;
+		if (c == 'a')
+			show_all++;
+		if (c == 'd')
+			delete++;
+		if (c == 'e')
+			encrypt_loop++;
+		if (c == 'f')
+			find++;
+		if (c == 'o')
+			offset = atoi(optarg);
+		if (c == 'v')
+			_switches[VERBOSE_ARG]++;
+	}
+
+	*argv += optind ;
+	*argc -= optind ;
+
+	if (encrypt_loop){
+		fprintf(stderr, "%s: Sorry, cryptoloop is not yet implemented "
+				"in this version.\n", base);
+		return 0;
+	}
+
+	if (show_all) {
+		fprintf(stderr, "%s: Sorry, show all is not yet implemented "
+				"in this version.\n", base);
+		return 0;
+	}
+
+	if (find) {
+		fprintf(stderr, "%s: Sorry, find is not yet implemented "
+				"in this version.\n", base);
+		if (!*argc)
+			return 0;
+	}
+
+	if (!*argc) {
+		fprintf(stderr, "%s: Please specify loop_device.\n", base);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	if (!(device_name = parse_loop_device_name((*argv)[0]))) {
+		fprintf(stderr, "%s: Could not parse loop_device %s\n",
+			base, (*argv)[0]);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	if (delete) {
+		*argc = 2;
+
+		(*argv)[1] = device_name;
+		(*argv)[0] = (char *) "remove";
+
+		return 1;
+	}
+
+	if (*argc != 2) {
+		fprintf(stderr, "%s: Too few arguments\n", base);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	/* FIXME move these to make them available to native dmsetup */
+	if (!(loop_file = _get_abspath((*argv)[(find) ? 0 : 1]))) {
+		fprintf(stderr, "%s: Could not parse loop file name %s\n",
+			base, (*argv)[1]);
+		_losetup_usage(stderr);
+		return 0;
+	}
+
+	/* FIXME Missing free */
+	_table = dm_malloc(LOOP_TABLE_SIZE);
+	if (!_loop_table(_table, LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
+		fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
+		return 0;
+	}
+	_switches[TABLE_ARG]++;
+
+	(*argv)[0] = (char *) "create";
+	(*argv)[1] = device_name ;
+
+	return 1;
+}
+
 static int _process_switches(int *argc, char ***argv)
 {
 	char *base, *namebase;
 	static int ind;
-	int c;
+	int c, r;
 
 #ifdef HAVE_GETOPTLONG
 	static struct option long_options[] = {
@@ -1606,11 +1862,13 @@
 		{"major", 1, &ind, MAJOR_ARG},
 		{"minor", 1, &ind, MINOR_ARG},
 		{"mode", 1, &ind, MODE_ARG},
+		{"noflush", 0, &ind, NOFLUSH_ARG},
 		{"noheadings", 0, &ind, NOHEADINGS_ARG},
 		{"nolockfs", 0, &ind, NOLOCKFS_ARG},
 		{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
 		{"notable", 0, &ind, NOTABLE_ARG},
 		{"options", 1, &ind, OPTIONS_ARG},
+		{"table", 1, &ind, TABLE_ARG},
 		{"target", 1, &ind, TARGET_ARG},
 		{"tree", 0, &ind, TREE_ARG},
 		{"uid", 1, &ind, UID_ARG},
@@ -1661,12 +1919,20 @@
 		return 1;
 	}
 
+	if(!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
+		r = _process_losetup_switches(base, argc, argv);
+		free(namebase);
+		return r;
+	}
+
 	free(namebase);
 
 	optarg = 0;
 	optind = OPTIND_INIT;
 	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfG:j:m:M:no:ru:U:v",
 					    long_options, NULL)) != -1) {
+		if (c == ':' || c == '?')
+			return 0;
 		if (c == 'c' || c == 'C' || ind == COLS_ARG)
 			_switches[COLS_ARG]++;
 		if (c == 'f' || ind == FORCE_ARG)
@@ -1714,12 +1980,18 @@
 			_switches[TARGET_ARG]++;
 			_target = optarg;
 		}
+		if ((ind == NOFLUSH_ARG))
+			_switches[NOFLUSH_ARG]++;
 		if ((ind == NOHEADINGS_ARG))
 			_switches[NOHEADINGS_ARG]++;
 		if ((ind == NOLOCKFS_ARG))
 			_switches[NOLOCKFS_ARG]++;
 		if ((ind == NOOPENCOUNT_ARG))
 			_switches[NOOPENCOUNT_ARG]++;
+		if ((ind == TABLE_ARG)) {
+			_switches[TABLE_ARG]++;
+			_table = optarg;
+		}
 		if ((ind == TREE_ARG))
 			_switches[TREE_ARG]++;
 		if ((ind == VERSION_ARG))
@@ -1745,6 +2017,11 @@
 	if (_switches[TREE_ARG] && !_process_tree_options(_fields))
 		return 0;
 
+	if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
+		fprintf(stderr, "--table and --notable are incompatible.\n");
+		return 0;
+	}
+
 	*argv += optind;
 	*argc -= optind;
 	return 1;
@@ -1755,7 +2032,7 @@
 	struct command *c;
 	int r = 1;
 
-        (void) setlocale(LC_ALL, "");
+	(void) setlocale(LC_ALL, "");
 
 	if (!_process_switches(&argc, &argv)) {
 		fprintf(stderr, "Couldn't process command line.\n");

Modified: devmapper/trunk/include/configure.h.in
==============================================================================
--- devmapper/trunk/include/configure.h.in	(original)
+++ devmapper/trunk/include/configure.h.in	Mon Oct 23 08:43:05 2006
@@ -3,6 +3,9 @@
 /* Define to 1 if the `closedir' function returns void instead of `int'. */
 #undef CLOSEDIR_VOID
 
+/* Define to 1 if canonicalize_file_name is available. */
+#undef HAVE_CANONICALIZE_FILE_NAME
+
 /* Define to 1 if you have the <ctype.h> header file. */
 #undef HAVE_CTYPE_H
 
@@ -113,6 +116,9 @@
 /* Define to 1 if you have the <sys/param.h> header file. */
 #undef HAVE_SYS_PARAM_H
 
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 

Modified: devmapper/trunk/kernel/ioctl/dm-ioctl.h
==============================================================================
--- devmapper/trunk/kernel/ioctl/dm-ioctl.h	(original)
+++ devmapper/trunk/kernel/ioctl/dm-ioctl.h	Mon Oct 23 08:43:05 2006
@@ -8,7 +8,9 @@
 #ifndef _LINUX_DM_IOCTL_V4_H
 #define _LINUX_DM_IOCTL_V4_H
 
-#include <linux/types.h>
+#ifdef linux
+#  include <linux/types.h>
+#endif
 
 #define DM_DIR "mapper"		/* Slashes not supported */
 #define DM_MAX_TYPE_NAME 16
@@ -285,9 +287,9 @@
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	8
+#define DM_VERSION_MINOR	11
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2006-06-08)"
+#define DM_VERSION_EXTRA	"-ioctl (2006-10-12)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
@@ -323,4 +325,9 @@
  */
 #define DM_SKIP_LOCKFS_FLAG	(1 << 10) /* In */
 
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG		(1 << 11) /* In */
+
 #endif				/* _LINUX_DM_IOCTL_H */

Modified: devmapper/trunk/lib/.exported_symbols
==============================================================================
--- devmapper/trunk/lib/.exported_symbols	(original)
+++ devmapper/trunk/lib/.exported_symbols	Mon Oct 23 08:43:05 2006
@@ -28,6 +28,7 @@
 dm_task_set_mode
 dm_task_suppress_identical_reload
 dm_task_add_target
+dm_task_no_flush
 dm_task_no_open_count
 dm_task_skip_lockfs
 dm_task_update_nodes
@@ -111,3 +112,6 @@
 dm_hash_get_next
 dm_set_selinux_context
 dm_task_set_geometry
+dm_split_lvm_name
+dm_split_words
+dm_snprintf

Modified: devmapper/trunk/lib/Makefile.in
==============================================================================
--- devmapper/trunk/lib/Makefile.in	(original)
+++ devmapper/trunk/lib/Makefile.in	Mon Oct 23 08:43:05 2006
@@ -23,6 +23,7 @@
 	libdm-common.c \
 	libdm-file.c \
 	libdm-deptree.c \
+	libdm-string.c \
 	mm/abi.c \
 	mm/dbg_malloc.c \
 	mm/pool.c \

Modified: devmapper/trunk/lib/ioctl/libdm-iface.c
==============================================================================
--- devmapper/trunk/lib/ioctl/libdm-iface.c	(original)
+++ devmapper/trunk/lib/ioctl/libdm-iface.c	Mon Oct 23 08:43:05 2006
@@ -1026,6 +1026,13 @@
 	return 1;
 }
 
+int dm_task_no_flush(struct dm_task *dmt)
+{
+	dmt->no_flush = 1;
+
+	return 1;
+}
+
 int dm_task_no_open_count(struct dm_task *dmt)
 {
 	dmt->no_open_count = 1;
@@ -1270,6 +1277,8 @@
 
 	if (dmt->type == DM_DEVICE_SUSPEND)
 		dmi->flags |= DM_SUSPEND_FLAG;
+	if (dmt->no_flush)
+		dmi->flags |= DM_NOFLUSH_FLAG;
 	if (dmt->read_only)
 		dmi->flags |= DM_READONLY_FLAG;
 	if (dmt->skip_lockfs)
@@ -1543,7 +1552,7 @@
 		dmi->flags |= DM_SKIP_BDGET_FLAG;
 
 	log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
-		  "%s%c %.0llu %s [%u]",
+		  "%s%c%c%s %.0llu %s [%u]",
 		  _cmd_data_v4[dmt->type].name,
 		  dmi->name, dmi->uuid, dmt->newname ? " " : "",
 		  dmt->newname ? dmt->newname : "",
@@ -1554,6 +1563,8 @@
 		  dmt->major > 0 && dmt->minor == 0 ? "0" : "",
 		  dmt->major > 0 ? ") " : "",
 		  dmt->no_open_count ? 'N' : 'O',
+		  dmt->no_flush ? 'N' : 'F',
+		  dmt->skip_lockfs ? "S " : "",
 		  dmt->sector, dmt->message ? dmt->message : "",
 		  dmi->data_size);
 #ifdef DM_IOCTLS

Modified: devmapper/trunk/lib/ioctl/libdm-targets.h
==============================================================================
--- devmapper/trunk/lib/ioctl/libdm-targets.h	(original)
+++ devmapper/trunk/lib/ioctl/libdm-targets.h	Mon Oct 23 08:43:05 2006
@@ -52,6 +52,7 @@
 	char *message;
 	char *geometry;
 	uint64_t sector;
+	int no_flush;
 	int no_open_count;
 	int skip_lockfs;
 	int suppress_identical_reload;

Modified: devmapper/trunk/lib/libdevmapper.h
==============================================================================
--- devmapper/trunk/lib/libdevmapper.h	(original)
+++ devmapper/trunk/lib/libdevmapper.h	Mon Oct 23 08:43:05 2006
@@ -17,6 +17,7 @@
 #define LIB_DEVICE_MAPPER_H
 
 #include <inttypes.h>
+#include <stdarg.h>
 #include <sys/types.h>
 
 #ifdef linux
@@ -150,6 +151,7 @@
 int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
 int dm_task_set_message(struct dm_task *dmt, const char *message);
 int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
+int dm_task_no_flush(struct dm_task *dmt);
 int dm_task_no_open_count(struct dm_task *dmt);
 int dm_task_skip_lockfs(struct dm_task *dmt);
 int dm_task_suppress_identical_reload(struct dm_task *dmt);
@@ -591,4 +593,28 @@
  *********/
 int dm_set_selinux_context(const char *path, mode_t mode);
 
+/*********************
+ * string manipulation
+ *********************/
+
+/*
+ * Break up the name of a mapped device into its constituent
+ * Volume Group, Logical Volume and Layer (if present).
+ */
+int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
+		      char **vgname, char **lvname, char **layer);
+
+/*
+ * Destructively split buffer into NULL-separated words in argv.
+ * Returns number of words.
+ */
+int dm_split_words(char *buffer, unsigned max,
+		   unsigned ignore_comments, /* Not implemented */
+		   char **argv);
+
+/* 
+ * Returns -1 if buffer too small
+ */
+int dm_snprintf(char *buf, size_t bufsize, const char *format, ...);
+
 #endif				/* LIB_DEVICE_MAPPER_H */

Modified: devmapper/trunk/lib/libdm-deptree.c
==============================================================================
--- devmapper/trunk/lib/libdm-deptree.c	(original)
+++ devmapper/trunk/lib/libdm-deptree.c	Mon Oct 23 08:43:05 2006
@@ -1047,7 +1047,7 @@
 			continue;
 
 		if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
-		    !info.exists)
+		    !info.exists || info.suspended)
 			continue;
 
 		if (!_suspend_node(name, info.major, info.minor,

Added: devmapper/trunk/lib/libdm-string.c
==============================================================================
--- (empty file)
+++ devmapper/trunk/lib/libdm-string.c	Mon Oct 23 08:43:05 2006
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "libdevmapper.h"
+
+#include <ctype.h>
+
+/*
+ * consume characters while they match the predicate function.
+ */
+static char *_consume(char *buffer, int (*fn) (int))
+{
+	while (*buffer && fn(*buffer))
+		buffer++;
+
+	return buffer;
+}
+
+static int _isword(int c)
+{
+	return !isspace(c);
+}
+
+/*
+ * Split buffer into NULL-separated words in argv.
+ * Returns number of words.
+ */
+int dm_split_words(char *buffer, unsigned max, unsigned ignore_comments,
+		   char **argv)
+{
+	unsigned arg;
+
+	for (arg = 0; arg < max; arg++) {
+		buffer = _consume(buffer, isspace);
+		if (!*buffer)
+			break;
+
+		argv[arg] = buffer;
+		buffer = _consume(buffer, _isword);
+
+		if (*buffer) {
+			*buffer = '\0';
+			buffer++;
+		}
+	}
+
+	return arg;
+}
+
+/*
+ * Remove hyphen quoting from a component of a name.
+ * NULL-terminates the component and returns start of next component.
+ */
+static char *_unquote(char *component)
+{
+	char *c = component;
+	char *o = c;
+	char *r;
+
+	while (*c) {
+		if (*(c + 1)) {
+			if (*c == '-') {
+				if (*(c + 1) == '-')
+					c++;
+				else
+					break;
+			}
+		}
+		*o = *c;
+		o++;
+		c++;
+	}
+
+	r = (*c) ? c + 1 : c;
+	*o = '\0';
+
+	return r;
+}
+
+int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
+		      char **vgname, char **lvname, char **layer)
+{
+	if (!(*vgname = dm_pool_strdup(mem, dmname)))
+		return 0;
+
+	_unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
+
+	return 1;
+}
+
+/*
+ * On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
+ * From glibc 2.1 it returns number of chars (excl. trailing null) that would 
+ * have been written had there been room.
+ *
+ * dm_snprintf reverts to the old behaviour.
+ */
+int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
+{
+	int n;
+	va_list ap;
+
+	va_start(ap, format);
+	n = vsnprintf(buf, bufsize, format, ap);
+	va_end(ap);
+
+	if (n < 0 || (n > bufsize - 1))
+		return -1;
+
+	return n;
+}

Modified: devmapper/trunk/lib/mm/dbg_malloc.c
==============================================================================
--- devmapper/trunk/lib/mm/dbg_malloc.c	(original)
+++ devmapper/trunk/lib/mm/dbg_malloc.c	Mon Oct 23 08:43:05 2006
@@ -83,15 +83,6 @@
 	nb->length = s;
 	nb->id = ++_mem_stats.block_serialno;
 	nb->next = 0;
-	nb->prev = _tail;
-
-	/* link to tail of the list */
-	if (!_head)
-		_head = _tail = nb;
-	else {
-		_tail->next = nb;
-		_tail = nb;
-	}
 
 	/* stomp a pretty pattern across the new memory
 	   and fill in the boundary bytes */
@@ -105,6 +96,16 @@
 			*ptr++ = (char) nb->id;
 	}
 
+	nb->prev = _tail;
+
+	/* link to tail of the list */
+	if (!_head)
+		_head = _tail = nb;
+	else {
+		_tail->next = nb;
+		_tail = nb;
+	}
+
 	_mem_stats.blocks_allocated++;
 	if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
 		_mem_stats.blocks_max = _mem_stats.blocks_allocated;
@@ -140,12 +141,6 @@
 
 	/* have we freed this before ? */
 	assert(mb->id != 0);
-	mb->id = 0;
-
-	/* stomp a different pattern across the memory */
-	ptr = ((char *) mb) + sizeof(struct memblock);
-	for (i = 0; i < mb->length; i++)
-		*ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
 
 	/* unlink */
 	if (mb->prev)
@@ -158,6 +153,13 @@
 	else
 		_tail = mb->prev;
 
+	mb->id = 0;
+
+	/* stomp a different pattern across the memory */
+	ptr = ((char *) mb) + sizeof(struct memblock);
+	for (i = 0; i < mb->length; i++)
+		*ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
+
 	assert(_mem_stats.blocks_allocated);
 	_mem_stats.blocks_allocated--;
 	_mem_stats.bytes -= mb->length;

Modified: devmapper/trunk/man/dmsetup.8
==============================================================================
--- devmapper/trunk/man/dmsetup.8	(original)
+++ devmapper/trunk/man/dmsetup.8	Mon Oct 23 08:43:05 2006
@@ -4,7 +4,7 @@
 .SH SYNOPSIS
 .ad l
 .B dmsetup create 
-.I device_name [-u uuid] [--notable] [table_file]
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
 .br
 .B dmsetup remove
 .I [-f|--force] device_name
@@ -13,19 +13,19 @@
 .I [-f|--force]
 .br
 .B dmsetup suspend
-.I [--nolockfs] device_name
+.I [--nolockfs] [--noflush] device_name
 .br
 .B dmsetup resume
 .I device_name
 .br
 .B dmsetup load
-.I device_name [table_file]
+.I device_name [--table <table> | table_file]
 .br
 .B dmsetup clear
 .I device_name
 .br
 .B dmsetup reload
-.I device_name [table_file]
+.I device_name [--table <table> | table_file]
 .br
 .B dmsetup rename
 .I device_name new_name
@@ -101,6 +101,9 @@
 .IP \fB-r|--readonly
 .br
 Set the table being loaded read-only.
+.IP \fB--table\ <table>
+.br
+Specify a one-line table directly on the command line.
 .IP \fB-u|--uuid
 .br
 Specify the uuid.
@@ -112,10 +115,10 @@
 Display the library and kernel driver version.
 .SH COMMANDS
 .IP \fBcreate
-.I device_name [-u uuid] [--notable] [table_file]
+.I device_name [-u uuid] [--notable | --table <table> | table_file]
 .br
 Creates a device with the given name.
-If table_file is supplied, the table is loaded and made live.
+If table_file or <table> is supplied, the table is loaded and made live.
 Otherwise a table is read from standard input unless --notable is used.
 The optional uuid can be used in place of
 device_name in subsequent dmsetup commands.  
@@ -160,10 +163,10 @@
 Others specify how the tree is displayed:
 ascii, utf, vt100; compact, inverted, notrunc.
 .IP \fBload|reload
-.I device_name [table_file]
+.I device_name [--table <table> | table_file]
 .br
-Loads table_file into the inactive table slot for device_name.
-If table_file is not supplied, reads a table from standard input.
+Loads <table> or table_file into the inactive table slot for device_name.
+If neither is supplied, reads a table from standard input.
 .IP \fBmknodes
 .I [device_name]
 .br
@@ -210,7 +213,7 @@
 With --target, only information relating to the specified target type
 is displayed.
 .IP \fBsuspend
-.I [--nolockfs]
+.I [--nolockfs] [--noflush]
 .I device_name
 .br
 Suspends a device.  Any I/O that has already been mapped by the device
@@ -218,6 +221,9 @@
 device will be postponed for as long as the device is suspended.
 If there's a filesystem on the device which supports the operation, 
 an attempt will be made to sync it first unless --nolockfs is specified.
+Some targets such as recent (October 2006) versions of multipath may support
+the --noflush option.  This lets outstanding I/O that has not yet reached the
+device to remain unflushed.
 .IP \fBtable
 .I [--target target_type]
 .I [device_name]



More information about the pkg-lvm-commits mailing list