Index: Makefile =================================================================== RCS file: Makefile diff -N Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Makefile 19 Dec 2008 00:00:15 -0000 @@ -0,0 +1,7 @@ +.include + +.if (${MKLVM} != "no") +SUBDIR+= lvm2tools +.endif + +.include Index: ./lvm2tools/Makefile =================================================================== RCS file: ./lvm2tools/Makefile diff -N ./lvm2tools/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/Makefile 19 Dec 2008 00:00:15 -0000 @@ -0,0 +1,9 @@ +# $NetBSD$ + +.include "lvm2tools.mk" + +SUBDIR+= lib .WAIT + +SUBDIR+= sbin + +.include Index: ./lvm2tools/lvm2tools.mk =================================================================== RCS file: ./lvm2tools/lvm2tools.mk diff -N ./lvm2tools/lvm2tools.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lvm2tools.mk 19 Dec 2008 00:00:15 -0000 @@ -0,0 +1,21 @@ +# $NetBSD$ + +.include + +LVM2TOOLS_SRCDIR= ${NETBSDSRCDIR}/external/gpl2/lvm2tools +LVM2TOOLS_DISTDIR= ${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist + +LVM2TOOLS_PREFIX= / + +LIBDM_SRCDIR= ${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist/libdm +LIBDM_INCLUDE= ${NETBSDSRCDIR}/external/gpl2/lvm2tools/dist/include + +# +#LIBDM_OBJDIR.libdevmapper=${LIBDM_SRCDIR}/lib/libdevmapper/ +# +#.if !defined(LVM2TOOLSOBJDIR.liblvm) +#LVM2TOOLSOBJDIR.liblvm!= cd ${LVM2TOOLS_SRCDIR}/lib/liblvm && ${PRINTOBJDIR} +#.MAKEOVERRIDES+= LVM2TOOLSOBJDIR.liblvm +#.endif +# +#LVM2TOOLS.liblvm= ${LVM2TOOLSOBJDIR.liblvm}/liblvm.a Index: ./lvm2tools/dist/include/netbsd.h =================================================================== RCS file: ./lvm2tools/dist/include/netbsd.h diff -N ./lvm2tools/dist/include/netbsd.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/include/netbsd.h 19 Dec 2008 00:00:15 -0000 @@ -0,0 +1,13 @@ + +/* + * NetBSD specific header file. + */ + +#ifndef __NETBSD_H__ +#define __NETBSD_H__ + + +/* lib/netbsd/netbsd.c */ +int nbsd_check_dev(int, const char *); + +#endif Index: ./lvm2tools/dist/lib/activate/fs.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/lib/activate/fs.c,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 fs.c --- ./lvm2tools/dist/lib/activate/fs.c 12 Dec 2008 11:42:24 -0000 1.1.1.2 +++ ./lvm2tools/dist/lib/activate/fs.c 19 Dec 2008 00:00:16 -0000 @@ -101,6 +101,20 @@ static void _rm_blks(const char *dir) if (unlink(path) < 0) log_sys_error("unlink", path); } +#ifdef __NetBSD__ + if (dm_snprintf(path, sizeof(path), "%s/r%s", dir, name) == -1) { + log_error("Couldn't create path for r%s", name); + continue; + } + + if (!lstat(path, &buf)) { + if (!S_ISCHR(buf.st_mode)) + continue; + log_very_verbose("Removing %s", path); + if (unlink(path) < 0) + log_sys_error("unlink", path); + } +#endif } } @@ -111,6 +125,11 @@ static int _mk_link(const char *dev_dir, char vg_path[PATH_MAX]; struct stat buf; +#ifdef __NetBSD__ + /* Add support for creating links to BSD raw devices */ + char raw_lv_path[PATH_MAX], raw_link_path[PATH_MAX]; +#endif + if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s", dev_dir, vg_name) == -1) { log_error("Couldn't create path for volume group dir %s", @@ -118,6 +137,42 @@ static int _mk_link(const char *dev_dir, return 0; } +#ifdef __NetBSD__ + if (dm_snprintf(raw_lv_path, sizeof(raw_lv_path), "%s/r%s", vg_path, + lv_name) == -1) { + log_error("Couldn't create source pathname for " + "logical volume link r%s", lv_name); + return 0; + } + + if (dm_snprintf(raw_link_path, sizeof(raw_link_path), "%s/r%s", + dm_dir(), dev) == -1) { + log_error("Couldn't create destination pathname for " + "logical volume link for %s", lv_name); + return 0; + } + + if (!lstat(raw_lv_path, &buf)) { + if (!S_ISLNK(buf.st_mode) && !S_ISCHR(buf.st_mode)) { + log_error("Symbolic link %s not created: file exists", + raw_link_path); + return 0; + } + + log_very_verbose("Removing %s", raw_lv_path); + if (unlink(raw_lv_path) < 0) { + log_sys_error("unlink", raw_lv_path); + return 0; + } + } + + log_very_verbose("Linking %s -> %s", raw_lv_path, raw_link_path); + if (symlink(raw_link_path, raw_lv_path) < 0) { + log_sys_error("symlink", raw_lv_path); + return 0; + } + +#endif if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path, lv_name) == -1) { log_error("Couldn't create source pathname for " @@ -190,6 +245,29 @@ static int _rm_link(const char *dev_dir, struct stat buf; char lv_path[PATH_MAX]; +#ifdef __NetBSD__ + /* Add support for removing links to BSD raw devices */ + char raw_lv_path[PATH_MAX]; + + if (dm_snprintf(raw_lv_path, sizeof(raw_lv_path), "%s%s/r%s", + dev_dir, vg_name, lv_name) == -1) { + log_error("Couldn't determine link pathname."); + return 0; + } + + if (lstat(raw_lv_path, &buf) || !S_ISLNK(buf.st_mode)) { + if (errno == ENOENT) + return 1; + log_error("%s not symbolic link - not removing", raw_lv_path); + return 0; + } + + log_very_verbose("Removing link %s", raw_lv_path); + if (unlink(raw_lv_path) < 0) { + log_sys_error("unlink", raw_lv_path); + return 0; + } +#endif if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s", dev_dir, vg_name, lv_name) == -1) { log_error("Couldn't determine link pathname."); Index: ./lvm2tools/dist/lib/commands/toolcontext.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/lib/commands/toolcontext.c,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 toolcontext.c --- ./lvm2tools/dist/lib/commands/toolcontext.c 12 Dec 2008 11:42:15 -0000 1.1.1.2 +++ ./lvm2tools/dist/lib/commands/toolcontext.c 19 Dec 2008 00:00:16 -0000 @@ -220,6 +220,8 @@ static int _process_config(struct cmd_co #ifdef DEVMAPPER_SUPPORT dm_set_dev_dir(cmd->dev_dir); #endif +#ifndef __NetBSD__ + /* proc dir */ if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s", @@ -228,11 +230,11 @@ static int _process_config(struct cmd_co log_error("Device directory given in config file too long"); return 0; } - +#endif if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) { log_error("WARNING: proc dir %s not found - some checks will be bypassed", cmd->proc_dir); - cmd->proc_dir[0] = '\0'; + *cmd->proc_dir = '\0'; } _get_sysfs_dir(cmd); Index: ./lvm2tools/dist/lib/device/dev-cache.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/lib/device/dev-cache.c,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 dev-cache.c --- ./lvm2tools/dist/lib/device/dev-cache.c 12 Dec 2008 11:42:18 -0000 1.1.1.2 +++ ./lvm2tools/dist/lib/device/dev-cache.c 19 Dec 2008 00:00:17 -0000 @@ -27,6 +27,10 @@ #include #include +#ifdef __NetBSD__ +#include "netbsd.h" +#endif + struct dev_iter { struct btree_iter *current; struct dev_filter *filter; @@ -423,14 +427,26 @@ static int _insert(const char *path, int if (rec) r = _insert_dir(path); - } else { /* add a device */ - if (!S_ISBLK(info.st_mode)) { - log_debug("%s: Not a block device", path); - return 0; + } else { + /* add a device */ +#ifdef __NetBSD__ + /* + * In NetBSD we have two different types of devices + * raw and block. I can insert only existing + * raw and block device. + */ + if (nbsd_check_dev(MAJOR(info.st_rdev),path) < 0) { + log_debug("%s: Not a block device.", path); + return_0; } - if (!_insert_dev(path, info.st_rdev)) +#else + if (!S_ISBLK(info.st_mode)) + log_debug("%s: Not a block device", path); +#endif + if (!_insert_dev(path, info.st_rdev)) { return_0; + } r = 1; } Index: ./lvm2tools/dist/lib/device/dev-io.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/lib/device/dev-io.c,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 dev-io.c --- ./lvm2tools/dist/lib/device/dev-io.c 12 Dec 2008 11:42:19 -0000 1.1.1.2 +++ ./lvm2tools/dist/lib/device/dev-io.c 19 Dec 2008 00:00:17 -0000 @@ -38,6 +38,10 @@ # ifndef BLKGETSIZE64 /* fs.h out-of-date */ # define BLKGETSIZE64 _IOR(0x12, 114, size_t) # endif /* BLKGETSIZE64 */ +#elif __NetBSD__ +# include +# include +# include #else # include # define BLKBSZGET DKIOCGETBLOCKSIZE @@ -127,12 +131,22 @@ static int _io(struct device_area *where static int _get_block_size(struct device *dev, unsigned int *size) { const char *name = dev_name(dev); +#ifdef __NetBSD__ + struct disklabel lab; +#endif if ((dev->block_size == -1)) { +#ifdef __NetBSD__ + if (ioctl(dev_fd(dev), DIOCGDINFO, &lab) < 0) { + dev->block_size = DEV_BSIZE; + } else + dev->block_size = lab.d_secsize; +#else if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); return 0; } +#endif log_debug("%s: block size is %u bytes", name, dev->block_size); } @@ -242,12 +256,35 @@ static int _dev_get_size_dev(const struc { int fd; const char *name = dev_name(dev); +#ifdef __NetBSD__ + struct disklabel lab; + struct dkwedge_info dkw; +#endif if ((fd = open(name, O_RDONLY)) < 0) { log_sys_error("open", name); return 0; + } + +#ifdef __NetBSD__ + if ((*size = lseek (fd, 0, SEEK_END)) < 0) { + log_sys_error("lseek SEEK_END", name); + close(fd); + return 0; } + if (ioctl(fd, DIOCGDINFO, &lab) < 0) { + if (ioctl(fd, DIOCGWEDGEINFO, &dkw) < 0) { + log_sys_error("ioctl DIOCGWEDGEINFO", name); + close(fd); + return 0; + } else + if (dkw.dkw_size) + *size = dkw.dkw_size; + } else + if (lab.d_secsize) + *size /= lab.d_secsize; +#else if (ioctl(fd, BLKGETSIZE64, size) < 0) { log_sys_error("ioctl BLKGETSIZE64", name); if (close(fd)) @@ -256,6 +293,7 @@ static int _dev_get_size_dev(const struc } *size >>= BLKSIZE_SHIFT; /* Convert to sectors */ +#endif if (close(fd)) log_sys_error("close", name); @@ -308,8 +346,10 @@ int dev_get_sectsize(struct device *dev, void dev_flush(struct device *dev) { +#ifdef __linux__ if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0) return; +#endif if (fsync(dev->fd) >= 0) return; Index: ./lvm2tools/dist/lib/filters/filter_netbsd.c =================================================================== RCS file: ./lvm2tools/dist/lib/filters/filter_netbsd.c diff -N ./lvm2tools/dist/lib/filters/filter_netbsd.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/lib/filters/filter_netbsd.c 19 Dec 2008 00:00:17 -0000 @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2008 Adam Hamsik. All rights reserved. + * + * This file is part of LVM2. + * + * 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "dev-cache.h" +#include "filter.h" +#include "lvm-string.h" +#include "config.h" +#include "metadata.h" +#include "activate.h" + +#include + +#include +#include +#include +#include +#include + +#define NUMBER_OF_MAJORS 4096 + +#define LVM_SUCCESS 1 +#define LVM_FAILURE 0 + +/* -1 means LVM won't use this major number. */ +static int _char_device_major[NUMBER_OF_MAJORS]; +static int _block_device_major[NUMBER_OF_MAJORS]; + +typedef struct { + const char *name; + const int max_partitions; +} device_info_t; + +static int _md_major = -1; +static int _device_mapper_major = -1; + +int md_major(void) +{ + return _md_major; +} + +/* + * Devices are only checked for partition tables if their minor number + * is a multiple of the number corresponding to their type below + * i.e. this gives the granularity of whole-device minor numbers. + * Use 1 if the device is not partitionable. + * + * The list can be supplemented with devices/types in the config file. + */ +static const device_info_t device_info[] = { + {"wd", 64}, + {"sd", 64}, + {"dk", 1}, + {"wd", 64}, + {"vnd", 1}, + {"raid", 64}, + {"cgd", 1}, + {"ccd", 1}, + {NULL, -1} +}; + +/* + * Test if device passes filter tests and can be inserted in to cache. + */ +static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)), + struct device *dev) +{ + const char *name = dev_name(dev); + int ret = 0; + uint64_t size; + + /* Is this a recognised device type? */ + if (_char_device_major[MAJOR(dev->dev)] == -1 ){ + log_debug("%s: Skipping: Unrecognised LVM device type %" + PRIu64, name, (uint64_t) MAJOR(dev->dev)); + return LVM_FAILURE; + } + + /* Skip suspended devices */ + if (MAJOR(dev->dev) == _device_mapper_major && + ignore_suspended_devices() && !device_is_usable(dev->dev)) { + log_debug("%s: Skipping: Suspended dm device", name); + return LVM_FAILURE; + } + + /* Check it's accessible */ + if (!dev_open_flags(dev, O_RDONLY, 0, 1)) { + log_debug("%s: Skipping: open failed", name); + return LVM_FAILURE; + } + + /* Check it's not too small */ + if (!dev_get_size(dev, &size)) { + log_debug("%s: Skipping: dev_get_size failed", name); + goto out; + } + + if (size < PV_MIN_SIZE) { + log_debug("%s: Skipping: Too small to hold a PV", name); + goto out; + } + + if (is_partitioned_dev(dev)) { + log_debug("%s: Skipping: Partition table signature found", + name); + goto out; + } + + ret = LVM_SUCCESS; + + out: + dev_close(dev); + + return ret; +} + +static int _scan_dev(const struct config_node *cn) +{ + size_t val_len,i,j; + char *name; + + struct kinfo_drivers *kd; + struct config_value *cv; + + /* All types unrecognised initially */ + memset(_char_device_major, -1, sizeof(int) * NUMBER_OF_MAJORS); + memset(_block_device_major, -1, sizeof(int) * NUMBER_OF_MAJORS); + + /* get size kernel drivers array from kernel*/ + if (sysctlbyname("kern.drivers", NULL, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed"); + return LVM_FAILURE; + } + + if ((kd = malloc(val_len)) == NULL){ + printf("malloc kd info error\n"); + return LVM_FAILURE; + } + + /* get array from kernel */ + if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed kd"); + return LVM_FAILURE; + } + + for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) { + + if (!strncmp("device-mapper", kd[i].d_name, 13) || + !strncmp("dm", kd[i].d_name, 2)) + _device_mapper_major = kd[i].d_bmajor; + + /* We select only devices with correct char/block major number. */ + if (kd[i].d_cmajor != -1 && kd[i].d_bmajor != -1) { + /* Go through the valid device names and if there is a + match store max number of partitions */ + for (j = 0; device_info[j].name != NULL; j++){ + if (!strcmp(device_info[j].name, kd[i].d_name)){ + _char_device_major[kd[i].d_cmajor] = + device_info[j].max_partitions; + _block_device_major[kd[i].d_bmajor] = + device_info[j].max_partitions; + break; + } + } + } + + if (!cn) + continue; + + /* Check devices/types for local variations */ + for (cv = cn->v; cv; cv = cv->next) { + if (cv->type != CFG_STRING) { + log_error("Expecting string in devices/types " + "in config file"); + free(kd); + return LVM_FAILURE; + } + + name = cv->v.str; + cv = cv->next; + if (!cv || cv->type != CFG_INT) { + log_error("Max partition count missing for %s " + "in devices/types in config file", + name); + free(kd); + return LVM_FAILURE; + } + if (!cv->v.i) { + log_error("Zero partition count invalid for " + "%s in devices/types in config file", + name); + free(kd); + return LVM_FAILURE; + } + + if (!strncmp(name, kd[i].d_name, strlen(name))){ + _char_device_major[kd[i].d_cmajor] = + device_info[j].max_partitions; + _block_device_major[kd[i].d_bmajor] = + device_info[j].max_partitions; + break; + } + } + } + + free(kd); + + return LVM_SUCCESS; +} + +int max_partitions(int major) +{ + return _char_device_major[major]; +} + +struct dev_filter *lvm_type_filter_create(const char *proc, + const struct config_node *cn) +{ + struct dev_filter *f; + + if (!(f = dm_malloc(sizeof(struct dev_filter)))) { + log_error("LVM type filter allocation failed"); + return NULL; + } + + f->passes_filter = _passes_lvm_type_device_filter; + f->destroy = lvm_type_filter_destroy; + f->private = NULL; + + if (!_scan_dev(cn)) { + dm_free(f); + return_NULL; + } + + return f; +} + +void lvm_type_filter_destroy(struct dev_filter *f) +{ + dm_free(f); + return; +} Index: ./lvm2tools/dist/lib/metadata/lv_manip.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/lib/metadata/lv_manip.c,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 lv_manip.c --- ./lvm2tools/dist/lib/metadata/lv_manip.c 12 Dec 2008 11:42:32 -0000 1.1.1.2 +++ ./lvm2tools/dist/lib/metadata/lv_manip.c 19 Dec 2008 00:00:18 -0000 @@ -2656,13 +2656,19 @@ int set_lv(struct cmd_context *cmd, stru log_error("Name allocation failed - device not cleared"); return 0; } - +#ifdef __NetBSD__ + if (dm_snprintf(name, PATH_MAX, "%s%s/r%s", cmd->dev_dir, + lv->vg->name, lv->name) < 0) { + log_error("Name too long - device not cleared (%s)", lv->name); + return 0; + } +#else if (dm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir, lv->vg->name, lv->name) < 0) { log_error("Name too long - device not cleared (%s)", lv->name); return 0; } - +#endif log_verbose("Clearing start of logical volume \"%s\"", lv->name); if (!(dev = dev_cache_get(name, NULL))) { Index: ./lvm2tools/dist/lib/netbsd/dev.c =================================================================== RCS file: ./lvm2tools/dist/lib/netbsd/dev.c diff -N ./lvm2tools/dist/lib/netbsd/dev.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/lib/netbsd/dev.c 19 Dec 2008 00:00:21 -0000 @@ -0,0 +1,70 @@ +/* + * NetBSD specific device routines are added to this file. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "netbsd.h" + +#define LVM_FAILURE -1 + +/* + * Find major numbers for char/block parts of all block devices. + * In NetBSD every block device has it's char counter part. + * Return success only for device drivers with defined char/block + * major numbers. + */ +int +nbsd_check_dev(int major, const char *path) +{ + + size_t val_len,i; + + struct kinfo_drivers *kd; + + /* XXX HACK */ + if (strcmp(path,"/dev/console") == 0) + return LVM_FAILURE; + + /* get size kernel drivers array from kernel*/ + if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) { + printf("sysctlbyname failed"); + return LVM_FAILURE; + } + + if ((kd = malloc (val_len)) == NULL){ + printf("malloc kd info error\n"); + return LVM_FAILURE; + } + + /* get array from kernel */ + if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed kd"); + return LVM_FAILURE; + } + + for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) + /* We select only devices with correct char/block major number. */ + if (kd[i].d_cmajor != -1 && kd[i].d_bmajor != -1) { + + if (kd[i].d_cmajor == major) + return kd[i].d_bmajor; + + if (kd[i].d_bmajor == major) + return kd[i].d_cmajor; + + } + + return LVM_FAILURE; +} Index: ./lvm2tools/dist/lib/netbsd/netbsd.h =================================================================== RCS file: ./lvm2tools/dist/lib/netbsd/netbsd.h diff -N ./lvm2tools/dist/lib/netbsd/netbsd.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/lib/netbsd/netbsd.h 19 Dec 2008 00:00:21 -0000 @@ -0,0 +1,13 @@ + +/* + * NetBSD specific header file. + */ + +#ifndef __NETBSD_H__ +#define __NETBSD_H__ + + +/* lib/netbsd/netbsd.c */ +int nbsd_check_dev(int, const char *); + +#endif Index: ./lvm2tools/dist/libdm/libdm-common.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/libdm/libdm-common.c,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 libdm-common.c --- ./lvm2tools/dist/libdm/libdm-common.c 12 Dec 2008 11:42:48 -0000 1.1.1.1 +++ ./lvm2tools/dist/libdm/libdm-common.c 19 Dec 2008 00:00:21 -0000 @@ -18,7 +18,9 @@ #include "dmlib.h" #include "libdm-targets.h" #include "libdm-common.h" +#ifdef linux #include "kdev_t.h" +#endif #include "dm-ioctl.h" #include @@ -34,6 +36,10 @@ # include #endif +#ifdef __NetBSD__ +#include +#endif + #define DEV_DIR "/dev/" static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR; @@ -268,6 +274,45 @@ static int _add_dev_node(const char *dev dev_t dev = MKDEV(major, minor); mode_t old_mask; + #ifdef __NetBSD__ + char rpath[PATH_MAX]; + uint32_t raw_major; + dev_t rdev; + char raw_devname[DM_NAME_LEN+1]; /* r + other device name */ + + nbsd_get_dm_major(&raw_major,DM_CHAR_MAJOR); + rdev = MKDEV(raw_major,minor); + + snprintf(raw_devname,sizeof(raw_devname),"r%s",dev_name); + + _build_dev_path(rpath, sizeof(rpath), raw_devname); + + if (stat(rpath, &info) >= 0) { + if (!S_ISCHR(info.st_mode)) { + log_error("A non-raw device file at '%s' " + "is already present", rpath); + return 0; + } + + /* If right inode already exists we don't touch uid etc. */ + if (info.st_rdev == rdev) + return 1; + + if (unlink(rpath) < 0) { + log_error("Unable to unlink device node for '%s'", + raw_devname); + return 0; + } + } + + old_mask = umask(0); + + if (mknod(rpath, S_IFCHR | mode, rdev) < 0) { + log_error("Unable to make device node for '%s'", raw_devname); + return 0; + } +#endif + _build_dev_path(path, sizeof(path), dev_name); if (stat(path, &info) >= 0) { @@ -316,6 +361,42 @@ static int _rename_dev_node(const char * char newpath[PATH_MAX]; struct stat info; +#ifdef __NetBSD__ + char rpath[PATH_MAX]; + char nrpath[PATH_MAX]; + char raw_devname[DM_NAME_LEN+1]; /* r + other device name */ + char nraw_devname[DM_NAME_LEN+1]; /* r + other device name */ + + snprintf(nraw_devname,sizeof(raw_devname),"r%s",new_name); + snprintf(raw_devname,sizeof(raw_devname),"r%s",old_name); + + _build_dev_path(nrpath, sizeof(nrpath), nraw_devname); + _build_dev_path(rpath, sizeof(rpath), raw_devname); + + if (stat(nrpath, &info) == 0) { + if (S_ISBLK(info.st_mode)) { + log_error("A block device file at '%s' " + "is present where raw device should be.", newpath); + return 0; + } + + if (unlink(nrpath) < 0) { + log_error("Unable to unlink device node for '%s'", + nraw_devname); + return 0; + } + } + + if (rename(rpath, nrpath) < 0) { + log_error("Unable to rename device node from '%s' to '%s'", + raw_devname, nraw_devname); + return 0; + } + + log_debug("Renamed %s to %s", rpath, nrpath); + +#endif + _build_dev_path(oldpath, sizeof(oldpath), old_name); _build_dev_path(newpath, sizeof(newpath), new_name); @@ -353,6 +434,25 @@ static int _rm_dev_node(const char *dev_ char path[PATH_MAX]; struct stat info; +#ifdef __NetBSD__ + char rpath[PATH_MAX]; + char raw_devname[DM_NAME_LEN+1]; /* r + other device name */ + + snprintf(raw_devname,sizeof(raw_devname),"r%s",dev_name); + + _build_dev_path(rpath, sizeof(rpath), raw_devname); + + if (stat(rpath, &info) < 0) + return 1; + + if (unlink(rpath) < 0) { + log_error("Unable to unlink device node for '%s'", raw_devname); + return 0; + } + + log_debug("Removed %s", rpath); +#endif + _build_dev_path(path, sizeof(path), dev_name); if (stat(path, &info) < 0) Index: ./lvm2tools/dist/libdm/libdm-deptree.c =================================================================== RCS file: /cvsroot/src/external/gpl2/lvm2tools/dist/libdm/libdm-deptree.c,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 libdm-deptree.c --- ./lvm2tools/dist/libdm/libdm-deptree.c 12 Dec 2008 11:42:50 -0000 1.1.1.1 +++ ./lvm2tools/dist/libdm/libdm-deptree.c 19 Dec 2008 00:00:22 -0000 @@ -1830,12 +1830,17 @@ int dm_tree_node_add_target_area(struct log_error("Device %s not found.", dev_name); return 0; } - +#ifndef __NetBSD__ if (!S_ISBLK(info.st_mode)) { log_error("Device %s is not a block device.", dev_name); return 0; } - +#else + if (S_ISBLK(info.st_mode)) { + log_error("Device %s is a block device. Use raw devices on NetBSD.", dev_name); + return 0; + } +#endif /* FIXME Check correct macro use */ if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), MINOR(info.st_rdev)))) return_0; Index: ./lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c =================================================================== RCS file: ./lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c diff -N ./lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/libdm/ioctl/libdm-nbsd-iface.c 19 Dec 2008 00:00:23 -0000 @@ -0,0 +1,1153 @@ +/* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2008 Adam Hamsik. 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "dmlib.h" +#include "libdm-targets.h" +#include "libdm-common.h" + +#include +#include + +#include +#include +#include + +#include + +#include + +/* + * Ensure build compatibility. + * The hard-coded versions here are the highest present + * in the _cmd_data arrays. + */ + +#if !((DM_VERSION_MAJOR == 1 && DM_VERSION_MINOR >= 0) || \ + (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0)) +#error The version of dm-ioctl.h included is incompatible. +#endif + +/* dm major version no for running kernel */ +static unsigned _dm_version_minor = 0; +static unsigned _dm_version_patchlevel = 0; + +static int _control_fd = -1; +static int _version_checked = 0; +static int _version_ok = 1; +static unsigned _ioctl_buffer_double_factor = 0; + +/* *INDENT-OFF* */ + +/* + * XXX Remove this structure and write another own one + * I don't understand why ioctl calls has different + * names then dm task type + */ +static struct cmd_data _cmd_data_v4[] = { + {"create", DM_DEV_CREATE, {4, 0, 0}}, + {"reload", DM_TABLE_LOAD, {4, 0, 0}}, /* DM_DEVICE_RELOAD */ + {"remove", DM_DEV_REMOVE, {4, 0, 0}}, + {"remove_all", DM_REMOVE_ALL, {4, 0, 0}}, + {"suspend", DM_DEV_SUSPEND, {4, 0, 0}}, + {"resume", DM_DEV_SUSPEND, {4, 0, 0}}, + {"info", DM_DEV_STATUS, {4, 0, 0}}, + {"deps", DM_TABLE_DEPS, {4, 0, 0}}, /* DM_DEVICE_DEPS */ + {"rename", DM_DEV_RENAME, {4, 0, 0}}, + {"version", DM_VERSION, {4, 0, 0}}, + {"status", DM_TABLE_STATUS, {4, 0, 0}}, + {"table", DM_TABLE_STATUS, {4, 0, 0}}, /* DM_DEVICE_TABLE */ + {"waitevent", DM_DEV_WAIT, {4, 0, 0}}, + {"names", DM_LIST_DEVICES, {4, 0, 0}}, + {"clear", DM_TABLE_CLEAR, {4, 0, 0}}, + {"mknodes", DM_DEV_STATUS, {4, 0, 0}}, +#ifdef DM_LIST_VERSIONS + {"targets", DM_LIST_VERSIONS, {4, 1, 0}}, +#endif +#ifdef DM_TARGET_MSG + {"message", DM_TARGET_MSG, {4, 2, 0}}, +#endif +#ifdef DM_DEV_SET_GEOMETRY + {"setgeometry", DM_DEV_SET_GEOMETRY, {4, 6, 0}}, +#endif +}; +/* *INDENT-ON* */ + +/* + * In NetBSD we use sysctl to get kernel drivers info. control device + * has predefined minor number 0 and major number = char major number + * of dm driver. First slot is therefore ocupied with control device + * and minor device starts from 1; + */ + +static int _control_device_number(uint32_t *major, uint32_t *minor) +{ + + nbsd_get_dm_major(major, DM_CHAR_MAJOR); + + *minor = 0; + + return 1; +} + +/* + * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong + */ +static int _control_exists(const char *control, uint32_t major, uint32_t minor) +{ + struct stat buf; + + if (stat(control, &buf) < 0) { + if (errno != ENOENT) + log_sys_error("stat", control); + return 0; + } + + if (!S_ISCHR(buf.st_mode)) { + log_verbose("%s: Wrong inode type", control); + if (!unlink(control)) + return 0; + log_sys_error("unlink", control); + return -1; + } + + if (major && buf.st_rdev != MKDEV(major, minor)) { + log_verbose("%s: Wrong device number: (%u, %u) instead of " + "(%u, %u)", control, + MAJOR(buf.st_mode), MINOR(buf.st_mode), + major, minor); + if (!unlink(control)) + return 0; + log_sys_error("unlink", control); + return -1; + } + + return 1; +} + +static int _create_control(const char *control, uint32_t major, uint32_t minor) +{ + int ret; + mode_t old_umask; + + if (!major) + return 0; + + old_umask = umask(0022); + ret = dm_create_dir(dm_dir()); + umask(old_umask); + + if (!ret) + return 0; + + log_verbose("Creating device %s (%u, %u)", control, major, minor); + + if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR, + MKDEV(major, minor)) < 0) { + log_sys_error("mknod", control); + return 0; + } + + + return 1; +} + +/* Check if major is device-mapper block device major number */ +int dm_is_dm_major(uint32_t major) +{ + uint32_t dm_major; + + nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR); + + if (major == dm_major) + return 1; + + return 0; +} + +/* Open control device if doesn't exist create it. */ +static int _open_control(void) +{ + char control[PATH_MAX]; + uint32_t major = 0, minor = 0; + + if (_control_fd != -1) + return 1; + + snprintf(control, sizeof(control), "%s/control", dm_dir()); + + if (!_control_device_number(&major, &minor)) + log_error("Is device-mapper driver missing from kernel?"); + + if (!_control_exists(control, major, minor) && + !_create_control(control, major, minor)) + goto error; + + if ((_control_fd = open(control, O_RDWR)) < 0) { + log_sys_error("open", control); + goto error; + } + + return 1; + +error: + log_error("Failure to communicate with kernel device-mapper driver."); + return 0; +} + +/* + * Destroy dm task structure there are some dynamically alocated values there. + * name, uuid, head, tail list. + */ +void dm_task_destroy(struct dm_task *dmt) +{ + struct target *t, *n; + + for (t = dmt->head; t; t = n) { + n = t->next; + dm_free(t->params); + dm_free(t->type); + dm_free(t); + } + + if (dmt->dev_name) + dm_free(dmt->dev_name); + + if (dmt->newname) + dm_free(dmt->newname); + + if (dmt->message) + dm_free(dmt->message); + + if (dmt->dmi.v4) + dm_free(dmt->dmi.v4); + + if (dmt->uuid) + dm_free(dmt->uuid); + + dm_free(dmt); + +} + +/* Get kernel driver version from dm_ioctl structure. */ +int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size) +{ + unsigned *v; + + if (!dmt->dmi.v4) { + version[0] = '\0'; + return 0; + } + + v = dmt->dmi.v4->version; + snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]); + _dm_version_minor = v[1]; + _dm_version_patchlevel = v[2]; + + return 1; +} + +/* Get kernel driver protocol version and comapre it with library version. */ +static int _check_version(char *version, size_t size) +{ + struct dm_task *task; + int r; + + if (!(task = dm_task_create(DM_DEVICE_VERSION))) { + log_error("Failed to get device-mapper version"); + version[0] = '\0'; + return 0; + } + + r = dm_task_run(task); + dm_task_get_driver_version(task, version, size); + dm_task_destroy(task); + + return r; +} + +/* + * Find out device-mapper's major version number the first time + * this is called and whether or not we support it. + */ +int dm_check_version(void) +{ + char dmversion[64]; + + if (_version_checked) + return _version_ok; + + _version_checked = 1; + + if (_check_version(dmversion, sizeof(dmversion))) + return 1; + + + return 0; +} + +/* Get next target(table description) from list pointed by dmt->head. */ +void *dm_get_next_target(struct dm_task *dmt, void *next, + uint64_t *start, uint64_t *length, + char **target_type, char **params) +{ + struct target *t = (struct target *) next; + + if (!t) + t = dmt->head; + + if (!t) + return NULL; + + *start = t->start; + *length = t->length; + *target_type = t->type; + *params = t->params; + + return t->next; +} + +/* Unmarshall the target info returned from a status call */ +static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi) +{ + char *outbuf = (char *) dmi + dmi->data_start; + char *outptr = outbuf; + uint32_t i; + struct dm_target_spec *spec; + + for (i = 0; i < dmi->target_count; i++) { + spec = (struct dm_target_spec *) outptr; + if (!dm_task_add_target(dmt, spec->sector_start, + spec->length, + spec->target_type, + outptr + sizeof(*spec))) { + return 0; + } + + outptr = outbuf + spec->next; + } + + return 1; +} + +/* + * @dev_major is major number of char device + * + * I have to find it's block device number and lookup dev in + * device database to find device path. + * + */ + +int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, + uint32_t dev_minor) +{ + int r; + uint32_t major, dm_major; + char *name; + mode_t mode; + dev_t dev; + size_t val_len,i; + struct kinfo_drivers *kd; + + mode = 0; + + nbsd_get_dm_major(&dm_major, DM_BLOCK_MAJOR); + + log_error("format_dev %d--%d %d", dev_major, dev_minor, bufsize); + + if (bufsize < 8) + return 0; + + if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) { + printf("sysctlbyname failed"); + return 0; + } + + if ((kd = malloc (val_len)) == NULL){ + printf("malloc kd info error\n"); + return 0; + } + + if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed kd"); + return 0; + } + + for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){ + if (kd[i].d_cmajor == dev_major) { + major = kd[i].d_bmajor; + break; + } + } + + dev = MKDEV(major,dev_minor); + + mode |= S_IFBLK; + + name = devname(dev,mode); + + r = snprintf(buf, (size_t) bufsize, "/dev/%s",name); + + free(kd); + + if (r < 0 || r > bufsize - 1 || name == NULL) + return 0; + + return 1; +} + +/* Fill info from dm_ioctl structure. Look at DM_EXISTS_FLAG*/ +int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) +{ + if (!dmt->dmi.v4) + return 0; + + memset(info, 0, sizeof(*info)); + + info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0; + if (!info->exists) + return 1; + + info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0; + info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0; + info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0; + info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ? + 1 : 0; + info->target_count = dmt->dmi.v4->target_count; + info->open_count = dmt->dmi.v4->open_count; + info->event_nr = dmt->dmi.v4->event_nr; + + nbsd_get_dm_major(&info->major, DM_BLOCK_MAJOR); /* get netbsd dm device major number */ + info->minor = MINOR(dmt->dmi.v4->dev); + + return 1; +} + +/* Unsupported on NetBSD */ +uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead) +{ + *read_ahead = DM_READ_AHEAD_NONE; + return 1; +} + +const char *dm_task_get_name(const struct dm_task *dmt) +{ + + return (dmt->dmi.v4->name); +} + +const char *dm_task_get_uuid(const struct dm_task *dmt) +{ + + return (dmt->dmi.v4->uuid); +} + +struct dm_deps *dm_task_get_deps(struct dm_task *dmt) +{ + return (struct dm_deps *) (((void *) dmt->dmi.v4) + + dmt->dmi.v4->data_start); +} + +struct dm_names *dm_task_get_names(struct dm_task *dmt) +{ + return (struct dm_names *) (((void *) dmt->dmi.v4) + + dmt->dmi.v4->data_start); +} + +struct dm_versions *dm_task_get_versions(struct dm_task *dmt) +{ + return (struct dm_versions *) (((void *) dmt->dmi.v4) + + dmt->dmi.v4->data_start); +} + +int dm_task_set_ro(struct dm_task *dmt) +{ + dmt->read_only = 1; + return 1; +} + +/* Unsupported on NetBSD */ +int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead, + uint32_t read_ahead_flags) +{ + return 1; +} + +int dm_task_suppress_identical_reload(struct dm_task *dmt) +{ + dmt->suppress_identical_reload = 1; + return 1; +} + +int dm_task_set_newname(struct dm_task *dmt, const char *newname) +{ + if (!(dmt->newname = dm_strdup(newname))) { + log_error("dm_task_set_newname: strdup(%s) failed", newname); + return 0; + } + + return 1; +} + +int dm_task_set_message(struct dm_task *dmt, const char *message) +{ + if (!(dmt->message = dm_strdup(message))) { + log_error("dm_task_set_message: strdup(%s) failed", message); + return 0; + } + + return 1; +} + +int dm_task_set_sector(struct dm_task *dmt, uint64_t sector) +{ + dmt->sector = sector; + + return 1; +} + +/* Unsupported in NetBSD */ +int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, + const char *heads, const char *sectors, const char *start) +{ + return 0; +} + +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; + + return 1; +} + +int dm_task_skip_lockfs(struct dm_task *dmt) +{ + dmt->skip_lockfs = 1; + + return 1; +} + +int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr) +{ + dmt->event_nr = event_nr; + + return 1; +} + +/* Allocate one target(table description) entry. */ +struct target *create_target(uint64_t start, uint64_t len, const char *type, + const char *params) +{ + struct target *t = dm_malloc(sizeof(*t)); + + if (!t) { + log_error("create_target: malloc(%" PRIsize_t ") failed", + sizeof(*t)); + return NULL; + } + + memset(t, 0, sizeof(*t)); + + if (!(t->params = dm_strdup(params))) { + log_error("create_target: strdup(params) failed"); + goto bad; + } + + if (!(t->type = dm_strdup(type))) { + log_error("create_target: strdup(type) failed"); + goto bad; + } + + t->start = start; + t->length = len; + return t; + + bad: + dm_free(t->params); + dm_free(t->type); + dm_free(t); + return NULL; +} + +/* Parse given dm task structure to proplib dictionary. */ +static int _flatten(struct dm_task *dmt, prop_dictionary_t dm_dict) +{ + prop_array_t cmd_array; + prop_dictionary_t target_spec; + + struct target *t; + + size_t len; + char type[DM_MAX_TYPE_NAME]; + + uint32_t major, flags; + int count = 0; + const int (*version)[3]; + + flags = 0; + version = &_cmd_data_v4[dmt->type].version; + + cmd_array = prop_array_create(); + + for (t = dmt->head; t; t = t->next) { + target_spec = prop_dictionary_create(); + + prop_dictionary_set_uint64(target_spec,DM_TABLE_START,t->start); + prop_dictionary_set_uint64(target_spec,DM_TABLE_LENGTH,t->length); + + strlcpy(type,t->type,DM_MAX_TYPE_NAME); + + prop_dictionary_set_cstring(target_spec,DM_TABLE_TYPE,type); + prop_dictionary_set_cstring(target_spec,DM_TABLE_PARAMS,t->params); + + prop_array_set(cmd_array,count,target_spec); + + prop_object_release(target_spec); + + count++; + } + + + if (count && (dmt->sector || dmt->message)) { + log_error("targets and message are incompatible"); + return -1; + } + + if (count && dmt->newname) { + log_error("targets and newname are incompatible"); + return -1; + } + + if (count && dmt->geometry) { + log_error("targets and geometry are incompatible"); + return -1; + } + + if (dmt->newname && (dmt->sector || dmt->message)) { + log_error("message and newname are incompatible"); + return -1; + } + + if (dmt->newname && dmt->geometry) { + log_error("geometry and newname are incompatible"); + return -1; + } + + if (dmt->geometry && (dmt->sector || dmt->message)) { + log_error("geometry and message are incompatible"); + return -1; + } + + if (dmt->sector && !dmt->message) { + log_error("message is required with sector"); + return -1; + } + + if (dmt->newname) + len += strlen(dmt->newname) + 1; + + if (dmt->message) + len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1; + + if (dmt->geometry) + len += strlen(dmt->geometry) + 1; + + nbsd_dmi_add_version((*version), dm_dict); + + nbsd_get_dm_major(&major, DM_BLOCK_MAJOR); + /* + * Only devices with major which is equal to netbsd dm major + * dm devices in NetBSD can't have more majors then one assigned to dm. + */ + if (dmt->major != major && dmt->major != -1) + return -1; + + if (dmt->minor >= 0) { + flags |= DM_PERSISTENT_DEV_FLAG; + + prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmt->minor); + } + + /* Set values to dictionary. */ + if (dmt->dev_name) + prop_dictionary_set_cstring(dm_dict, DM_IOCTL_NAME, dmt->dev_name); + + if (dmt->uuid) + prop_dictionary_set_cstring(dm_dict, DM_IOCTL_UUID, dmt->uuid); + + if (dmt->type == DM_DEVICE_SUSPEND) + flags |= DM_SUSPEND_FLAG; + if (dmt->no_flush) + flags |= DM_NOFLUSH_FLAG; + if (dmt->read_only) + flags |= DM_READONLY_FLAG; + if (dmt->skip_lockfs) + flags |= DM_SKIP_LOCKFS_FLAG; + + prop_dictionary_set_uint32(dm_dict, DM_IOCTL_FLAGS, flags); + + prop_dictionary_set_uint32(dm_dict, DM_IOCTL_EVENT, dmt->event_nr); + + if (dmt->newname) + prop_array_set_cstring(cmd_array, 0, dmt->newname); + + /* Add array for all COMMAND specific data. */ + prop_dictionary_set(dm_dict, DM_IOCTL_CMD_DATA, cmd_array); + prop_object_release(cmd_array); + + return 0; +} + +static int _process_mapper_dir(struct dm_task *dmt) +{ + struct dirent *dirent; + DIR *d; + const char *dir; + int r = 1; + + dir = dm_dir(); + if (!(d = opendir(dir))) { + log_sys_error("opendir", dir); + return 0; + } + + while ((dirent = readdir(d))) { + if (!strcmp(dirent->d_name, ".") || + !strcmp(dirent->d_name, "..") || + !strcmp(dirent->d_name, "control")) + continue; + dm_task_set_name(dmt, dirent->d_name); + dm_task_run(dmt); + } + + if (closedir(d)) + log_sys_error("closedir", dir); + + return r; +} + +/* Get list of all devices. */ +static int _process_all_v4(struct dm_task *dmt) +{ + struct dm_task *task; + struct dm_names *names; + unsigned next = 0; + int r = 1; + + if (!(task = dm_task_create(DM_DEVICE_LIST))) + return 0; + + if (!dm_task_run(task)) { + r = 0; + goto out; + } + + if (!(names = dm_task_get_names(task))) { + r = 0; + goto out; + } + + if (!names->dev) + goto out; + + do { + names = (void *) names + next; + if (!dm_task_set_name(dmt, names->name)) { + r = 0; + goto out; + } + if (!dm_task_run(dmt)) + r = 0; + next = names->next; + } while (next); + + out: + dm_task_destroy(task); + return r; +} + +static int _mknodes_v4(struct dm_task *dmt) +{ + (void) _process_mapper_dir(dmt); + + return _process_all_v4(dmt); +} + +/* Create new device and load table to it. */ +static int _create_and_load_v4(struct dm_task *dmt) +{ + struct dm_task *task; + int r; + + printf("create and load called \n"); + + /* Use new task struct to create the device */ + if (!(task = dm_task_create(DM_DEVICE_CREATE))) { + log_error("Failed to create device-mapper task struct"); + return 0; + } + + /* Copy across relevant fields */ + if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { + dm_task_destroy(task); + return 0; + } + + if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { + dm_task_destroy(task); + return 0; + } + + task->major = dmt->major; + task->minor = dmt->minor; + task->uid = dmt->uid; + task->gid = dmt->gid; + task->mode = dmt->mode; + + r = dm_task_run(task); + dm_task_destroy(task); + if (!r) + return r; + + /* Next load the table */ + if (!(task = dm_task_create(DM_DEVICE_RELOAD))) { + log_error("Failed to create device-mapper task struct"); + return 0; + } + + /* Copy across relevant fields */ + if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { + dm_task_destroy(task); + return 0; + } + + task->read_only = dmt->read_only; + task->head = dmt->head; + task->tail = dmt->tail; + + r = dm_task_run(task); + + task->head = NULL; + task->tail = NULL; + dm_task_destroy(task); + if (!r) + goto revert; + + /* Use the original structure last so the info will be correct */ + dmt->type = DM_DEVICE_RESUME; + dm_free(dmt->uuid); + dmt->uuid = NULL; + + r = dm_task_run(dmt); + + if (r) + return r; + + revert: + dmt->type = DM_DEVICE_REMOVE; + dm_free(dmt->uuid); + dmt->uuid = NULL; + + if (!dm_task_run(dmt)) + log_error("Failed to revert device creation."); + + return r; +} + +uint64_t dm_task_get_existing_table_size(struct dm_task *dmt) +{ + return dmt->existing_table_size; +} + +static int _reload_with_suppression_v4(struct dm_task *dmt) +{ + struct dm_task *task; + struct target *t1, *t2; + int r; + + /* New task to get existing table information */ + if (!(task = dm_task_create(DM_DEVICE_TABLE))) { + log_error("Failed to create device-mapper task struct"); + return 0; + } + + /* Copy across relevant fields */ + if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { + dm_task_destroy(task); + return 0; + } + + if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { + dm_task_destroy(task); + return 0; + } + + task->major = dmt->major; + task->minor = dmt->minor; + + r = dm_task_run(task); + + if (!r) { + dm_task_destroy(task); + return r; + } + + /* Store existing table size */ + t2 = task->head; + while (t2 && t2->next) + t2 = t2->next; + dmt->existing_table_size = t2 ? t2->start + t2->length : 0; + + if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only) + goto no_match; + + t1 = dmt->head; + t2 = task->head; + + while (t1 && t2) { + while (t2->params[strlen(t2->params) - 1] == ' ') + t2->params[strlen(t2->params) - 1] = '\0'; + if ((t1->start != t2->start) || + (t1->length != t2->length) || + (strcmp(t1->type, t2->type)) || + (strcmp(t1->params, t2->params))) + goto no_match; + t1 = t1->next; + t2 = t2->next; + } + + if (!t1 && !t2) { + dmt->dmi.v4 = task->dmi.v4; + task->dmi.v4 = NULL; + dm_task_destroy(task); + return 1; + } + +no_match: + dm_task_destroy(task); + + /* Now do the original reload */ + dmt->suppress_identical_reload = 0; + r = dm_task_run(dmt); + + 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. */ + if (prop_dictionary_sendrecv_ioctl(dm_dict_in,_control_fd, + NETBSD_DM_IOCTL,&dm_dict_out) != 0) { + + 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; + } + } + + 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); + break; + + case DM_DEVICE_REMOVE: + /* FIXME Kernel needs to fill in dmi->name */ + if (dmt->dev_name) + rm_dev_node(dmt->dev_name); + 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); + 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); + else if (dmt->dev_name) + rm_dev_node(dmt->dev_name); + 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; +} Index: ./lvm2tools/dist/libdm/ioctl/libdm_netbsd.c =================================================================== RCS file: ./lvm2tools/dist/libdm/ioctl/libdm_netbsd.c diff -N ./lvm2tools/dist/libdm/ioctl/libdm_netbsd.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/dist/libdm/ioctl/libdm_netbsd.c 19 Dec 2008 00:00:23 -0000 @@ -0,0 +1,502 @@ +/* + * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Adam Hamsik. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include "lib.h" + +#define DMI_SIZE 16 * 1024 + +static int dm_list_versions(prop_dictionary_t, struct dm_ioctl *); +static int dm_list_devices(prop_dictionary_t, struct dm_ioctl *); +static int dm_dev_deps(prop_dictionary_t, struct dm_ioctl *); +static int dm_table_status(prop_dictionary_t, struct dm_ioctl *); + +int +nbsd_get_dm_major(uint32_t *major, int type) +{ + size_t val_len,i; + struct kinfo_drivers *kd; + + if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) { + printf("sysctlbyname failed"); + return 0; + } + + if ((kd = malloc (val_len)) == NULL){ + printf("malloc kd info error\n"); + return 0; + } + + if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed kd"); + return 0; + } + + for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) { + + if (strncmp(kd[i].d_name,DM_NAME,strlen(kd[i].d_name)) == 0){ + + if (type == DM_CHAR_MAJOR) + /* Set major to dm-driver char major number. */ + *major = kd[i].d_cmajor; + else + if (type == DM_BLOCK_MAJOR) + *major = kd[i].d_bmajor; + + free(kd); + + return 1; + } + } + + free(kd); + + return 0; +} + +int +nbsd_dmi_add_version(const int *version, prop_dictionary_t dm_dict) +{ + prop_array_t ver; + size_t i; + + if ((ver = prop_array_create()) == NULL) + return -1; + + for (i=0;i<3;i++) + prop_array_set_uint32(ver,i,version[i]); + + if ((prop_dictionary_set(dm_dict,"version",ver)) == false) + return -1; + + prop_object_release(ver); + + return 0; +} + +struct dm_ioctl* +nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict,const int cmd) +{ + struct dm_ioctl *dmi; + prop_array_t ver; + + size_t i; + int r; + char *name, *uuid; + uint32_t major,minor; + + name = NULL; + uuid = NULL; + minor = 0; + + nbsd_get_dm_major(&major, DM_BLOCK_MAJOR); + + if (!(dmi = dm_malloc(DMI_SIZE))) + return NULL; + + memset(dmi,0,DMI_SIZE); + + prop_dictionary_get_int32(dm_dict, DM_IOCTL_OPEN, &dmi->open_count); + prop_dictionary_get_uint32(dm_dict, DM_IOCTL_EVENT, &dmi->event_nr); + prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &dmi->flags); + prop_dictionary_get_uint32(dm_dict, DM_IOCTL_TARGET_COUNT, + &dmi->target_count); + + if (prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor)) + dmi->dev = MKDEV(major, minor); + else + dmi->dev = 0; + + /* Copy name and uuid to dm_ioctl. */ + if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, + (const char **)&name)){ + strlcpy(dmi->name, name, DM_NAME_LEN); + } else + dmi->name[0] = '\0'; + + if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, + (const char **)&uuid)){ + strlcpy(dmi->uuid, uuid, DM_UUID_LEN); + } else + dmi->uuid[0] = '\0'; + + /* dmi parsing values, size of dmi block and offset to data. */ + dmi->data_size = DMI_SIZE; + dmi->data_start = sizeof(struct dm_ioctl); + + /* Get kernel version from dm_dict. */ + ver = prop_dictionary_get(dm_dict,DM_IOCTL_VERSION); + + for(i=0; i<3; i++) + prop_array_get_uint32(ver,i,&dmi->version[i]); + + switch (cmd){ + + case DM_LIST_VERSIONS: + r = dm_list_versions(dm_dict,dmi); + if (r >= 0) + dmi->target_count = r; + break; + + case DM_LIST_DEVICES: + r = dm_list_devices(dm_dict,dmi); + if (r >= 0) + dmi->target_count = r; + break; + + case DM_TABLE_STATUS: + r = dm_table_status(dm_dict,dmi); + if (r >= 0) + dmi->target_count = r; + break; + + case DM_TABLE_DEPS: + r = dm_dev_deps(dm_dict,dmi); + if (r >= 0) + dmi->target_count = r; + break; + } + + return dmi; +} + +/* + * Parse dm_dict when targets command was called and fill dm_ioctl buffer with it. + * + * Return number of targets or if failed <0 error. + */ + +static int +dm_list_versions(prop_dictionary_t dm_dict, struct dm_ioctl *dmi) +{ + struct dm_target_versions *dmtv,*odmtv; + + prop_array_t targets,ver; + prop_dictionary_t target_dict; + prop_object_iterator_t iter; + + char *name; + size_t j,i,slen,rec_size; + + odmtv = NULL; + name = NULL; + j = 0; + + dmtv = (struct dm_target_versions *)((uint8_t *)dmi + dmi->data_start); + +/* printf("dmi: vers: %d.%d.%d data_size: %d data_start: %d name: %s t_count: %d\n", + dmi->version[0],dmi->version[1],dmi->version[2],dmi->data_size,dmi->data_start, + dmi->name,dmi->target_count); + + printf("dmi: size: %d -- %p --- %p \n",sizeof(struct dm_ioctl),dmi,dmi+dmi->data_start); + printf("dmtv: size: %p --- %p\n",dmtv,(struct dm_target_versions *)(dmi+312));*/ + + /* get prop_array of target_version dictionaries */ + if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){ + + iter = prop_array_iterator(targets); + if (!iter) + err(EXIT_FAILURE,"dm_list_versions %s",__func__); + + while((target_dict = prop_object_iterator_next(iter)) != NULL){ + j++; + + prop_dictionary_get_cstring_nocopy(target_dict, + DM_TARGETS_NAME,(const char **)&name); + + slen = strlen(name) + 1; + rec_size = sizeof(struct dm_target_versions) + slen + 1; + + if (rec_size > dmi->data_size) + return -ENOMEM; + + ver = prop_dictionary_get(target_dict,DM_TARGETS_VERSION); + + for (i=0; i<3; i++) + prop_array_get_uint32(ver,i,&dmtv->version[i]); + + dmtv->next = rec_size; + + strlcpy(dmtv->name,name,slen); + + odmtv = dmtv; + + dmtv =(struct dm_target_versions *)((uint8_t *)dmtv + rec_size); + } + + if (odmtv != NULL) + odmtv->next = 0; + } + + prop_object_iterator_release(iter); + return j; +} + +/* + * List all available dm devices in system. + */ +static int +dm_list_devices(prop_dictionary_t dm_dict, struct dm_ioctl *dmi) +{ + struct dm_name_list *dml,*odml; + + prop_array_t targets; + prop_dictionary_t target_dict; + prop_object_iterator_t iter; + + uint32_t minor; + uint32_t major; + + char *name; + size_t j,slen,rec_size; + + odml = NULL; + name = NULL; + minor = 0; + j = 0; + + nbsd_get_dm_major(&major,DM_BLOCK_MAJOR); + + dml = (struct dm_name_list *)((uint8_t *)dmi + dmi->data_start); + + if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){ + + iter = prop_array_iterator(targets); + if (!iter) + err(EXIT_FAILURE,"dm_list_devices %s",__func__); + + while((target_dict = prop_object_iterator_next(iter)) != NULL){ + + prop_dictionary_get_cstring_nocopy(target_dict, + DM_DEV_NAME,(const char **)&name); + + prop_dictionary_get_uint32(target_dict,DM_DEV_DEV,&minor); + + dml->dev = MKDEV(major,minor); + + slen = strlen(name) + 1; + rec_size = sizeof(struct dm_name_list) + slen + 1; + + if (rec_size > dmi->data_size) + return -ENOMEM; + + dml->next = rec_size; + + strlcpy(dml->name,name,slen); + + odml = dml; + + dml =(struct dm_name_list *)((uint8_t *)dml + rec_size); + + j++; + } + + if (odml != NULL) + odml->next = 0; + } + prop_object_iterator_release(iter); + return j; +} + +/* + * Print status of each table, target arguments, start sector, + * size and target name. + */ +static int +dm_table_status(prop_dictionary_t dm_dict,struct dm_ioctl *dmi) +{ + struct dm_target_spec *dmts, *odmts; + + prop_array_t targets; + prop_dictionary_t target_dict; + prop_object_iterator_t iter; + + char *type,*params,*params_start; + + bool prm; + size_t j,plen,rec_size,next; + + j = 0; + next = 0; + params = NULL; + odmts = NULL; + rec_size = 0; + plen = -1; + prm = false; + + dmts = (struct dm_target_spec *)((uint8_t *)dmi + dmi->data_start); + + if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){ + + iter = prop_array_iterator(targets); + if (!iter) + err(EXIT_FAILURE,"dm_table_status %s",__func__); + + while((target_dict = prop_object_iterator_next(iter)) != NULL){ + + prop_dictionary_get_cstring_nocopy(target_dict, + DM_TABLE_TYPE,(const char **)&type); + + prm = prop_dictionary_get_cstring_nocopy(target_dict, + DM_TABLE_PARAMS,(const char **)¶ms); + + prop_dictionary_get_uint64(target_dict,DM_TABLE_START,&dmts->sector_start); + prop_dictionary_get_uint64(target_dict,DM_TABLE_LENGTH,&dmts->length); + prop_dictionary_get_int32(target_dict,DM_TABLE_STAT,&dmts->status); + + if (prm) + plen = strlen(params) + 1; + + rec_size = sizeof(struct dm_target_spec) + plen; + + /* + * In linux when copying table status from kernel next is + * number of bytes from the start of the first dm_target_spec + * structure. I don't know why but, it has to be done this way. + */ + next += rec_size; + + if (rec_size > dmi->data_size) + return -ENOMEM; + + dmts->next = next; + + strlcpy(dmts->target_type, type, DM_MAX_TYPE_NAME); + + params_start = (char *)dmts + sizeof(struct dm_target_spec); + + if (prm) + strlcpy(params_start, params, plen); + else + params_start = "\0"; + + + odmts = dmts; + + dmts = (struct dm_target_spec *)((uint8_t *)dmts + rec_size); + + j++; + + } + + if (odmts != NULL) + odmts->next = 0; + } + prop_object_iterator_release(iter); + + return j; +} + +/* + * Print dm device dependiences, get minor/major number for + * devices. From kernel I will receive major:minor number of + * block device used with target. I have to translate it to + * raw device numbers and use them, because all other parts of lvm2tools + * uses raw devices internaly. + */ +static int +dm_dev_deps(prop_dictionary_t dm_dict, struct dm_ioctl *dmi) +{ + struct dm_target_deps *dmtd; + struct kinfo_drivers *kd; + + prop_array_t targets; + prop_object_iterator_t iter; + + uint32_t major; + + size_t val_len, i, j; + + uint64_t dev_tmp; + + dev_tmp = 0; + j = 0; + i = 0; + + if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) { + printf("sysctlbyname failed"); + return 0; + } + + if ((kd = malloc (val_len)) == NULL){ + printf("malloc kd info error\n"); + return 0; + } + + if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) { + printf("sysctlbyname failed kd"); + return 0; + } + + dmtd = (struct dm_target_deps *)((uint8_t *)dmi + dmi->data_start); + + if ((targets = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA))){ + + iter = prop_array_iterator(targets); + if (!iter) + err(EXIT_FAILURE,"dm_target_deps %s", __func__); + + while((prop_object_iterator_next(iter)) != NULL){ + + prop_array_get_uint64(targets, j, &dev_tmp); + + for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){ + if (kd[i].d_bmajor == MAJOR(dev_tmp)) { + major = kd[i].d_cmajor; + break; + } + } + + dmtd->dev[j] = MKDEV(major,MINOR(dev_tmp)); + + j++; + } + } + + dmtd->count = j; + + prop_object_iterator_release(iter); + + return j; +} Index: ./lvm2tools/lib/Makefile =================================================================== RCS file: ./lvm2tools/lib/Makefile diff -N ./lvm2tools/lib/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lib/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,5 @@ +# $NetBSD$ + +SUBDIR= libdevmapper liblvm + +.include Index: ./lvm2tools/lib/libdevmapper/Makefile =================================================================== RCS file: ./lvm2tools/lib/libdevmapper/Makefile diff -N ./lvm2tools/lib/libdevmapper/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lib/libdevmapper/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,34 @@ +# $NetBSD$ + +USE_SHLIBDIR= yes +USE_FORT?= no +NOLINT= #defined + +.include "../../lvm2tools.mk" + +LIB= devmapper + +CFLAGS+= -fno-inline + +CPPFLAGS+= -I${LIBDM_SRCDIR} -I${LIBDM_SRCDIR}/misc -I${LIBDM_SRCDIR}/mm \ + -I${LIBDM_SRCDIR}/datastruct -I${LIBDM_SRCDIR}/ioctl \ + -I${LVM2TOOLS_DISTDIR}/include -I. -D__NetBSD__ + + +CPPFLAGS+= -D__LIB_DEVMAPPER__ -DDM_DEVICE_UID=0 \ + -DDM_DEVICE_GID=0 -DDM_DEVICE_MODE=0600 + +LDADD+= -lprop + +SRCS+= bitset.c hash.c list.c libdm-common.c libdm-file.c \ + libdm-deptree.c libdm-string.c libdm-report.c \ + dbg_malloc.c pool.c matcher.c parse_rx.c ttree.c \ + libdm-nbsd-iface.c libdm_netbsd.c + +.PATH: ${LIBDM_SRCDIR}/ +.PATH: ${LIBDM_SRCDIR}/datastruct +.PATH: ${LIBDM_SRCDIR}/mm +.PATH: ${LIBDM_SRCDIR}/regex +.PATH: ${LIBDM_SRCDIR}/ioctl + +.include Index: ./lvm2tools/lib/libdevmapper/netbsd-dm.h =================================================================== RCS file: ./lvm2tools/lib/libdevmapper/netbsd-dm.h diff -N ./lvm2tools/lib/libdevmapper/netbsd-dm.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lib/libdevmapper/netbsd-dm.h 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,174 @@ +#ifndef __NETBSD_DM_H__ +#define __NETBSD_DM_H__ + +#include + +#define DM_CMD_LEN 16 + +#define DM_IOCTL 0xfd + +#define DM_IOCTL_CMD 0 + +#define NETBSD_DM_IOCTL _IOWR(DM_IOCTL, DM_IOCTL_CMD, struct plistref) + + +/* + * DM-ioctl dictionary. + * + * This contains general information about dm device. + * + * + * command + * ... + * + * event_nr + * ... + * + * name + * ... + * + * uuid + * ... + * + * dev + * + * + * flags + * + * + * version + * + * ... + * ... + * ... + * + * + * cmd_data + * + * + * + * + * + * Available commands from _cmd_data_v4. + * + * create, reload, remove, remove_all, suspend, + * resume, info, deps, rename, version, status, + * table, waitevent, names, clear, mknodes, + * targets, message, setgeometry + * + */ + +/* + * DM_LIST_VERSIONS command dictionary entry. + * Lists all available targets with their version. + * + * + * + * name + * ... + * + * version + * + * ... + * ... + * ... + * + * + * + * + */ + +#define DM_IOCTL_COMMAND "command" +#define DM_IOCTL_VERSION "version" +#define DM_IOCTL_OPEN "open_count" +#define DM_IOCTL_MINOR "minor" +#define DM_IOCTL_NAME "name" +#define DM_IOCTL_UUID "uuid" +#define DM_IOCTL_TARGET_COUNT "target_count" +#define DM_IOCTL_EVENT "event_nr" +#define DM_IOCTL_FLAGS "flags" +#define DM_IOCTL_CMD_DATA "cmd_data" + +#define DM_TARGETS_NAME "name" +#define DM_TARGETS_VERSION "ver" + +#define DM_DEV_NEWNAME "newname" +#define DM_DEV_NAME "name" +#define DM_DEV_DEV "dev" + +#define DM_TABLE_TYPE "type" +#define DM_TABLE_START "start" +#define DM_TABLE_STAT "status" +#define DM_TABLE_LENGTH "length" +#define DM_TABLE_PARAMS "params" + + +/* Status bits */ +#define DM_READONLY_FLAG (1 << 0) /* In/Out */ +#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */ +#define DM_EXISTS_FLAG (1 << 2) /* In/Out */ /* XXX. This flag is undocumented. */ +#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */ + +/* + * Flag passed into ioctl STATUS command to get table information + * rather than current status. + */ +#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */ + +/* + * Flags that indicate whether a table is present in either of + * the two table slots that a device has. + */ +#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */ +#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */ + +/* + * Indicates that the buffer passed in wasn't big enough for the + * results. + */ +#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ + +/* + * This flag is now ignored. + */ +#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ + +/* + * Set this to avoid attempting to freeze any filesystem when suspending. + */ +#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ + +/* + * Set this to suspend without flushing queued ios. + */ +#define DM_NOFLUSH_FLAG (1 << 11) /* In */ + + +#ifdef __LIB_DEVMAPPER__ + +# define MAJOR(x) major((x)) +# define MINOR(x) minor((x)) +# define MKDEV(x,y) makedev((x),(y)) + +/* Name of device-mapper driver in kernel */ +#define DM_NAME "dm" + +/* Types for nbsd_get_dm_major */ +#define DM_CHAR_MAJOR 1 +#define DM_BLOCK_MAJOR 2 + +/* libdm_netbsd.c */ + +int nbsd_get_dm_major(uint32_t *, int); /* Get dm device major numbers */ + +int nbsd_dmi_add_cmd(const char *, prop_dictionary_t); +int nbsd_dmi_add_version(const int [3], prop_dictionary_t); +int nbsd_dm_add_uint(const char *, uint64_t, prop_dictionary_t); +int nbsd_dm_add_str(const char *, char *, prop_dictionary_t ); + +struct dm_ioctl* nbsd_dm_dict_to_dmi(prop_dictionary_t, const int); + +#endif /* __LIB_DEVMAPPER__ */ + +#endif /* __NETBSD_DM_H__ */ Index: ./lvm2tools/lib/libdevmapper/shlib_version =================================================================== RCS file: ./lvm2tools/lib/libdevmapper/shlib_version diff -N ./lvm2tools/lib/libdevmapper/shlib_version --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lib/libdevmapper/shlib_version 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,2 @@ +major=0 +minor=0 Index: ./lvm2tools/lib/liblvm/Makefile =================================================================== RCS file: ./lvm2tools/lib/liblvm/Makefile diff -N ./lvm2tools/lib/liblvm/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/lib/liblvm/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,63 @@ +# $NetBSD$ + +LIBISPRIVATE= yes + +USE_FORT?= no +NOLINT= #defined + +.include "../../lvm2tools.mk" + +LIB= lvm + +CPPFLAGS+= -I${LVM2TOOLS_DISTDIR}/lib -I${LVM2TOOLS_DISTDIR}/include \ + -I. + +SRCS+= activate.c lvmcache.c toolcontext.c config.c btree.c \ + str_list.c dev-cache.c dev-io.c dev-md.c device.c \ + display.c errseg.c filter-composite.c \ + filter-persistent.c \ + filter-regex.c filter-sysfs.c filter-md.c archive.c \ + archiver.c export.c flags.c format-text.c import.c \ + import_vsn1.c tags.c text_label.c freeseg.c label.c \ + file_locking.c locking.c no_locking.c log.c lv_manip.c \ + merge.c metadata.c mirror.c pv_manip.c pv_map.c segtype.c \ + snapshot_manip.c crc.c lvm-exec.c lvm-file.c lvm-string.c \ + lvm-wrappers.c timestamp.c util.c memlock.c report.c \ + striped.c uuid.c zero.c disk-rep.c format1.c import-export.c \ + import-extents.c layout.c lvm1-label.c vg_number.c \ + disk_rep.c format_pool.c import_export.c pool_label.c \ + filter_netbsd.c snapshot.c mirrored.c dev_manager.c fs.c dev.c \ + lvm-globals.c + +LDADD+= -lprop + +.PATH: ${LVM2TOOLS_DISTDIR}/lib/ +.PATH: ${LVM2TOOLS_DISTDIR}/lib/activate +.PATH: ${LVM2TOOLS_DISTDIR}/lib/cache +.PATH: ${LVM2TOOLS_DISTDIR}/lib/commands +.PATH: ${LVM2TOOLS_DISTDIR}/lib/config +.PATH: ${LVM2TOOLS_DISTDIR}/lib/datastruct +.PATH: ${LVM2TOOLS_DISTDIR}/lib/device +.PATH: ${LVM2TOOLS_DISTDIR}/lib/display +.PATH: ${LVM2TOOLS_DISTDIR}/lib/error +.PATH: ${LVM2TOOLS_DISTDIR}/lib/filters +.PATH: ${LVM2TOOLS_DISTDIR}/lib/format1 +.PATH: ${LVM2TOOLS_DISTDIR}/lib/format_pool +.PATH: ${LVM2TOOLS_DISTDIR}/lib/format_text +.PATH: ${LVM2TOOLS_DISTDIR}/lib/freeseg +.PATH: ${LVM2TOOLS_DISTDIR}/lib/label +.PATH: ${LVM2TOOLS_DISTDIR}/lib/locking +.PATH: ${LVM2TOOLS_DISTDIR}/lib/log +.PATH: ${LVM2TOOLS_DISTDIR}/lib/metadata +.PATH: ${LVM2TOOLS_DISTDIR}/lib/mirror +.PATH: ${LVM2TOOLS_DISTDIR}/lib/misc +.PATH: ${LVM2TOOLS_DISTDIR}/lib/mm +.PATH: ${LVM2TOOLS_DISTDIR}/lib/report +.PATH: ${LVM2TOOLS_DISTDIR}/lib/snapshot +.PATH: ${LVM2TOOLS_DISTDIR}/lib/striped +.PATH: ${LVM2TOOLS_DISTDIR}/lib/uuid +.PATH: ${LVM2TOOLS_DISTDIR}/lib/zero +.PATH: ${LVM2TOOLS_DISTDIR}/lib/netbsd + +.include +.include Index: ./lvm2tools/sbin/Makefile =================================================================== RCS file: ./lvm2tools/sbin/Makefile diff -N ./lvm2tools/sbin/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/sbin/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,5 @@ +# $NetBSD$ + +SUBDIR= dmsetup lvm + +.include Index: ./lvm2tools/sbin/dmsetup/Makefile =================================================================== RCS file: ./lvm2tools/sbin/dmsetup/Makefile diff -N ./lvm2tools/sbin/dmsetup/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/sbin/dmsetup/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,31 @@ +# $NetBSD$ + +USE_FORT?= no +NOLINT= #defined + +.include "../../lvm2tools.mk" + +.PATH: ${LVM2TOOLS_DISTDIR}/man + +PROG= dmsetup + +MAN= dmsetup.8 +MLINKS= dmsetup.8 dmsetup.1 + +BINDIR= /sbin + +CPPFLAGS+= -I${LIBDM_SRCDIR}/ -I${LIBDM_SRCDIR}/misc \ + -I. -I${LIBDM_SRCDIR}/ioctl -I${LVM2TOOLS_DISTDIR}/include + +CPPFLAGS+= -D__LIB_DEVMAPPER__ -DDM_DEVICE_UID=0 \ + -DDM_DEVICE_GID=0 -DDM_DEVICE_MODE=0600 + +LIBDM_OBJDIR!= cd ${LVM2TOOLS_SRCDIR}/lib/libdevmapper && ${PRINTOBJDIR} +LDADD+= -L${LIBDM_OBJDIR} -ldevmapper +DPADD+= ${LIBDM_OBJDIR}/libdevmapper.a + +LDADD+= -lprop + +.PATH: ${LVM2TOOLS_DISTDIR}/tools + +.include Index: ./lvm2tools/sbin/lvm/Makefile =================================================================== RCS file: ./lvm2tools/sbin/lvm/Makefile diff -N ./lvm2tools/sbin/lvm/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./lvm2tools/sbin/lvm/Makefile 19 Dec 2008 00:00:24 -0000 @@ -0,0 +1,102 @@ + + +USE_FORT?= no +NOLINT= #defined + +.include "../../lvm2tools.mk" + +.PATH: ${LVM2TOOLS_DISTDIR}/man + +PROG= lvm + +BINDIR= /sbin + +SRCS= dumpconfig.c formats.c lvchange.c lvconvert.c lvcreate.c \ + lvdisplay.c lvextend.c lvmchange.c lvmcmdline.c \ + lvmdiskscan.c lvreduce.c lvremove.c lvrename.c lvresize.c \ + lvscan.c polldaemon.c pvchange.c pvck.c pvcreate.c \ + pvdisplay.c pvmove.c pvremove.c pvresize.c pvscan.c \ + reporter.c segtypes.c toollib.c vgcfgbackup.c \ + vgcfgrestore.c vgchange.c vgck.c vgconvert.c vgcreate.c \ + vgdisplay.c vgexport.c vgextend.c vgimport.c vgmerge.c \ + vgmknodes.c vgreduce.c vgremove.c vgrename.c vgscan.c \ + vgsplit.c lvm.c + +CFLAGS+= -fno-inline + +CPPFLAGS+= -I${LVM2TOOLS_DISTDIR}/lib -I${LVM2TOOLS_DISTDIR}/include \ + -I. -I${LIBDM_INCLUDE} -I${LVM2TOOLS_DISTDIR}/tools -I${LVM2TOOLS_DISTDIR}/libdm + +CPPFLAGS+= -DLVM_SHARED_PATH=\"$(BINDIR)/lvm\" + + +MAN= lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 \ + lvm.8 lvm.conf.5 lvmchange.8 lvmdiskscan.8 lvmdump.8 \ + lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \ + lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 \ + pvmove.8 pvremove.8 pvresize.8 pvs.8 pvscan.8 \ + vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgconvert.8 \ + vgcreate.8 vgdisplay.8 vgexport.8 vgextend.8 vgimport.8 \ + vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \ + vgs.8 vgscan.8 vgsplit.8 + + +MKLINKS+= lvchange.8 lvchange.1 \ + lvconvert.8 lvconvert.1 \ + lvcreate.8 lvcreate.1 \ + lvdisplay.8 lvdisplay.1 \ + lvextend.8 lvextend.1 \ + lvm.8 lvm.1 \ + lvm.conf lvm.1 \ + lvmchange.8 lvmchange.1 \ + lvmdiskscan.8 lvmdiskscan.1 \ + lvmdump.8 lvmdump.1 \ + lvreduce.8 lvreduce.1 \ + lvremove.8 lvremove.1 \ + lvrename.8 lvrename.1 \ + lvresize.8 lvresize.1 \ + lvs.8 lvs.1 \ + lvscan.8 lvscan.1 \ + pvchange.8 pvchange.1 \ + pvck.8 pvck.1 \ + pvcreate.8 pvcreate.1 \ + pvdisplay.8 pvdisplay.1 \ + pvmove.8 pvmove.1 \ + pvremove.8 pvremove.1 \ + pvresize.8 pvresize.1 \ + pvs.8 pvs.1 \ + pvscan.8 pvscan.1 \ + vgcfgbackup.8 vgcfgbackup.1 \ + vgcfgrestore.8 vgcfgrestore.1 \ + vgchange.8 vgchange.1 \ + vgck.8 vgck.1 \ + vgconvert.8 vgconvert.1 \ + vgcreate.8 vgcreate.1 \ + vgdisplay.8 vgdisplay.1 \ + vgexport.8 vgexport.1 \ + vgextend.8 vgextend.1 \ + vgimport.8 vgimport.1 \ + vgmerge.8 vgmerge.1 \ + vgmknodes.8 vgmknodes.1 \ + vgreduce.8 vgreduce.1 \ + vgremove.8 vgremove.1 \ + vgrename.8 vgrename.1 \ + vgs.8 vgs.1 \ + vgscan.8 vgscan.1 \ + vgsplit.8 vgsplit.1 + +LIBLVM_OBJDIR!= cd ${LVM2TOOLS_SRCDIR}/lib/liblvm && ${PRINTOBJDIR} +LDADD+= -L${LIBLVM_OBJDIR} -llvm +DPADD+= ${LIBLVM_OBJDIR}/liblvm.a + +LIBDM_OBJDIR!= cd ${LVM2TOOLS_SRCDIR}/lib/libdevmapper && ${PRINTOBJDIR} +LDADD+= -L${LIBDM_OBJDIR} -ldevmapper +DPADD+= ${LIBDM_OBJDIR}/libdevmapper.a + +LDADD+= -lprop + + +.PATH: ${LVM2TOOLS_DISTDIR}/tools + + +.include