mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
[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:
parent
83fa40fc2a
commit
2bf80b67d1
@ -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)
|
||||
|
15
extras/multipath/libdevmapper/Makefile
Normal file
15
extras/multipath/libdevmapper/Makefile
Normal 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
|
1092
extras/multipath/libdevmapper/ioctl/libdevmapper.c
Normal file
1092
extras/multipath/libdevmapper/ioctl/libdevmapper.c
Normal file
File diff suppressed because it is too large
Load Diff
111
extras/multipath/libdevmapper/ioctl/libdm-compat.h
Normal file
111
extras/multipath/libdevmapper/ioctl/libdm-compat.h
Normal 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
|
51
extras/multipath/libdevmapper/ioctl/libdm-targets.h
Normal file
51
extras/multipath/libdevmapper/ioctl/libdm-targets.h
Normal 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
|
147
extras/multipath/libdevmapper/libdevmapper.h
Normal file
147
extras/multipath/libdevmapper/libdevmapper.h
Normal 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 */
|
382
extras/multipath/libdevmapper/libdm-common.c
Normal file
382
extras/multipath/libdevmapper/libdm-common.c
Normal 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;
|
||||
}
|
38
extras/multipath/libdevmapper/libdm-common.h
Normal file
38
extras/multipath/libdevmapper/libdm-common.h
Normal 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
|
99
extras/multipath/libdevmapper/list.h
Normal file
99
extras/multipath/libdevmapper/list.h
Normal 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
|
@ -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)
|
||||
|
@ -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, \
|
||||
|
Loading…
x
Reference in New Issue
Block a user