[PATCH] extras/multipath update

here is the next update which brings this multipath to the state i'm not
ashamed of it being in udev :)

* drop a libdevmapper copy in extras/multipath; maybe discussions w/
Sistina folks will bring a better solution in the future.
* drop a putchar usage in libdevmapper to compile cleanly with klibc
* drop another such usage of my own in main.c
* massage the Makefile to compile libdevmapper against klibc
* use "ld" to produce the binary rather than "gcc -static"
* stop being stupid w/ uneeded major, minor & dev in main.c:dm_mk_node()
* reverse to creating striped target for now because the multipath
target is more hairy than expected initialy
* push the version code to 009 to be in synch w/ udev

builds & run here.
binary size is 43ko, which is fairly gratifying after all the efforts
I've put to compiling it with klibc :)
This commit is contained in:
christophe.varoqui@free.fr 2003-12-07 08:44:59 -08:00 committed by Greg KH
parent 83fa40fc2a
commit 2bf80b67d1
11 changed files with 1964 additions and 17 deletions

View File

@ -13,17 +13,35 @@ CFLAGS = -pipe -g -O2 -Wall -Wunused -Wstrict-prototypes -nostdinc -I../../klibc
LDFLAGS = -lsysfs -ldevmapper -ldlist
OBJS = main.o
CRT0 = ../../klibc/klibc/crt0.o
LIB = ../../klibc/klibc/libc.a
LIBGCC = /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.1/libgcc.a
DMOBJS = libdevmapper/libdm-common.o libdevmapper/ioctl/libdevmapper.o
SYSFSOBJS = ../../libsysfs/dlist.o ../../libsysfs/sysfs_bus.o \
../../libsysfs/sysfs_class.o ../../libsysfs/sysfs_device.o \
../../libsysfs/sysfs_dir.o ../../libsysfs/sysfs_driver.o \
../../libsysfs/sysfs_utils.o
all: $(EXEC)
strip $(EXEC)
SUBDIRS = libdevmapper
recurse:
@for dir in $(SUBDIRS); do\
$(MAKE) -C $$dir ; \
done
$(MAKE) $(EXEC)
all: recurse
@echo ""
@echo "Make complete"
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS)
$(LD) -o $(EXEC) $(CRT0) $(OBJS) $(SYSFSOBJS) $(DMOBJS) $(LIB) $(LIBGCC)
strip $(EXEC)
clean:
rm -f core *.o $(EXEC)
$(MAKE) -C libdevmapper clean
install:
install -d $(bindir)

View File

@ -0,0 +1,15 @@
# Makefile
#
# Copyright (C) 2003 Christophe Varoqui, <christophe.varoqui@free.fr>
CC = gcc
CFLAGS = -pipe -g -O2 -Wall -Wunused -Wstrict-prototypes -nostdinc -I../../../klibc/klibc/include -I../../../klibc/klibc/include/bits32 -I/usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.3.1/include -I../../../klibc/linux/include -I. -Iioctl
OBJS = ioctl/libdevmapper.o libdm-common.o
all: $(OBJS)
@echo ""
@echo "Make complete"
clean:
rm -f core *.o ioctl/*.o ioctl/*.so

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef _LINUX_LIBDM_COMPAT_H
#define _LINUX_LIBDM_COMPAT_H
#include <inttypes.h>
#include <linux/dm-ioctl.h>
#include <linux/kdev_t.h>
#include <sys/ioctl.h>
struct dm_task;
struct dm_info;
/*
* Old versions of structures for backwards compatibility.
*/
struct dm_ioctl_v1 {
uint32_t version[3]; /* in/out */
uint32_t data_size; /* total size of data passed in
* including this struct */
uint32_t data_start; /* offset to start of data
* relative to start of this struct */
int32_t target_count; /* in/out */
int32_t open_count; /* out */
uint32_t flags; /* in/out */
__kernel_dev_t dev; /* in/out */
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
};
struct dm_target_spec_v1 {
int32_t status; /* used when reading from kernel only */
uint64_t sector_start;
uint32_t length;
uint32_t next;
char target_type[DM_MAX_TYPE_NAME];
};
struct dm_target_deps_v1 {
uint32_t count;
__kernel_dev_t dev[0]; /* out */
};
enum {
/* Top level cmds */
DM_VERSION_CMD_V1 = 0,
DM_REMOVE_ALL_CMD_V1,
/* device level cmds */
DM_DEV_CREATE_CMD_V1,
DM_DEV_REMOVE_CMD_V1,
DM_DEV_RELOAD_CMD_V1,
DM_DEV_RENAME_CMD_V1,
DM_DEV_SUSPEND_CMD_V1,
DM_DEV_DEPS_CMD_V1,
DM_DEV_STATUS_CMD_V1,
/* target level cmds */
DM_TARGET_STATUS_CMD_V1,
DM_TARGET_WAIT_CMD_V1,
};
#define DM_VERSION_V1 _IOWR(DM_IOCTL, DM_VERSION_CMD_V1, struct dm_ioctl)
#define DM_REMOVE_ALL_V1 _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD_V1, struct dm_ioctl)
#define DM_DEV_CREATE_V1 _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD_V1, struct dm_ioctl)
#define DM_DEV_REMOVE_V1 _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD_V1, struct dm_ioctl)
#define DM_DEV_RELOAD_V1 _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD_V1, struct dm_ioctl)
#define DM_DEV_SUSPEND_V1 _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD_V1, struct dm_ioctl)
#define DM_DEV_RENAME_V1 _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD_V1, struct dm_ioctl)
#define DM_DEV_DEPS_V1 _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD_V1, struct dm_ioctl)
#define DM_DEV_STATUS_V1 _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD_V1, struct dm_ioctl)
#define DM_TARGET_STATUS_V1 _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD_V1, struct dm_ioctl)
#define DM_TARGET_WAIT_V1 _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD_V1, struct dm_ioctl)
/* *INDENT-OFF* */
static struct cmd_data _cmd_data_v1[] = {
{ "create", DM_DEV_CREATE_V1, {1, 0, 0} },
{ "reload", DM_DEV_RELOAD_V1, {1, 0, 0} },
{ "remove", DM_DEV_REMOVE_V1, {1, 0, 0} },
{ "remove_all", DM_REMOVE_ALL_V1, {1, 0, 0} },
{ "suspend", DM_DEV_SUSPEND_V1, {1, 0, 0} },
{ "resume", DM_DEV_SUSPEND_V1, {1, 0, 0} },
{ "info", DM_DEV_STATUS_V1, {1, 0, 0} },
{ "deps", DM_DEV_DEPS_V1, {1, 0, 0} },
{ "rename", DM_DEV_RENAME_V1, {1, 0, 0} },
{ "version", DM_VERSION_V1, {1, 0, 0} },
{ "status", DM_TARGET_STATUS_V1, {1, 0, 0} },
{ "table", DM_TARGET_STATUS_V1, {1, 0, 0} },
{ "waitevent", DM_TARGET_WAIT_V1, {1, 0, 0} },
{ "names", 0, {4, 0, 0} },
{ "clear", 0, {4, 0, 0} },
{ "mknodes", 0, {4, 0, 0} },
};
/* *INDENT-ON* */
#endif

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef LIB_DMTARGETS_H
#define LIB_DMTARGETS_H
#include <inttypes.h>
struct dm_ioctl;
struct dm_ioctl_v1;
struct target {
uint64_t start;
uint64_t length;
char *type;
char *params;
struct target *next;
};
struct dm_task {
int type;
char *dev_name;
struct target *head, *tail;
int read_only;
uint32_t event_nr;
int major;
int minor;
union {
struct dm_ioctl *v4;
struct dm_ioctl_v1 *v1;
} dmi;
char *newname;
char *uuid;
};
struct cmd_data {
const char *name;
const int cmd;
const int version[3];
};
int dm_check_version(void);
#endif

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef LIB_DEVICE_MAPPER_H
#define LIB_DEVICE_MAPPER_H
#include <inttypes.h>
#include <sys/types.h>
#ifdef linux
# include <linux/types.h>
#endif
/*
* Since it is quite laborious to build the ioctl
* arguments for the device-mapper people are
* encouraged to use this library.
*
* You will need to build a struct dm_task for
* each ioctl command you want to execute.
*/
typedef void (*dm_log_fn) (int level, const char *file, int line,
const char *f, ...);
/*
* The library user may wish to register their own
* logging function, by default errors go to
* stderr.
*/
void dm_log_init(dm_log_fn fn);
void dm_log_init_verbose(int level);
enum {
DM_DEVICE_CREATE,
DM_DEVICE_RELOAD,
DM_DEVICE_REMOVE,
DM_DEVICE_REMOVE_ALL,
DM_DEVICE_SUSPEND,
DM_DEVICE_RESUME,
DM_DEVICE_INFO,
DM_DEVICE_DEPS,
DM_DEVICE_RENAME,
DM_DEVICE_VERSION,
DM_DEVICE_STATUS,
DM_DEVICE_TABLE,
DM_DEVICE_WAITEVENT,
DM_DEVICE_LIST,
DM_DEVICE_CLEAR,
DM_DEVICE_MKNODES
};
struct dm_task;
struct dm_task *dm_task_create(int type);
void dm_task_destroy(struct dm_task *dmt);
int dm_task_set_name(struct dm_task *dmt, const char *name);
int dm_task_set_uuid(struct dm_task *dmt, const char *uuid);
/*
* Retrieve attributes after an info.
*/
struct dm_info {
int exists;
int suspended;
int live_table;
int inactive_table;
int32_t open_count;
uint32_t event_nr;
uint32_t major;
uint32_t minor; /* minor device number */
int read_only; /* 0:read-write; 1:read-only */
int32_t target_count;
};
struct dm_deps {
uint32_t count;
uint32_t filler;
uint64_t device[0];
};
struct dm_names {
uint64_t dev;
uint32_t next; /* Offset to next struct from start of this struct */
char name[0];
};
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
const char *dm_task_get_name(struct dm_task *dmt);
const char *dm_task_get_uuid(struct dm_task *dmt);
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
struct dm_names *dm_task_get_names(struct dm_task *dmt);
int dm_task_set_ro(struct dm_task *dmt);
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
int dm_task_set_minor(struct dm_task *dmt, int minor);
int dm_task_set_major(struct dm_task *dmt, int major);
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
/*
* Use these to prepare for a create or reload.
*/
int dm_task_add_target(struct dm_task *dmt,
uint64_t start,
uint64_t size, const char *ttype, const char *params);
/*
* Format major/minor numbers correctly for input to driver
*/
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
/* Use this to retrive target information returned from a STATUS call */
void *dm_get_next_target(struct dm_task *dmt,
void *next, uint64_t *start, uint64_t *length,
char **target_type, char **params);
/*
* Call this to actually run the ioctl.
*/
int dm_task_run(struct dm_task *dmt);
/*
* Configure the device-mapper directory
*/
int dm_set_dev_dir(const char *dir);
const char *dm_dir(void);
/* Release library resources */
void dm_lib_release(void);
void dm_lib_exit(void);
#endif /* LIB_DEVICE_MAPPER_H */

View File

@ -0,0 +1,382 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "libdm-targets.h"
#include "libdm-common.h"
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <linux/dm-ioctl.h>
#include <linux/kdev_t.h>
#define DEV_DIR "/dev/"
static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
static int _verbose = 0;
/*
* Library users can provide their own logging
* function.
*/
static void _default_log(int level, const char *file, int line,
const char *f, ...)
{
va_list ap;
if (level > _LOG_WARN && !_verbose)
return;
va_start(ap, f);
if (level < _LOG_WARN)
vfprintf(stderr, f, ap);
else
vprintf(f, ap);
va_end(ap);
if (level < _LOG_WARN)
fprintf(stderr, "\n");
else
fprintf(stdout, "\n");
}
dm_log_fn _log = _default_log;
void dm_log_init(dm_log_fn fn)
{
_log = fn;
}
void dm_log_init_verbose(int level)
{
_verbose = level;
}
static void _build_dev_path(char *buffer, size_t len, const char *dev_name)
{
/* If there's a /, assume caller knows what they're doing */
if (strchr(dev_name, '/'))
snprintf(buffer, len, "%s", dev_name);
else
snprintf(buffer, len, "%s/%s", _dm_dir, dev_name);
}
int dm_get_library_version(char *version, size_t size)
{
strncpy(version, DM_LIB_VERSION, size);
return 1;
}
struct dm_task *dm_task_create(int type)
{
struct dm_task *dmt = malloc(sizeof(*dmt));
if (!dm_check_version())
return NULL;
if (!dmt) {
log_error("dm_task_create: malloc(%d) failed", sizeof(*dmt));
return NULL;
}
memset(dmt, 0, sizeof(*dmt));
dmt->type = type;
dmt->minor = -1;
dmt->major = -1;
return dmt;
}
int dm_task_set_name(struct dm_task *dmt, const char *name)
{
char *pos;
char path[PATH_MAX];
struct stat st1, st2;
if (dmt->dev_name) {
free(dmt->dev_name);
dmt->dev_name = NULL;
}
/* If path was supplied, remove it if it points to the same device
* as its last component.
*/
if ((pos = strrchr(name, '/'))) {
snprintf(path, sizeof(path), "%s/%s", _dm_dir, pos + 1);
if (stat(name, &st1) || stat(path, &st2) ||
!(st1.st_dev == st2.st_dev)) {
log_error("dm_task_set_name: Device %s not found",
name);
return 0;
}
name = pos + 1;
}
if (!(dmt->dev_name = strdup(name))) {
log_error("dm_task_set_name: strdup(%s) failed", name);
return 0;
}
return 1;
}
int dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
{
if (dmt->uuid) {
free(dmt->uuid);
dmt->uuid = NULL;
}
if (!(dmt->uuid = strdup(uuid))) {
log_error("dm_task_set_uuid: strdup(%s) failed", uuid);
return 0;
}
return 1;
}
int dm_task_set_major(struct dm_task *dmt, int major)
{
dmt->major = major;
log_debug("Setting major: %d", dmt->major);
return 1;
}
int dm_task_set_minor(struct dm_task *dmt, int minor)
{
dmt->minor = minor;
log_debug("Setting minor: %d", dmt->minor);
return 1;
}
int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
const char *ttype, const char *params)
{
struct target *t = create_target(start, size, ttype, params);
if (!t)
return 0;
if (!dmt->head)
dmt->head = dmt->tail = t;
else {
dmt->tail->next = t;
dmt->tail = t;
}
return 1;
}
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
{
char path[PATH_MAX];
struct stat info;
dev_t dev = MKDEV(major, minor);
_build_dev_path(path, sizeof(path), dev_name);
if (stat(path, &info) >= 0) {
if (!S_ISBLK(info.st_mode)) {
log_error("A non-block device file at '%s' "
"is already present", path);
return 0;
}
if (info.st_rdev == dev)
return 1;
if (unlink(path) < 0) {
log_error("Unable to unlink device node for '%s'",
dev_name);
return 0;
}
}
if (mknod(path, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, dev) < 0) {
log_error("Unable to make device node for '%s'", dev_name);
return 0;
}
return 1;
}
static int _rename_dev_node(const char *old_name, const char *new_name)
{
char oldpath[PATH_MAX];
char newpath[PATH_MAX];
struct stat info;
_build_dev_path(oldpath, sizeof(oldpath), old_name);
_build_dev_path(newpath, sizeof(newpath), new_name);
if (stat(newpath, &info) == 0) {
if (!S_ISBLK(info.st_mode)) {
log_error("A non-block device file at '%s' "
"is already present", newpath);
return 0;
}
if (unlink(newpath) < 0) {
if (errno == EPERM) {
/* devfs, entry has already been renamed */
return 1;
}
log_error("Unable to unlink device node for '%s'",
new_name);
return 0;
}
}
if (rename(oldpath, newpath) < 0) {
log_error("Unable to rename device node from '%s' to '%s'",
old_name, new_name);
return 0;
}
return 1;
}
static int _rm_dev_node(const char *dev_name)
{
char path[PATH_MAX];
struct stat info;
_build_dev_path(path, sizeof(path), dev_name);
if (stat(path, &info) < 0)
return 1;
if (unlink(path) < 0) {
log_error("Unable to unlink device node for '%s'", dev_name);
return 0;
}
return 1;
}
typedef enum {
NODE_ADD,
NODE_DEL,
NODE_RENAME
} node_op_t;
static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
uint32_t minor, const char *old_name)
{
switch (type) {
case NODE_ADD:
return _add_dev_node(dev_name, major, minor);
case NODE_DEL:
return _rm_dev_node(dev_name);
case NODE_RENAME:
return _rename_dev_node(old_name, dev_name);
}
return 1;
}
static LIST_INIT(_node_ops);
struct node_op_parms {
struct list list;
node_op_t type;
char *dev_name;
uint32_t major;
uint32_t minor;
char *old_name;
char names[0];
};
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
}
static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
uint32_t minor, const char *old_name)
{
struct node_op_parms *nop;
size_t len = strlen(dev_name) + strlen(old_name) + 2;
char *pos;
if (!(nop = malloc(sizeof(*nop) + len))) {
log_error("Insufficient memory to stack mknod operation");
return 0;
}
pos = nop->names;
nop->type = type;
nop->major = major;
nop->minor = minor;
_store_str(&pos, &nop->dev_name, dev_name);
_store_str(&pos, &nop->old_name, old_name);
list_add(&_node_ops, &nop->list);
return 1;
}
static void _pop_node_ops(void)
{
struct list *noph, *nopht;
struct node_op_parms *nop;
list_iterate_safe(noph, nopht, &_node_ops) {
nop = list_item(noph, struct node_op_parms);
_do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
nop->old_name);
list_del(&nop->list);
free(nop);
}
}
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
{
return _stack_node_op(NODE_ADD, dev_name, major, minor, "");
}
int rename_dev_node(const char *old_name, const char *new_name)
{
return _stack_node_op(NODE_RENAME, new_name, 0, 0, old_name);
}
int rm_dev_node(const char *dev_name)
{
return _stack_node_op(NODE_DEL, dev_name, 0, 0, "");
}
void update_devs(void)
{
_pop_node_ops();
}
int dm_set_dev_dir(const char *dir)
{
snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR);
return 1;
}
const char *dm_dir(void)
{
return _dm_dir;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef LIB_DMCOMMON_H
#define LIB_DMCOMMON_H
#include "libdevmapper.h"
#define _LOG_DEBUG 7
#define _LOG_INFO 6
#define _LOG_NOTICE 5
#define _LOG_WARN 4
#define _LOG_ERR 3
#define _LOG_FATAL 2
extern dm_log_fn _log;
#define log_error(msg, x...) _log(_LOG_ERR, __FILE__, __LINE__, msg, ## x)
#define log_print(msg, x...) _log(_LOG_WARN, __FILE__, __LINE__, msg, ## x)
#define log_verbose(msg, x...) _log(_LOG_NOTICE, __FILE__, __LINE__, msg, ## x)
#define log_very_verbose(msg, x...) _log(_LOG_INFO, __FILE__, __LINE__, msg, ## x)
#define log_debug(msg, x...) _log(_LOG_DEBUG, __FILE__, __LINE__, msg, ## x)
struct target *create_target(uint64_t start,
uint64_t len,
const char *type, const char *params);
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major);
int rm_dev_node(const char *dev_name);
int rename_dev_node(const char *old_name, const char *new_name);
void update_devs(void);
#define DM_LIB_VERSION "1.00.07-ioctl (2003-11-21)"
#endif

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2001 Sistina Software
*
* This file is released under the LGPL.
*/
#ifndef _LVM_LIST_H
#define _LVM_LIST_H
#include <assert.h>
struct list {
struct list *n, *p;
};
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head)
{
head->n = head->p = head;
}
static inline void list_add(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head;
elem->p = head->p;
head->p->n = elem;
head->p = elem;
}
static inline void list_add_h(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head->n;
elem->p = head;
head->n->p = elem;
head->n = elem;
}
static inline void list_del(struct list *elem)
{
elem->n->p = elem->p;
elem->p->n = elem->n;
}
static inline int list_empty(struct list *head)
{
return head->n == head;
}
static inline int list_end(struct list *head, struct list *elem)
{
return elem->n == head;
}
static inline struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
#define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */
#define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
/* Given a known element in a known structure, locate the list head */
#define list_head(v, t, e) struct_field(v, t, e, list)
#endif

View File

@ -26,7 +26,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <libsysfs.h>
#include <libdevmapper.h>
#include "libdevmapper/libdevmapper.h"
#include "main.h"
static int
@ -458,9 +458,7 @@ static int
make_dm_node(char * str)
{
int r = 0;
dev_t dev;
char buff[FILE_NAME_SIZE];
int major, minor;
struct dm_names * names;
unsigned next = 0;
struct dm_task *dmt;
@ -486,14 +484,9 @@ make_dm_node(char * str)
names = (void *) names + next;
} while (next);
major = (int) MAJOR(names->dev);
minor = (int) MINOR(names->dev);
dev = major << sizeof(dev_t);
dev = dev | minor;
sprintf(buff, "/dev/mapper/%s", str);
unlink(buff);
mknod(buff, 0600 | S_IFBLK, dev);
mknod(buff, 0600 | S_IFBLK, names->dev);
out:
dm_task_destroy(dmt);
@ -729,9 +722,10 @@ main(int argc, char *argv[])
if (conf.verbose) {
print_all_path(&conf, all_paths);
printf("\n");
fprintf(stdout, "\n");
print_all_mp(all_paths, mp, nmp);
printf("\n");
fprintf(stdout, "\n");
//printf("\n");
}
if (conf.dry_run)

View File

@ -46,7 +46,7 @@
#define TUR_CMD_LEN 6
#define MX_ALLOC_LEN 255
#define BLKGETSIZE _IO(0x12,96)
#define DM_TARGET "multipath"
#define DM_TARGET "striped"
#define PINDEX(x,y) mp[(x)].pindex[(y)]
@ -105,8 +105,8 @@ struct env {
/* Build version */
#define PROG "multipath"
#define VERSION_CODE 0x000006
#define DATE_CODE 0x271103
#define VERSION_CODE 0x000009
#define DATE_CODE 0x0C0503
#define MULTIPATH_VERSION(version) \
(version >> 16) & 0xFF, \