[DRBD-cvs] svn commit by phil - r2386 - in trunk: . drbd drbd/linux
user - The new netlink (connector) based userland <-> kernel i
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Fri Aug 25 10:50:51 CEST 2006
Author: phil
Date: 2006-08-25 10:50:47 +0200 (Fri, 25 Aug 2006)
New Revision: 2386
Added:
trunk/drbd/drbd_nl.c
trunk/drbd/linux/drbd_limits.h
trunk/drbd/linux/drbd_nl.h
trunk/drbd/linux/drbd_tag_magic.h
Removed:
trunk/drbd/drbd_sizeof_sanity_check.c
trunk/user/drbd_limits.h
trunk/user/drbd_nl.h
trunk/user/drbd_tag_magic.h
trunk/user/drbdsetup.c
Modified:
trunk/ROADMAP
trunk/drbd/Makefile-2.6
trunk/drbd/drbd_compat_wrappers.h
trunk/drbd/drbd_fs.c
trunk/drbd/drbd_int.h
trunk/drbd/drbd_main.c
trunk/drbd/drbd_proc.c
trunk/drbd/drbd_receiver.c
trunk/drbd/drbd_req.c
trunk/drbd/drbd_worker.c
trunk/drbd/linux/drbd.h
trunk/drbd/linux/drbd_config.h
trunk/user/Makefile
trunk/user/drbdadm_parser.c
trunk/user/drbdsetup_nl.c
trunk/user/drbdtool_common.c
Log:
The new netlink (connector) based userland <-> kernel interface.
It probably breaks a lot of things, but it the way to go. It will
take a few days before everything works again, and the bugs are
shaked out...
Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/ROADMAP 2006-08-25 08:50:47 UTC (rev 2386)
@@ -417,8 +417,41 @@
at the beginning, including the expected API version.
Consider using DRBD ioctls with some char device similar to
/dev/mapper/control
- 0% DONE
+ The new interface is now based on netlink (actually connector).
+ It is based on the concept of tag lists. The idea is that on the
+ interface we pass lists (actually arrays) of tags. Where each
+ tag identifies the following sniplet of data.
+ Each tag also states if it is mandatory.
+
+ In case we have to add a new value to the interface, the
+ existing userland tools continue to work with newer kernel
+ modules and vice versa. (Only the older part of the two will
+ inform the user with a warning, that there was a unknown
+ tag on the interface, and that the unknown tag got ignored)
+ But the basic functionality stays intact!
+
+ While implementing this, we also implemented dynamic device allocation.
+
+ drbdsetup is basically call compatible to its ioctl based
+ ancestor, but has two now options:
+
+ --create-device ___ create the device in case int does not exist yet.
+ --set-defaults ____ set all not mentioned options to it's default values.
+
+ Things to do:
+
+ * Fix drbdadm (nees to use --create-device and --set-defaults; adjust
+ needs to be changes since the kernel can not return the device
+ names of backing and meta device.)
+ * Remove the memset( .., 0, ...) from drbd_nl.c. Use the defaults instead.
+ * Use only one connector callback.
+ * use try_module_get() and put_module() when control enters a/the connector
+ callback.
+ * Locking in userspace, to prevent multiple instances of drbdsetup
+
+ 50% DONE
+
15 Accept BIOs bigger than one page, probabely up to 32k (8 pages)
currently.
* Normal Requsts. -> DONE
@@ -785,7 +818,7 @@
34 Improve the initial hand-shake, to identify the sockets (and TCP-
links) by an initial message, and not only by the connection timming.
- 99% DONE
+ 99% DONE
35 Bigger AL-extents (e.g. 16MB)
@@ -828,17 +861,14 @@
2 Implement online verification
-3 dynamic device allocation
- (requires configuration throu a new mechanism (netlink socket/misc dev)
-
-4 Change the bitmap code to work with unmapped highmem pages, instead
+3 Change the bitmap code to work with unmapped highmem pages, instead
of using vmalloc()ed memory. This allows users of 32bit platforms
to use drbd on big devices (in the ~3TB range)
-5 3 node support. Do and test a 3 node setup (2nd DRBD stacked over
+4 3 node support. Do and test a 3 node setup (2nd DRBD stacked over
a DRBD pair). Enhance the user level tools to support the 3 node
setup.
-6 Have protocol version 74 available in drbd-0.8, to allow rolling
+5 Have protocol version 74 available in drbd-0.8, to allow rolling
upgrades
Modified: trunk/drbd/Makefile-2.6
===================================================================
--- trunk/drbd/Makefile-2.6 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/Makefile-2.6 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,7 +1,6 @@
#CFLAGS_drbd_sizeof_sanity_check.o = -Wpadded # -Werror
-drbd-objs := drbd_sizeof_sanity_check.o \
- drbd_buildtag.o drbd_bitmap.o drbd_fs.o drbd_proc.o \
+drbd-objs := drbd_buildtag.o drbd_bitmap.o drbd_proc.o \
drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o \
- lru_cache.o drbd_main.o drbd_strings.o
+ lru_cache.o drbd_main.o drbd_strings.o drbd_nl.o
obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o
Modified: trunk/drbd/drbd_compat_wrappers.h
===================================================================
--- trunk/drbd/drbd_compat_wrappers.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_compat_wrappers.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -174,14 +174,11 @@
*/
static inline void drbd_generic_make_request(int rw, struct bio *bio)
{
- drbd_dev *mdev = drbd_conf -1; // for DRBD_ratelimit
bio->bi_rw = rw; // on the receiver side, e->..rw was not yet defined.
if (!bio->bi_bdev) {
- if (DRBD_ratelimit(5*HZ,5)) {
- printk(KERN_ERR "drbd_generic_make_request: bio->bi_bdev == NULL\n");
- dump_stack();
- }
+ printk(KERN_ERR "drbd_generic_make_request: bio->bi_bdev == NULL\n");
+ dump_stack();
drbd_bio_IO_error(bio);
return;
}
Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_fs.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -54,7 +54,7 @@
struct drbd_backing_dev *bdev)
{
sector_t md_size_sect = 0;
- switch(bdev->md_index) {
+ switch(bdev->dc.meta_dev_idx) {
default:
case DRBD_MD_INDEX_FLEX_EXT:
/* just occupy the full device; unit: sectors */
@@ -180,7 +180,7 @@
sector_t p_size = mdev->p_size; // partner's disk size.
sector_t la_size = bdev->md.la_size_sect; // last agreed size.
sector_t m_size; // my size
- sector_t u_size = bdev->u_size; // size requested by user.
+ sector_t u_size = bdev->dc.disk_size; // size requested by user.
sector_t size=0;
m_size = drbd_get_max_capacity(bdev);
@@ -316,7 +316,7 @@
drbd_state_t ns,os;
int rv;
- minor=(int)(mdev-drbd_conf);
+ minor=mdev_to_minor(mdev);
/* if you want to reconfigure, please tear down first */
if (mdev->state.disk > Diskless)
@@ -439,10 +439,10 @@
goto release_bdev2_fail_ioctl;
}
- nbc->md_index = new_conf.meta_index;
- nbc->u_size = new_conf.disk_size;
- nbc->on_io_error = new_conf.on_io_error;
- nbc->fencing = new_conf.fencing;
+ nbc->dc.meta_dev_idx = new_conf.meta_index;
+ nbc->dc.disk_size = new_conf.disk_size;
+ nbc->dc.on_io_error = new_conf.on_io_error;
+ nbc->dc.fencing = new_conf.fencing;
drbd_md_set_sector_offsets(mdev,nbc);
retcode = drbd_md_read(mdev,nbc);
@@ -562,7 +562,7 @@
}
if( ns.disk == Consistent &&
- ( ns.pdsk == Outdated || nbc->fencing == DontCare ) ) {
+ ( ns.pdsk == Outdated || nbc->dc.fencing == DontCare ) ) {
ns.disk = UpToDate;
}
@@ -616,17 +616,17 @@
cn.meta_device_major = MAJOR(mdev->bc->md_bdev->bd_dev);
cn.meta_device_minor = MINOR(mdev->bc->md_bdev->bd_dev);
bdevname(mdev->bc->md_bdev,cn.meta_device_name);
- cn.meta_index=mdev->bc->md_index;
- cn.on_io_error=mdev->bc->on_io_error;
- cn.fencing=mdev->bc->fencing;
+ cn.meta_index=mdev->bc->dc.meta_dev_idx;
+ cn.on_io_error=mdev->bc->dc.on_io_error;
+ cn.fencing=mdev->bc->dc.fencing;
dec_local(mdev);
}
cn.state=mdev->state;
if(inc_net(mdev)) {
- memcpy(&cn.nconf, mdev->net_conf, sizeof(struct net_config));
+ memcpy(&cn.nconf, mdev->net_conf, sizeof(struct net_conf));
dec_net(mdev);
}
- memcpy(&cn.sconf, &mdev->sync_conf, sizeof(struct syncer_config));
+ memcpy(&cn.sconf, &mdev->sync_conf, sizeof(struct syncer_conf));
if (copy_to_user(arg,&cn,sizeof(struct ioctl_get_config)))
return -EFAULT;
@@ -636,24 +636,23 @@
STATIC
-int drbd_ioctl_set_net(struct Drbd_Conf *mdev, struct ioctl_net_config * arg)
+int drbd_ioctl_set_net(struct Drbd_Conf *mdev, struct ioctl_net_conf * arg)
{
- int i,minor,ns;
+ int i,ns;
enum ret_codes retcode;
- struct net_config *new_conf = NULL;
+ struct net_conf *new_conf = NULL;
struct crypto_tfm* tfm = NULL;
struct hlist_head *new_tl_hash = NULL;
struct hlist_head *new_ee_hash = NULL;
+ struct Drbd_Conf *odev;
- minor=(int)(mdev-drbd_conf);
-
- new_conf = kmalloc(sizeof(struct net_config),GFP_KERNEL);
+ new_conf = kmalloc(sizeof(struct net_conf),GFP_KERNEL);
if(!new_conf) {
retcode=KMallocFailed;
goto fail_ioctl;
}
- if (copy_from_user(new_conf, &arg->config,sizeof(struct net_config)))
+ if (copy_from_user(new_conf, &arg->config,sizeof(struct net_conf)))
return -EFAULT;
if( mdev->state.role == Primary && new_conf->want_lose ) {
@@ -665,16 +664,17 @@
#define M_PORT(A) (((struct sockaddr_in *)&A->my_addr)->sin_port)
#define O_ADDR(A) (((struct sockaddr_in *)&A->other_addr)->sin_addr.s_addr)
#define O_PORT(A) (((struct sockaddr_in *)&A->other_addr)->sin_port)
- for(i=0;i<minor_count;i++) {
- if( i!=minor && drbd_conf[i].state.conn > StandAlone &&
- M_ADDR(new_conf) == M_ADDR(drbd_conf[i].net_conf) &&
- M_PORT(new_conf) == M_PORT(drbd_conf[i].net_conf) ) {
+ for(i=0;i<next_minor;i++) {
+ odev = minor_to_mdev(i);
+ if( mdev != odev && odev->state.conn > StandAlone &&
+ M_ADDR(new_conf) == M_ADDR(odev->net_conf) &&
+ M_PORT(new_conf) == M_PORT(odev->net_conf) ) {
retcode=LAAlreadyInUse;
goto fail_ioctl;
}
- if( i!=minor && drbd_conf[i].state.conn > StandAlone &&
- O_ADDR(new_conf) == O_ADDR(drbd_conf[i].net_conf) &&
- O_PORT(new_conf) == O_PORT(drbd_conf[i].net_conf) ) {
+ if( mdev != odev && odev->state.conn > StandAlone &&
+ O_ADDR(new_conf) == O_ADDR(odev->net_conf) &&
+ O_PORT(new_conf) == O_PORT(odev->net_conf) ) {
retcode=OAAlreadyInUse;
goto fail_ioctl;
}
@@ -808,7 +808,7 @@
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL };
- snprintf(mb,12,"minor-%d",(int)(mdev-drbd_conf));
+ snprintf(mb,12,"minor-%d",mdev_to_minor(mdev));
return call_usermodehelper("/sbin/drbdadm",argv,envp,1);
}
@@ -822,7 +822,7 @@
fp = DontCare;
if(inc_local(mdev)) {
- fp = mdev->bc->fencing;
+ fp = mdev->bc->dc.fencing;
dec_local(mdev);
}
@@ -1015,9 +1015,9 @@
}
STATIC int drbd_ioctl_set_syncer(struct Drbd_Conf *mdev,
- struct ioctl_syncer_config* arg)
+ struct ioctl_syncer_conf* arg)
{
- struct syncer_config sc;
+ struct syncer_conf sc;
drbd_dev *odev;
int err;
@@ -1025,12 +1025,12 @@
if(copy_from_user(&sc,&arg->config,sizeof(sc))) return -EFAULT;
if( sc.after != -1) {
- if( sc.after < -1 || sc.after > minor_count ) return -ERANGE;
- odev = drbd_conf + sc.after; // check against loops in
+ if( sc.after < -1 || sc.after > next_minor ) return -ERANGE;
+ odev = minor_to_mdev(sc.after); // check against loops in
while(1) {
if( odev == mdev ) return -EBADMSG; // cycle found.
if( odev->sync_conf.after == -1 ) break; // no cycles.
- odev = drbd_conf + odev->sync_conf.after;
+ odev = minor_to_mdev(odev->sync_conf.after);
}
}
@@ -1181,8 +1181,8 @@
struct gendisk *disk = bdev->bd_disk;
minor = MINOR(inode->i_rdev);
- if (minor >= minor_count) return -ENODEV;
- mdev = drbd_conf + minor;
+ if (minor >= next_minor) return -ENODEV;
+ mdev = minor_to_mdev(minor);
D_ASSERT(MAJOR(inode->i_rdev) == MAJOR_NR);
@@ -1259,7 +1259,7 @@
break;
}
err=0;
- mdev->bc->u_size = (sector_t)(u64)arg;
+ mdev->bc->dc.disk_size = (sector_t)(u64)arg;
drbd_bm_lock(mdev);
drbd_determin_dev_size(mdev);
drbd_md_sync(mdev);
@@ -1271,12 +1271,12 @@
break;
case DRBD_IOCTL_SET_NET_CONFIG:
- err = drbd_ioctl_set_net(mdev,(struct ioctl_net_config*) arg);
+ err = drbd_ioctl_set_net(mdev,(struct ioctl_net_conf*) arg);
break;
case DRBD_IOCTL_SET_SYNC_CONFIG:
err = drbd_ioctl_set_syncer(mdev,
- (struct ioctl_syncer_config*) arg);
+ (struct ioctl_syncer_conf*) arg);
break;
case DRBD_IOCTL_GET_CONFIG:
Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_int.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -129,7 +129,7 @@
// Otherwise this is not portable from gcc-2.95 to gcc-3.3
#define PRINTK(level,fmt,args...) \
printk(level DEVICE_NAME "%d: " fmt, \
- (int)(mdev-drbd_conf) , ##args)
+ mdev->minor , ##args)
#define ALERT(fmt,args...) PRINTK(KERN_ALERT, fmt , ##args)
#define ERR(fmt,args...) PRINTK(KERN_ERR, fmt , ##args)
@@ -246,24 +246,25 @@
*/
extern volatile int drbd_did_panic;
+extern struct Drbd_Conf **minor_table;
#if DRBD_PANIC == 0
#define drbd_panic(fmt, args...) \
- panic(DEVICE_NAME "%d: " fmt, (int)(mdev-drbd_conf) , ##args)
+ panic(DEVICE_NAME "%d: " fmt, mdev_to_minor(mdev) , ##args)
#elif DRBD_PANIC == 1
#error "sorry , this does not work, please contribute"
#elif DRBD_PANIC == 2
#define drbd_panic(fmt, args...) do { \
printk(KERN_EMERG DEVICE_NAME "%d: " fmt, \
- (int)(mdev-drbd_conf) , ##args); \
+ mdev_to_minor(mdev) , ##args); \
drbd_did_panic = DRBD_MAGIC; \
smp_mb(); \
- panic(DEVICE_NAME "%d: " fmt, (int)(mdev-drbd_conf) , ##args); \
+ panic(DEVICE_NAME "%d: " fmt, mdev_to_minor(mdev) , ##args); \
} while (0)
#else
#define drbd_panic(fmt, args...) do { \
printk(KERN_EMERG DEVICE_NAME "%d: " fmt, \
- (int)(mdev-drbd_conf) , ##args); \
+ mdev_to_minor(mdev) , ##args); \
} while (0)
#endif
#undef DRBD_PANIC
@@ -723,16 +724,21 @@
*/
};
+// for sync_conf and other types...
+#define PACKET(name, fields) struct name { fields };
+#define INTEGER(pn,pr,member) int member;
+#define INT64(pn,pr,member) __u64 member;
+#define BIT(pn,pr,member) unsigned member : 1;
+#define STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len;
+#include "linux/drbd_nl.h"
+
struct drbd_backing_dev {
struct block_device *backing_bdev;
struct block_device *md_bdev;
struct file *lo_file;
struct file *md_file;
- int md_index;
- enum io_error_handler on_io_error;
- enum fencing_policy fencing;
- sector_t u_size; /* user provided size */
struct drbd_md md;
+ struct disk_conf dc; /* The user provided config... */
};
struct Drbd_Conf {
@@ -746,8 +752,8 @@
struct semaphore device_mutex;
/* configured by drbdsetup */
- struct net_config *net_conf; // protected by inc_net() and dec_net()
- struct syncer_config sync_conf;
+ struct net_conf *net_conf; // protected by inc_net() and dec_net()
+ struct syncer_conf sync_conf;
struct drbd_backing_dev *bc; // protected by inc_local() dec_local()
sector_t p_size; /* partner's disk size */
@@ -831,9 +837,24 @@
int peer_seq;
spinlock_t peer_seq_lock;
struct list_head discard;
+ int minor;
};
+static inline drbd_dev *minor_to_mdev(int minor)
+{
+ drbd_dev *mdev;
+ mdev = minor < minor_count ? minor_table[minor] : NULL;
+
+ return mdev;
+}
+
+static inline int mdev_to_minor(drbd_dev *mdev)
+{
+ return mdev->minor;
+}
+
+
/*
* function declarations
*************************/
@@ -886,7 +907,7 @@
Drbd_Packet_Cmd cmd, Drbd_Header *h, size_t size);
extern int drbd_send_cmd2(drbd_dev *mdev, Drbd_Packet_Cmd cmd,
char* data, size_t size);
-extern int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc);
+extern int drbd_send_sync_param(drbd_dev *mdev, struct syncer_conf *sc);
extern int drbd_send_b_ack(drbd_dev *mdev, u32 barrier_nr,
u32 set_size);
extern int drbd_send_ack(drbd_dev *mdev, Drbd_Packet_Cmd cmd,
@@ -1092,7 +1113,6 @@
// drbd_main.c
-extern drbd_dev *drbd_conf;
extern int minor_count;
extern kmem_cache_t *drbd_request_cache;
extern kmem_cache_t *drbd_ee_cache;
@@ -1104,6 +1124,8 @@
extern int drbd_pp_vacant;
extern wait_queue_head_t drbd_pp_wait;
+extern drbd_dev *drbd_new_device(int minor);
+
// drbd_req
#define ERF_NOTLD 2 /* do not call tl_dependence */
extern void drbd_end_req(drbd_request_t *, int, int, sector_t);
@@ -1118,7 +1140,7 @@
extern sector_t drbd_new_dev_size(struct Drbd_Conf*, struct drbd_backing_dev*);
extern int drbd_determin_dev_size(drbd_dev*);
extern void drbd_setup_queue_param(drbd_dev *mdev, unsigned int);
-extern int drbd_set_role(drbd_dev *mdev, int *arg);
+extern int drbd_set_role(drbd_dev *mdev, drbd_role_t new_role, int force);
extern int drbd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
drbd_disks_t drbd_try_outdate_peer(drbd_dev *mdev);
@@ -1195,6 +1217,12 @@
extern void drbd_al_to_on_disk_bm(struct Drbd_Conf *mdev);
extern void drbd_al_shrink(struct Drbd_Conf *mdev);
+
+// drbd_nl.c
+
+void drbd_nl_cleanup(void);
+int __init drbd_nl_init(void);
+
/*
* inline helper functions
*************************/
@@ -1260,7 +1288,7 @@
unsigned long flags;
spin_lock_irqsave(&mdev->req_lock,flags);
- switch(mdev->bc->on_io_error) {
+ switch(mdev->bc->dc.on_io_error) {
case PassOn:
ERR("Ignoring local IO error!\n");
break;
@@ -1294,7 +1322,7 @@
*/
static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
{
- switch (bdev->md_index) {
+ switch (bdev->dc.meta_dev_idx) {
case DRBD_MD_INDEX_INTERNAL:
case DRBD_MD_INDEX_FLEX_INT:
return bdev->md.md_offset + bdev->md.bm_offset;
@@ -1308,7 +1336,7 @@
* to be able to catch out of band md access */
static inline sector_t drbd_md_last_sector(struct drbd_backing_dev *bdev)
{
- switch (bdev->md_index) {
+ switch (bdev->dc.meta_dev_idx) {
case DRBD_MD_INDEX_INTERNAL:
case DRBD_MD_INDEX_FLEX_INT:
return bdev->md.md_offset + MD_AL_OFFSET -1;
@@ -1321,7 +1349,7 @@
/* returns the capacity we announce to out peer */
static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
{
- switch (bdev->md_index) {
+ switch (bdev->dc.meta_dev_idx) {
case DRBD_MD_INDEX_INTERNAL:
case DRBD_MD_INDEX_FLEX_INT:
return drbd_get_capacity(bdev->backing_bdev)
@@ -1337,9 +1365,9 @@
static inline sector_t drbd_md_ss__(drbd_dev *mdev,
struct drbd_backing_dev *bdev)
{
- switch (bdev->md_index) {
+ switch (bdev->dc.meta_dev_idx) {
default: /* external, some index */
- return MD_RESERVED_SECT * bdev->md_index;
+ return MD_RESERVED_SECT * bdev->dc.meta_dev_idx;
case DRBD_MD_INDEX_INTERNAL:
/* with drbd08, internal meta data is always "flexible" */
case DRBD_MD_INDEX_FLEX_INT:
@@ -1637,7 +1665,7 @@
int recv, Drbd_Polymorph_Packet *p, char* file, int line)
{
if (dump_packets > DUMP_NONE &&
- ( ( 1 << (int)(mdev-drbd_conf)) & dump_packet_devs) )
+ ( ( 1 << mdev_to_minor(mdev)) & dump_packet_devs) )
_dump_packet(mdev,sock,recv,p,file,line);
}
#else
Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_main.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -56,24 +56,13 @@
#include <linux/vmalloc.h>
#include <linux/drbd.h>
+#include <linux/drbd_limits.h>
#include "drbd_int.h"
/* YES. We got an official device major from lanana
*/
#define LANANA_DRBD_MAJOR 147
-#ifdef CONFIG_COMPAT
-# if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
- /* FIXME on which thing could we test instead of the KERNEL_VERSION
- * again? register_ioctl32_conversion was deprecated in 2.6.10, got
- * "officially" deprecated somewhen in 2.6.12, and removed in 2.6.14.
- * so lets assume all vendor kernels did the transition. */
-# define HAVE_COMPAT_IOCTL_MEMBER
-# else
-# include <linux/ioctl32.h>
-# endif
-#endif
-
struct after_state_chg_work {
struct drbd_work w;
drbd_state_t os;
@@ -118,11 +107,8 @@
// module parameter, defined
int major_nr = LANANA_DRBD_MAJOR;
-#ifdef MODULE
-int minor_count = 2;
-#else
-int minor_count = 8;
-#endif
+int minor_count = 32;
+
int disable_bd_claim = 0;
#ifdef DUMP_EACH_PACKET
@@ -144,7 +130,8 @@
/* in 2.6.x, our device mapping and config info contains our virtual gendisks
* as member "struct gendisk *vdisk;"
*/
-struct Drbd_Conf *drbd_conf;
+struct Drbd_Conf **minor_table = NULL;
+
kmem_cache_t *drbd_request_cache;
kmem_cache_t *drbd_ee_cache;
mempool_t *drbd_request_mempool;
@@ -161,15 +148,10 @@
int drbd_pp_vacant;
wait_queue_head_t drbd_pp_wait;
-
STATIC struct block_device_operations drbd_ops = {
.owner = THIS_MODULE,
.open = drbd_open,
.release = drbd_close,
- .ioctl = drbd_ioctl,
-#ifdef HAVE_COMPAT_IOCTL_MEMBER
- .compat_ioctl = drbd_compat_ioctl,
-#endif
};
#define ARRY_SIZE(A) (sizeof(A)/sizeof(A[0]))
@@ -505,7 +487,7 @@
unsigned long flags;
int send,ok=1;
- if(mdev->bc->on_io_error != Panic && mdev->bc->on_io_error != Detach) return 1;
+ if(mdev->bc->dc.on_io_error != Panic && mdev->bc->dc.on_io_error != Detach) return 1;
spin_lock_irqsave(&mdev->req_lock,flags);
if( (send = (mdev->state.disk == Failed)) ) {
@@ -702,7 +684,7 @@
fp = DontCare;
if(inc_local(mdev)) {
- fp = mdev->bc->fencing;
+ fp = mdev->bc->dc.fencing;
dec_local(mdev);
}
@@ -768,7 +750,7 @@
fp = DontCare;
if(inc_local(mdev)) {
- fp = mdev->bc->fencing;
+ fp = mdev->bc->dc.fencing;
dec_local(mdev);
}
@@ -900,7 +882,9 @@
if ( os.disk == Diskless && os.conn == StandAlone &&
(ns.disk > Diskless || ns.conn > StandAlone) ) {
- __module_get(THIS_MODULE);
+ int i;
+ i = try_module_get(THIS_MODULE);
+ D_ASSERT(i);
}
if ( ns.role == Primary && ns.conn < Connected &&
@@ -950,7 +934,7 @@
fp = DontCare;
if(inc_local(mdev)) {
- fp = mdev->bc->fencing;
+ fp = mdev->bc->dc.fencing;
dec_local(mdev);
}
@@ -1314,7 +1298,7 @@
return ok;
}
-int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc)
+int drbd_send_sync_param(drbd_dev *mdev, struct syncer_conf *sc)
{
Drbd_SyncParam_Packet p;
@@ -1369,7 +1353,7 @@
if(inc_md_only(mdev,Attaching)) {
D_ASSERT(mdev->bc->backing_bdev);
d_size = drbd_get_max_capacity(mdev->bc);
- p.u_size = cpu_to_be64(mdev->bc->u_size);
+ p.u_size = cpu_to_be64(mdev->bc->dc.disk_size);
dec_local(mdev);
} else d_size = 0;
@@ -1901,19 +1885,19 @@
STATIC int drbd_open(struct inode *inode, struct file *file)
{
- int minor;
+ drbd_dev *mdev;
- minor = MINOR(inode->i_rdev);
- if(minor >= minor_count) return -ENODEV;
+ mdev = minor_to_mdev(MINOR(inode->i_rdev));
+ if(!mdev) return -ENODEV;
if (file->f_mode & FMODE_WRITE) {
- if( drbd_conf[minor].state.role == Secondary) {
+ if( mdev->state.role == Secondary) {
return -EROFS;
}
- set_bit(WRITER_PRESENT, &drbd_conf[minor].flags);
+ set_bit(WRITER_PRESENT, &mdev->flags);
}
- drbd_conf[minor].open_cnt++;
+ mdev->open_cnt++;
return 0;
}
@@ -1921,10 +1905,10 @@
STATIC int drbd_close(struct inode *inode, struct file *file)
{
/* do not use *file (May be NULL, in case of a unmount :-) */
- int minor;
+ drbd_dev *mdev;
- minor = MINOR(inode->i_rdev);
- if(minor >= minor_count) return -ENODEV;
+ mdev = minor_to_mdev(MINOR(inode->i_rdev));
+ if(!mdev) return -ENODEV;
/*
printk(KERN_ERR DEVICE_NAME ": close(inode=%p,file=%p)"
@@ -1932,8 +1916,8 @@
inode->i_writecount);
*/
- if (--drbd_conf[minor].open_cnt == 0) {
- clear_bit(WRITER_PRESENT, &drbd_conf[minor].flags);
+ if (--mdev->open_cnt == 0) {
+ clear_bit(WRITER_PRESENT, &mdev->flags);
}
return 0;
@@ -1968,9 +1952,9 @@
void drbd_set_defaults(drbd_dev *mdev)
{
- mdev->sync_conf.after = -1;
- mdev->sync_conf.rate = 250;
- mdev->sync_conf.al_extents = 127; // 512 MB active set
+ mdev->sync_conf.after = DRBD_AFTER_DEF;
+ mdev->sync_conf.rate = DRBD_RATE_DEF;
+ mdev->sync_conf.al_extents = DRBD_AL_EXTENTS_DEF; // 512 MB active set
mdev->state = (drbd_state_t){ { Secondary,
Unknown,
StandAlone,
@@ -2138,7 +2122,6 @@
D_ASSERT(list_empty(&mdev->resync_work.list));
D_ASSERT(list_empty(&mdev->unplug_work.list));
- drbd_set_defaults(mdev);
}
@@ -2250,28 +2233,29 @@
unregister_reboot_notifier(&drbd_notifier);
- if (drbd_conf) {
+ drbd_nl_cleanup();
+
+ if (minor_table) {
for (i = 0; i < minor_count; i++) {
- drbd_dev *mdev = drbd_conf + i;
+ drbd_dev *mdev = minor_to_mdev(i);
+ if(!mdev) continue;
- if (mdev) {
- down(&mdev->device_mutex);
- rr = Secondary;
- drbd_set_role(mdev,&rr);
- up(&mdev->device_mutex);
- drbd_sync_me(mdev);
- drbd_thread_stop(&mdev->receiver);
- }
+ down(&mdev->device_mutex);
+ drbd_set_role(mdev,Secondary,0);
+ up(&mdev->device_mutex);
+ drbd_sync_me(mdev);
+ drbd_thread_stop(&mdev->receiver);
}
if (drbd_proc)
remove_proc_entry("drbd",&proc_root);
i=minor_count;
while (i--) {
- drbd_dev *mdev = drbd_conf+i;
+ drbd_dev *mdev = minor_to_mdev(i);
struct gendisk **disk = &mdev->vdisk;
request_queue_t **q = &mdev->rq_queue;
+ if(!mdev) continue;
drbd_free_resources(mdev);
if (*disk) {
@@ -2338,26 +2322,7 @@
drbd_destroy_mempools();
}
-#ifndef HAVE_COMPAT_IOCTL_MEMBER
-#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64)
- lock_kernel();
- unregister_ioctl32_conversion(DRBD_IOCTL_GET_VERSION);
- unregister_ioctl32_conversion(DRBD_IOCTL_SET_STATE);
- unregister_ioctl32_conversion(DRBD_IOCTL_SET_DISK_CONFIG);
- unregister_ioctl32_conversion(DRBD_IOCTL_SET_NET_CONFIG);
- unregister_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_NET);
- unregister_ioctl32_conversion(DRBD_IOCTL_GET_CONFIG);
- unregister_ioctl32_conversion(DRBD_IOCTL_INVALIDATE);
- unregister_ioctl32_conversion(DRBD_IOCTL_INVALIDATE_REM);
- unregister_ioctl32_conversion(DRBD_IOCTL_SET_SYNC_CONFIG);
- unregister_ioctl32_conversion(DRBD_IOCTL_SET_DISK_SIZE);
- unregister_ioctl32_conversion(DRBD_IOCTL_WAIT_CONNECT);
- unregister_ioctl32_conversion(DRBD_IOCTL_WAIT_SYNC);
- unregister_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_DISK);
- unlock_kernel();
-#endif
-#endif
- kfree(drbd_conf);
+ kfree(minor_table);
if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0)
printk(KERN_ERR DEVICE_NAME": unregister of device failed\n");
@@ -2365,9 +2330,83 @@
printk(KERN_INFO DEVICE_NAME": module cleanup done.\n");
}
+drbd_dev *drbd_new_device(int minor)
+{
+ drbd_dev *mdev = NULL;
+ struct gendisk *disk;
+ request_queue_t *q;
+
+ mdev = kmalloc(sizeof(drbd_dev),GFP_KERNEL);
+ if(!mdev) goto Enomem;
+ memset(mdev,0,sizeof(drbd_dev ));
+
+ mdev->minor = minor;
+
+ drbd_init_set_defaults(mdev);
+
+ q = blk_alloc_queue(GFP_KERNEL);
+ if (!q) goto Enomem;
+ mdev->rq_queue = q;
+ q->queuedata = mdev;
+ q->max_segment_size = DRBD_MAX_SEGMENT_SIZE;
+
+ disk = alloc_disk(1);
+ if (!disk) goto Enomem;
+ mdev->vdisk = disk;
+
+ set_disk_ro( disk, TRUE );
+
+ disk->queue = q;
+ disk->major = MAJOR_NR;
+ disk->first_minor = minor;
+ disk->fops = &drbd_ops;
+ sprintf(disk->disk_name, DEVICE_NAME "%d", minor);
+ sprintf(disk->devfs_name, "%s/%d", drbd_devfs_name, minor);
+ disk->private_data = mdev;
+ add_disk(disk);
+
+ mdev->this_bdev = bdget(MKDEV(MAJOR_NR,minor));
+ // we have no partitions. we contain only ourselves.
+ mdev->this_bdev->bd_contains = mdev->this_bdev;
+ if (bd_claim(mdev->this_bdev,drbd_sec_holder)) {
+ // Initial we are Secondary -> should claim myself.
+ WARN("Could not bd_claim() myself.");
+ } else if (disable_bd_claim) {
+ bd_release(mdev->this_bdev);
+ }
+
+ blk_queue_make_request(q, drbd_make_request_26);
+ blk_queue_merge_bvec(q, drbd_merge_bvec);
+ q->queue_lock = &mdev->req_lock; // needed since we use
+ // plugging on a queue, that actually has no requests!
+ q->unplug_fn = drbd_unplug_fn;
+
+ mdev->md_io_page = alloc_page(GFP_KERNEL);
+ if(!mdev->md_io_page) goto Enomem;
+
+ if (drbd_bm_init(mdev)) goto Enomem;
+ // no need to lock access, we are still initializing the module.
+ init_MUTEX(&mdev->device_mutex);
+ if (!tl_init(mdev)) goto Enomem;
+
+ mdev->app_reads_hash=kmalloc(APP_R_HSIZE*sizeof(void*),GFP_KERNEL);
+ if (!mdev->app_reads_hash) goto Enomem;
+ memset(mdev->app_reads_hash,0,APP_R_HSIZE*sizeof(void*));
+
+ return mdev;
+
+ Enomem:
+ if(mdev) {
+ if(mdev->app_reads_hash) kfree(mdev->app_reads_hash);
+ if(mdev->md_io_page) __free_page(mdev->md_io_page);
+ kfree(mdev);
+ }
+ return NULL;
+}
+
int __init drbd_init(void)
{
- int i,err;
+ int err;
#if 0
#warning "DEBUGGING"
@@ -2422,6 +2461,10 @@
#endif
}
+ if( (err = drbd_nl_init()) ) {
+ return err;
+ }
+
err = register_blkdev(MAJOR_NR, DEVICE_NAME);
if (err) {
printk(KERN_ERR DEVICE_NAME
@@ -2429,6 +2472,7 @@
MAJOR_NR);
return err;
}
+
register_reboot_notifier(&drbd_notifier);
/*
@@ -2439,76 +2483,13 @@
init_waitqueue_head(&drbd_pp_wait);
drbd_proc = NULL; // play safe for drbd_cleanup
- drbd_conf = kmalloc(sizeof(drbd_dev)*minor_count,GFP_KERNEL);
- if (likely(drbd_conf!=NULL))
- memset(drbd_conf,0,sizeof(drbd_dev)*minor_count);
- else goto Enomem;
+ minor_table = kmalloc(sizeof(drbd_dev *)*minor_count,GFP_KERNEL);
+ if(!minor_table) goto Enomem;
+ memset(minor_table,0,sizeof(drbd_dev *)*minor_count);
- for (i = 0; i < minor_count; i++) {
- drbd_dev *mdev = drbd_conf + i;
- struct gendisk *disk;
- request_queue_t *q;
-
- q = blk_alloc_queue(GFP_KERNEL);
- if (!q) goto Enomem;
- mdev->rq_queue = q;
- q->queuedata = mdev;
- q->max_segment_size = DRBD_MAX_SEGMENT_SIZE;
-
- disk = alloc_disk(1);
- if (!disk) goto Enomem;
- mdev->vdisk = disk;
-
- set_disk_ro( disk, TRUE );
-
- disk->queue = q;
- disk->major = MAJOR_NR;
- disk->first_minor = i;
- disk->fops = &drbd_ops;
- sprintf(disk->disk_name, DEVICE_NAME "%d", i);
- disk->private_data = mdev;
- add_disk(disk);
-
- mdev->this_bdev = bdget(MKDEV(MAJOR_NR,i));
- // we have no partitions. we contain only ourselves.
- mdev->this_bdev->bd_contains = mdev->this_bdev;
- if (bd_claim(mdev->this_bdev,drbd_sec_holder)) {
- // Initial we are Secondary -> should claim myself.
- WARN("Could not bd_claim() myself.");
- } else if (disable_bd_claim) {
- bd_release(mdev->this_bdev);
- }
-
- blk_queue_make_request(q, drbd_make_request_26);
- blk_queue_merge_bvec(q, drbd_merge_bvec);
- q->queue_lock = &mdev->req_lock; // needed since we use
- // plugging on a queue, that actually has no requests!
- q->unplug_fn = drbd_unplug_fn;
- }
-
if ((err = drbd_create_mempools()))
goto Enomem;
- for (i = 0; i < minor_count; i++) {
- drbd_dev *mdev = &drbd_conf[i];
- struct page *page = alloc_page(GFP_KERNEL);
-
- drbd_init_set_defaults(mdev);
-
- if(!page) goto Enomem;
- mdev->md_io_page = page;
-
- if (drbd_bm_init(mdev)) goto Enomem;
- // no need to lock access, we are still initializing the module.
- init_MUTEX(&mdev->device_mutex);
- if (!tl_init(mdev)) goto Enomem;
-
- mdev->app_reads_hash=kmalloc(APP_R_HSIZE*sizeof(void*),
- GFP_KERNEL);
- if (!mdev->app_reads_hash) goto Enomem;
- memset(mdev->app_reads_hash,0,APP_R_HSIZE*sizeof(void*));
- }
-
#if CONFIG_PROC_FS
/*
* register with procfs
@@ -2526,27 +2507,6 @@
# error "Currently drbd depends on the proc file system (CONFIG_PROC_FS)"
#endif
-#ifndef HAVE_COMPAT_IOCTL_MEMBER
-#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64)
- // tell the kernel that we think our ioctls are 64bit clean
- lock_kernel();
- register_ioctl32_conversion(DRBD_IOCTL_GET_VERSION,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_SET_STATE,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_SET_DISK_CONFIG,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_SET_NET_CONFIG,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_NET,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_GET_CONFIG,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_INVALIDATE,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_INVALIDATE_REM,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_SET_SYNC_CONFIG,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_SET_DISK_SIZE,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_WAIT_CONNECT,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_WAIT_SYNC,NULL);
- register_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_DISK,NULL);
- unlock_kernel();
-#endif
-#endif
-
printk(KERN_INFO DEVICE_NAME ": initialised. "
"Version: " REL_VERSION " (api:%d/proto:%d)\n",
API_VERSION,PRO_VERSION);
Added: trunk/drbd/drbd_nl.c
===================================================================
--- trunk/drbd/drbd_nl.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_nl.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -0,0 +1,1608 @@
+/*
+-*- linux-c -*-
+ drbd_nl.c
+ Kernel module for 2.4.x/2.6.x Kernels
+
+ This file is part of drbd by Philipp Reisner.
+
+ Copyright (C) 1999-2006, Philipp Reisner <philipp.reisner at linbit.com>.
+ Copyright (C) 2002-2006, Lars Ellenberg <lars.ellenberg at linbit.com>.
+ Copyright (C) 2001-2006, LINBIT Information Technologies GmbH.
+
+ drbd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ drbd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with drbd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/in.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/connector.h>
+#include <linux/drbd.h>
+#include <linux/blkpg.h>
+
+#include <drbd_int.h>
+#include <linux/drbd_tag_magic.h>
+#include <linux/drbd_limits.h>
+
+/* see get_sb_bdev and bd_claim */
+char *drbd_sec_holder = "Secondary DRBD cannot be bd_claimed ;)";
+char *drbd_m_holder = "Hands off! this is DRBD's meta data device.";
+
+
+// Generate the tag_list to struct functions
+#define PACKET(name, fields) \
+int name ## _from_tags (drbd_dev *mdev, unsigned short* tags, struct name * arg) \
+{ \
+ int tag; \
+ int dlen; \
+ \
+ memset(arg,0,sizeof(struct name)); \
+ while( (tag = *tags++) != TT_END ) { \
+ dlen = *tags++; \
+ switch( tag_number(tag) ) { \
+ fields \
+ default: \
+ if( tag & T_MANDATORY ) { \
+ ERR("Unknown tag: %d\n",tag_number(tag)); \
+ return 0; \
+ } \
+ } \
+ tags = (unsigned short*)((char*)tags + dlen); \
+ } \
+ return 1; \
+}
+#define INTEGER(pn,pr,member) \
+ case pn: /* D_ASSERT( tag_type(tag) == TT_INTEGER ); */ \
+ arg->member = *(int*)(tags); \
+ break;
+#define INT64(pn,pr,member) \
+ case pn: /* D_ASSERT( tag_type(tag) == TT_INT64 ); */ \
+ arg->member = *(u64*)(tags); \
+ break;
+#define BIT(pn,pr,member) \
+ case pn: /* D_ASSERT( tag_type(tag) == TT_BIT ); */ \
+ arg->member = *(char*)(tags) ? 1 : 0; \
+ break;
+#define STRING(pn,pr,member,len) \
+ case pn: /* D_ASSERT( tag_type(tag) == TT_STRING ); */ \
+ arg->member ## _len = dlen; \
+ memcpy(arg->member,tags,dlen); \
+ break;
+#include "linux/drbd_nl.h"
+
+// Generate the struct to tag_list functions
+#define PACKET(name, fields) \
+unsigned short* \
+name ## _to_tags (drbd_dev *mdev, struct name * arg, unsigned short* tags) \
+{ \
+ fields \
+ return tags; \
+}
+
+#define INTEGER(pn,pr,member) \
+ *tags++ = pn | pr | TT_INTEGER; \
+ *tags++ = sizeof(int); \
+ *(int*)tags = arg->member; \
+ tags = (unsigned short*)((char*)tags+sizeof(int));
+#define INT64(pn,pr,member) \
+ *tags++ = pn | pr | TT_INT64; \
+ *tags++ = sizeof(u64); \
+ *(u64*)tags = arg->member; \
+ tags = (unsigned short*)((char*)tags+sizeof(u64));
+#define BIT(pn,pr,member) \
+ *tags++ = pn | pr | TT_BIT; \
+ *tags++ = sizeof(char); \
+ *(char*)tags = arg->member; \
+ tags = (unsigned short*)((char*)tags+sizeof(char));
+#define STRING(pn,pr,member,len) \
+ *tags++ = pn | pr | TT_STRING; \
+ *tags++ = arg->member ## _len; \
+ memcpy(tags,arg->member, arg->member ## _len); \
+ tags = (unsigned short*)((char*)tags + arg->member ## _len);
+#include "linux/drbd_nl.h"
+
+
+extern void drbd_init_set_defaults(drbd_dev *mdev);
+void drbd_nl_send_reply(struct cn_msg *, int);
+
+
+STATIC void drbd_nl_create (void *data)
+{
+ static int next_minor=0;
+ int minor,ok;
+ drbd_dev *mdev = NULL;
+
+ minor = next_minor;
+
+ mdev = drbd_new_device(minor);
+ if(!mdev) goto out;
+
+ spin_lock_irq(&drbd_pp_lock); // just to protect this from itself
+ if ( (ok = next_minor < minor_count && minor == next_minor) ) {
+ minor_table[minor] = mdev;
+ wmb();
+ next_minor++;
+ }
+ spin_unlock_irq(&drbd_pp_lock);
+
+ if(!ok) {
+ out:
+ if(mdev) {
+ if(mdev->app_reads_hash) kfree(mdev->app_reads_hash);
+ if(mdev->md_io_page) __free_page(mdev->md_io_page);
+ kfree(mdev);
+ }
+ }
+}
+
+int drbd_khelper(drbd_dev *mdev, char* cmd)
+{
+ char mb[12];
+ char *argv[] = {"/sbin/drbdadm", cmd, mb, NULL };
+ static char *envp[] = { "HOME=/",
+ "TERM=linux",
+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+ NULL };
+
+ snprintf(mb,12,"minor-%d",mdev_to_minor(mdev));
+ return call_usermodehelper("/sbin/drbdadm",argv,envp,1);
+}
+
+drbd_disks_t drbd_try_outdate_peer(drbd_dev *mdev)
+{
+ int r;
+ drbd_disks_t nps;
+ enum fencing_policy fp;
+
+ D_ASSERT(mdev->state.pdsk == DUnknown);
+
+ fp = DontCare;
+ if(inc_local(mdev)) {
+ fp = mdev->bc->dc.fencing;
+ dec_local(mdev);
+ }
+
+ D_ASSERT( fp > DontCare );
+
+ if( fp == Stonith ) drbd_request_state(mdev,NS(susp,1));
+
+ r=drbd_khelper(mdev,"outdate-peer");
+
+ switch( (r>>8) & 0xff ) {
+ case 3: /* peer is inconsistent */
+ nps = Inconsistent;
+ break;
+ case 4: /* peer is outdated */
+ nps = Outdated;
+ break;
+ case 5: /* peer was down, we will(have) create(d) a new UUID anyways... */
+ /* If we would be more strict, we would return DUnknown here. */
+ nps = Outdated;
+ break;
+ case 6: /* Peer is primary, voluntarily outdate myself */
+ WARN("Peer is primary, outdating myself.\n");
+ nps = DUnknown;
+ drbd_request_state(mdev,NS(disk,Outdated));
+ break;
+ case 7:
+ if( fp != Stonith ) {
+ ERR("outdate-peer() = 7 && fencing != Stonith !!!\n");
+ }
+ nps = Outdated;
+ break;
+ default:
+ /* The script is broken ... */
+ nps = DUnknown;
+ drbd_request_state(mdev,NS(disk,Outdated));
+ ERR("outdate-peer helper broken, returned %d \n",(r>>8)&0xff);
+ return nps;
+ }
+
+ INFO("outdate-peer helper returned %d \n",(r>>8)&0xff);
+ return nps;
+}
+
+
+int drbd_set_role(drbd_dev *mdev, drbd_role_t new_role, int force)
+{
+ int r=0,forced = 0, try=0;
+ drbd_state_t mask, val;
+ drbd_disks_t nps;
+
+ ERR_IF (mdev->this_bdev->bd_contains == 0) {
+ // FIXME this masks a bug somewhere else!
+ mdev->this_bdev->bd_contains = mdev->this_bdev;
+ }
+
+ if ( new_role & Secondary ) {
+ /* If I got here, I am Primary. I claim me for myself. If that
+ * does not succeed, someone other has claimed me, so I cannot
+ * become Secondary. */
+ if (bd_claim(mdev->this_bdev,drbd_sec_holder))
+ return FailedToClaimMyself;
+ if (disable_bd_claim)
+ bd_release(mdev->this_bdev);
+ }
+
+ mask.i = 0; mask.role = role_mask;
+ val.i = 0; val.role = new_role & role_mask;
+
+ while (try++ < 3) {
+ r = _drbd_request_state(mdev,mask,val,0);
+ if( r == SS_NoUpToDateDisk && force &&
+ ( mdev->state.disk == Inconsistent ||
+ mdev->state.disk == Outdated ) ) {
+ mask.disk = disk_mask;
+ val.disk = UpToDate;
+ forced = 1;
+ continue;
+ }
+ if ( r == SS_NothingToDo ) goto fail;
+ if ( r == SS_PrimaryNOP ) {
+ nps = drbd_try_outdate_peer(mdev);
+
+ if ( force && nps > Outdated ) {
+ WARN("Forced into split brain situation!\n");
+ nps = Outdated;
+ }
+
+ mask.pdsk = disk_mask;
+ val.pdsk = nps;
+
+ continue;
+ }
+
+ if ( r < SS_Success ) {
+ r = drbd_request_state(mdev,mask,val); // Be verbose.
+ if( r < SS_Success ) goto fail;
+ }
+ break;
+ }
+
+ if(forced) WARN("Forced to conisder local data as UpToDate!\n");
+
+ drbd_sync_me(mdev);
+
+ /* Wait until nothing is on the fly :) */
+ if ( wait_event_interruptible( mdev->cstate_wait,
+ atomic_read(&mdev->ap_pending_cnt) == 0 ) ) {
+ r = GotSignal;
+ goto fail;
+ }
+
+ /* FIXME RACE here: if our direct user is not using bd_claim (i.e.
+ * not a filesystem) since cstate might still be >= Connected, new
+ * ap requests may come in and increase ap_pending_cnt again!
+ * but that means someone is misusing DRBD...
+ * */
+
+ if (new_role & Secondary) {
+ set_disk_ro(mdev->vdisk, TRUE );
+ } else {
+ if(inc_net(mdev)) {
+ mdev->net_conf->want_lose = 0;
+ dec_net(mdev);
+ }
+ set_disk_ro(mdev->vdisk, FALSE );
+ D_ASSERT(mdev->this_bdev->bd_holder == drbd_sec_holder);
+ bd_release(mdev->this_bdev);
+ mdev->this_bdev->bd_disk = mdev->vdisk;
+
+ if ( ( ( mdev->state.conn < Connected ||
+ mdev->state.pdsk <= Attaching ) &&
+ mdev->bc->md.uuid[Bitmap] == 0) || forced ) {
+ drbd_uuid_new_current(mdev);
+ }
+ }
+
+ if(mdev->state.disk > Diskless && (new_role & Secondary)) {
+ drbd_al_to_on_disk_bm(mdev);
+ }
+
+ if (mdev->state.conn >= WFReportParams) {
+ /* if this was forced, we should consider sync */
+ if(forced) drbd_send_uuids(mdev);
+ drbd_send_state(mdev);
+ }
+
+ drbd_md_sync(mdev);
+
+ return r;
+
+ fail:
+ if ( new_role & Secondary ) {
+ D_ASSERT(mdev->this_bdev->bd_holder == drbd_sec_holder);
+ bd_release(mdev->this_bdev);
+ }
+
+ return r;
+}
+
+STATIC drbd_dev *ensure_mdev(struct drbd_nl_cfg_req *nlp)
+{
+ drbd_dev *mdev;
+
+ mdev = minor_to_mdev(nlp->drbd_minor);
+
+ if(!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) {
+ mdev = drbd_new_device(nlp->drbd_minor);
+
+ spin_lock_irq(&drbd_pp_lock);
+ if( minor_table[nlp->drbd_minor] == NULL) {
+ minor_table[nlp->drbd_minor] = mdev;
+ mdev = NULL;
+ }
+ spin_unlock_irq(&drbd_pp_lock);
+
+ if(mdev) {
+ if(mdev->app_reads_hash) kfree(mdev->app_reads_hash);
+ if(mdev->md_io_page) __free_page(mdev->md_io_page);
+ kfree(mdev);
+ mdev = NULL;
+ }
+
+ mdev = minor_to_mdev(nlp->drbd_minor);
+ }
+
+ return mdev;
+}
+
+
+STATIC void drbd_nl_primary (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ struct primary primary_args;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ if(!primary_from_tags(mdev,nlp->tag_list,&primary_args)) {
+ retcode=UnknownMandatoryTag;
+ goto fail;
+ }
+
+ retcode = drbd_set_role(mdev, Primary, primary_args.overwrite_peer);
+
+ fail:
+ drbd_nl_send_reply(req, retcode );
+}
+
+STATIC void drbd_nl_secondary (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_set_role(mdev, Secondary, 0);
+
+ fail:
+ drbd_nl_send_reply(req, retcode );
+}
+
+/* initializes the md.*_offset members, so we are able to find
+ * the on disk meta data */
+STATIC void drbd_md_set_sector_offsets(drbd_dev *mdev,
+ struct drbd_backing_dev *bdev)
+{
+ sector_t md_size_sect = 0;
+ switch(bdev->dc.meta_dev_idx) {
+ default:
+ case DRBD_MD_INDEX_FLEX_EXT:
+ /* just occupy the full device; unit: sectors */
+ bdev->md.md_size_sect = drbd_get_capacity(bdev->md_bdev);
+ bdev->md.md_offset = 0;
+ bdev->md.al_offset = MD_AL_OFFSET;
+ bdev->md.bm_offset = MD_BM_OFFSET;
+ break;
+ case DRBD_MD_INDEX_INTERNAL:
+ case DRBD_MD_INDEX_FLEX_INT:
+ bdev->md.md_offset = drbd_md_ss__(mdev,bdev);
+ /* al size is still fixed */
+ bdev->md.al_offset = -MD_AL_MAX_SIZE;
+ //LGE FIXME max size check missing.
+ /* we need (slightly less than) ~ this much bitmap sectors: */
+ md_size_sect = drbd_get_capacity(bdev->backing_bdev);
+ md_size_sect = ALIGN(md_size_sect,BM_SECT_PER_EXT);
+ md_size_sect = BM_SECT_TO_EXT(md_size_sect);
+ md_size_sect = ALIGN(md_size_sect,8);
+
+ /* plus the "drbd meta data super block",
+ * and the activity log; */
+ md_size_sect += MD_BM_OFFSET;
+
+ bdev->md.md_size_sect = md_size_sect;
+ /* bitmap offset is adjusted by 'super' block size */
+ bdev->md.bm_offset = -md_size_sect + MD_AL_OFFSET;
+ break;
+ }
+}
+
+char* ppsize(char* buf, size_t size)
+{
+ // Needs 9 bytes at max.
+ static char units[] = { 'K','M','G','T','P','E' };
+ int base = 0;
+ while (size >= 10000 ) {
+ size = size >> 10;
+ base++;
+ }
+ sprintf(buf,"%ld %cB",(long)size,units[base]);
+
+ return buf;
+}
+
+/* You should call drbd_md_sync() after calling this.
+ */
+int drbd_determin_dev_size(struct Drbd_Conf* mdev)
+{
+ sector_t prev_first_sect, prev_size; // previous meta location
+ sector_t la_size;
+ sector_t size;
+ char ppb[10];
+
+ int md_moved, la_size_changed;
+ int rv=0;
+
+ wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
+
+ prev_first_sect = drbd_md_first_sector(mdev->bc);
+ prev_size = mdev->bc->md.md_size_sect;
+ la_size = mdev->bc->md.la_size_sect;
+
+ // TODO: should only be some assert here, not (re)init...
+ drbd_md_set_sector_offsets(mdev,mdev->bc);
+
+ size = drbd_new_dev_size(mdev,mdev->bc);
+
+ if( drbd_get_capacity(mdev->this_bdev) != size ) {
+ int err;
+ err = drbd_bm_resize(mdev,size);
+ if (unlikely(err)) {
+ /* currently there is only one error: ENOMEM! */
+ size = drbd_bm_capacity(mdev)>>1;
+ if (size == 0) {
+ ERR("OUT OF MEMORY! Could not allocate bitmap! Set device size => 0\n");
+ } else {
+ /* FIXME this is problematic,
+ * if we in fact are smaller now! */
+ ERR("BM resizing failed. "
+ "Leaving size unchanged at size = %lu KB\n",
+ (unsigned long)size);
+ }
+ rv = err;
+ }
+ // racy, see comments above.
+ drbd_set_my_capacity(mdev,size);
+ mdev->bc->md.la_size_sect = size;
+ INFO("size = %s (%lu KB)\n",ppsize(ppb,size>>1),
+ (unsigned long)size>>1);
+ }
+ if (rv < 0) goto out;
+
+ la_size_changed = (la_size != mdev->bc->md.la_size_sect);
+
+ //LGE: flexible device size!! is this the right thing to test?
+ md_moved = prev_first_sect != drbd_md_first_sector(mdev->bc)
+ || prev_size != mdev->bc->md.md_size_sect;
+
+ if ( md_moved ) {
+ WARN("Moving meta-data.\n");
+ /* assert: (flexible) internal meta data */
+ }
+
+ if ( la_size_changed || md_moved ) {
+ if( inc_md_only(mdev,Attaching) ) {
+ drbd_al_shrink(mdev); // All extents inactive.
+ drbd_bm_write(mdev); // write bitmap
+ // Write mdev->la_size to on disk.
+ drbd_md_mark_dirty(mdev);
+ dec_local(mdev);
+ }
+ }
+ out:
+ lc_unlock(mdev->act_log);
+
+ return rv;
+}
+
+sector_t
+drbd_new_dev_size(struct Drbd_Conf* mdev, struct drbd_backing_dev *bdev)
+{
+ sector_t p_size = mdev->p_size; // partner's disk size.
+ sector_t la_size = bdev->md.la_size_sect; // last agreed size.
+ sector_t m_size; // my size
+ sector_t u_size = bdev->dc.disk_size; // size requested by user.
+ sector_t size=0;
+
+ m_size = drbd_get_max_capacity(bdev);
+
+ if(p_size && m_size) {
+ size=min_t(sector_t,p_size,m_size);
+ } else {
+ if(la_size) {
+ size=la_size;
+ if(m_size && m_size < size) size=m_size;
+ if(p_size && p_size < size) size=p_size;
+ } else {
+ if(m_size) size=m_size;
+ if(p_size) size=p_size;
+ }
+ }
+
+ if(size == 0) {
+ ERR("Both nodes diskless!\n");
+ }
+
+ if(u_size) {
+ if(u_size<<1 > size) {
+ ERR("Requested disk size is too big (%lu > %lu)\n",
+ (unsigned long)u_size, (unsigned long)size>>1);
+ } else {
+ size = u_size<<1;
+ }
+ }
+
+ return size;
+}
+
+/**
+ * drbd_check_al_size:
+ * checks that the al lru is of requested size, and if neccessary tries to
+ * allocate a new one. returns -EBUSY if current al lru is still used,
+ * -ENOMEM when allocation failed, and 0 on success. You should call
+ * drbd_md_sync() after you called this function.
+ */
+STATIC int drbd_check_al_size(drbd_dev *mdev)
+{
+ struct lru_cache *n,*t;
+ struct lc_element *e;
+ unsigned int in_use;
+ int i;
+
+ ERR_IF(mdev->sync_conf.al_extents < 7)
+ mdev->sync_conf.al_extents = 127;
+
+ if ( mdev->act_log &&
+ mdev->act_log->nr_elements == mdev->sync_conf.al_extents )
+ return 0;
+
+ in_use = 0;
+ t = mdev->act_log;
+ n = lc_alloc("act_log", mdev->sync_conf.al_extents,
+ sizeof(struct lc_element), mdev);
+
+ if (n==NULL) {
+ ERR("Cannot allocate act_log lru!\n");
+ return -ENOMEM;
+ }
+ spin_lock_irq(&mdev->al_lock);
+ if (t) {
+ for (i=0; i < t->nr_elements; i++) {
+ e = lc_entry(t,i);
+ if (e->refcnt)
+ ERR("refcnt(%d)==%d\n",
+ e->lc_number, e->refcnt);
+ in_use += e->refcnt;
+ }
+ }
+ if (!in_use) {
+ mdev->act_log = n;
+ }
+ spin_unlock_irq(&mdev->al_lock);
+ if (in_use) {
+ ERR("Activity log still in use!\n");
+ lc_free(n);
+ return -EBUSY;
+ } else {
+ if (t) lc_free(t);
+ }
+ drbd_md_mark_dirty(mdev); //we changed mdev->act_log->nr_elemens
+ return 0;
+}
+
+void drbd_setup_queue_param(drbd_dev *mdev, unsigned int max_seg_s)
+{
+ request_queue_t * const q = mdev->rq_queue;
+ request_queue_t * const b = mdev->bc->backing_bdev->bd_disk->queue;
+
+ unsigned int old_max_seg_s = q->max_segment_size;
+
+ if(b->merge_bvec_fn) {
+ max_seg_s = PAGE_SIZE;
+ }
+
+ q->max_sectors = max_seg_s >> 9;
+ q->max_phys_segments = max_seg_s >> PAGE_SHIFT;
+ q->max_hw_segments = max_seg_s >> PAGE_SHIFT;
+ q->max_segment_size = max_seg_s;
+ q->hardsect_size = 512;
+ q->seg_boundary_mask = PAGE_SIZE-1;
+ blk_queue_stack_limits(q, b);
+
+ if( old_max_seg_s != q->max_segment_size ) {
+ if(b->merge_bvec_fn) {
+ WARN("Backing device has merge_bvec_fn()!\n");
+ }
+ INFO("max_segment_size ( = BIO size ) = %u\n",
+ q->max_segment_size);
+ }
+
+ if( q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
+ INFO("Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
+ q->backing_dev_info.ra_pages,
+ b->backing_dev_info.ra_pages);
+ q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
+ }
+}
+
+STATIC void drbd_nl_disk_conf (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ enum ret_codes retcode;
+ struct drbd_backing_dev* nbc=NULL; // new_backing_conf
+ struct inode *inode, *inode2;
+ struct lru_cache* resync_lru = NULL;
+ drbd_state_t ns,os;
+ drbd_dev *mdev;
+ int rv;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ /* if you want to reconfigure, please tear down first */
+ if (mdev->state.disk > Diskless) {
+ retcode=HaveDiskConfig;
+ goto fail;
+ }
+
+ nbc = kmalloc(sizeof(struct drbd_backing_dev),GFP_KERNEL);
+ if(!nbc) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+
+ if(inc_local(mdev)) {
+ memcpy(&nbc->dc,&mdev->bc->dc,sizeof(struct disk_conf));
+ dec_local(mdev);
+ } else memset(&nbc->dc,0,sizeof(struct disk_conf));
+
+ if(nlp->flags & DRBD_NL_SET_DEFAULTS) {
+ nbc->dc.disk_size = DRBD_DISK_SIZE_SECT_DEF;
+ nbc->dc.on_io_error = DRBD_ON_IO_ERROR_DEF;
+ nbc->dc.fencing = DRBD_FENCING_DEF;
+ }
+
+ if(!disk_conf_from_tags(mdev,nlp->tag_list,&nbc->dc)) {
+ retcode=UnknownMandatoryTag;
+ goto fail;
+ }
+
+ nbc->lo_file = NULL;
+ nbc->md_file = NULL;
+
+ if ( nbc->dc.meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) {
+ retcode=LDMDInvalid;
+ goto fail;
+ }
+
+ nbc->lo_file = filp_open(nbc->dc.backing_dev,O_RDWR,0);
+ if (!nbc->lo_file) {
+ retcode=LDNameInvalid;
+ goto fail;
+ }
+
+ inode = nbc->lo_file->f_dentry->d_inode;
+
+ if (!S_ISBLK(inode->i_mode)) {
+ retcode=LDNoBlockDev;
+ goto fail;
+ }
+
+ nbc->md_file = filp_open(nbc->dc.meta_dev,O_RDWR,0);
+
+ if (!nbc->md_file) {
+ retcode=MDNameInvalid;
+ goto fail;
+ }
+
+ inode2 = nbc->md_file->f_dentry->d_inode;
+
+ if (!S_ISBLK(inode2->i_mode)) {
+ retcode=MDNoBlockDev;
+ goto fail;
+ }
+
+ nbc->backing_bdev = inode->i_bdev;
+ if (bd_claim(nbc->backing_bdev, mdev)) {
+ retcode=LDMounted;
+ goto fail;
+ }
+
+ resync_lru = lc_alloc("resync",7, sizeof(struct bm_extent),mdev);
+ if(!resync_lru) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+
+ nbc->md_bdev = inode2->i_bdev;
+ if (bd_claim(nbc->md_bdev,
+ (nbc->dc.meta_dev_idx==DRBD_MD_INDEX_INTERNAL ||
+ nbc->dc.meta_dev_idx==DRBD_MD_INDEX_FLEX_INT) ?
+ (void *)mdev : (void*) drbd_m_holder )) {
+ retcode=MDMounted;
+ goto release_bdev_fail;
+ }
+
+ if ( (nbc->backing_bdev==nbc->md_bdev) !=
+ (nbc->dc.meta_dev_idx==DRBD_MD_INDEX_INTERNAL ||
+ nbc->dc.meta_dev_idx==DRBD_MD_INDEX_FLEX_INT) ) {
+ retcode=LDMDInvalid;
+ goto release_bdev2_fail;
+ }
+
+ if ((drbd_get_capacity(nbc->backing_bdev)>>1) < nbc->dc.disk_size) {
+ retcode = LDDeviceTooSmall;
+ goto release_bdev2_fail;
+ }
+
+#warning checks below no longer valid
+// --- rewrite
+#if 0
+ if (drbd_get_capacity(nbc->backing_bdev) >= (sector_t)DRBD_MAX_SECTORS) {
+ retcode = LDDeviceTooLarge;
+ goto release_bdev2_fail;
+ }
+
+ if ( nbc->dc.meta_dev_idx == -1 ) i = 1;
+ else i = nbc->dc.meta_dev_idx+1;
+
+ /* for internal, we need to check agains <= (then we have a drbd with
+ * zero size, but meta data...) to be on the safe side, I require 32MB
+ * minimal data storage area for drbd with internal meta data (thats
+ * 160 total). if someone wants to use that small devices, she can use
+ * drbd 0.6 anyways...
+ *
+ * FIXME this is arbitrary and needs to be reconsidered as soon as we
+ * move to flexible size meta data.
+ */
+ if( drbd_get_capacity(nbc->md_bdev) < 2*MD_RESERVED_SIZE*i
+ + (nbc->dc.meta_dev_idx == -1) ? (1<<16) : 0 )
+ {
+ retcode = MDDeviceTooSmall;
+ goto release_bdev2_fail;
+ }
+#endif
+// -- up to here
+
+ // Make sure the new disk is big enough
+ if (drbd_get_capacity(nbc->backing_bdev) <
+ drbd_get_capacity(mdev->this_bdev) ) {
+ retcode = LDDeviceTooSmall;
+ goto release_bdev2_fail;
+ }
+
+ if((retcode = drbd_request_state(mdev,NS(disk,Attaching))) < SS_Success ) {
+ goto release_bdev2_fail;
+ }
+
+ drbd_md_set_sector_offsets(mdev,nbc);
+
+ retcode = drbd_md_read(mdev,nbc);
+ if ( retcode != NoError ) {
+ goto release_bdev3_fail;
+ }
+
+ // Since ware are diskless, fix the AL first...
+ if (drbd_check_al_size(mdev)) {
+ retcode = KMallocFailed;
+ goto release_bdev3_fail;
+ }
+
+ // Prevent shrinking of consistent devices !
+ if(drbd_md_test_flag(nbc,MDF_Consistent) &&
+ drbd_new_dev_size(mdev,nbc) < nbc->md.la_size_sect) {
+ retcode = LDDeviceTooSmall;
+ goto release_bdev3_fail;
+ }
+
+ if(!drbd_al_read_log(mdev,nbc)) {
+ retcode = MDIOError;
+ goto release_bdev3_fail;
+ }
+
+ // Point of no return reached.
+
+ if(drbd_md_test_flag(nbc,MDF_PrimaryInd)) {
+ set_bit(CRASHED_PRIMARY, &mdev->flags);
+ } else {
+ clear_bit(CRASHED_PRIMARY, &mdev->flags);
+ }
+
+ D_ASSERT(mdev->bc == NULL);
+ mdev->bc = nbc;
+ mdev->resync = resync_lru;
+
+ mdev->send_cnt = 0;
+ mdev->recv_cnt = 0;
+ mdev->read_cnt = 0;
+ mdev->writ_cnt = 0;
+
+ drbd_setup_queue_param(mdev, DRBD_MAX_SEGMENT_SIZE);
+ /*
+ * FIXME currently broken.
+ * drbd_set_recv_tcq(mdev,drbd_queue_order_type(mdev)==QUEUE_ORDERED_TAG);
+ */
+
+ /* If I am currently not Primary,
+ * but meta data primary indicator is set,
+ * I just now recover from a hard crash,
+ * and have been Primary before that crash.
+ *
+ * Now, if I had no connection before that crash
+ * (have been degraded Primary), chances are that
+ * I won't find my peer now either.
+ *
+ * In that case, and _only_ in that case,
+ * we use the degr-wfc-timeout instead of the default,
+ * so we can automatically recover from a crash of a
+ * degraded but active "cluster" after a certain timeout.
+ */
+ clear_bit(USE_DEGR_WFC_T,&mdev->flags);
+ if ( mdev->state.role != Primary &&
+ drbd_md_test_flag(mdev->bc,MDF_PrimaryInd) &&
+ !drbd_md_test_flag(mdev->bc,MDF_ConnectedInd) ) {
+ set_bit(USE_DEGR_WFC_T,&mdev->flags);
+ }
+
+ drbd_bm_lock(mdev); // racy...
+ drbd_determin_dev_size(mdev);
+
+ if (drbd_md_test_flag(mdev->bc,MDF_FullSync)) {
+ INFO("Assuming that all blocks are out of sync (aka FullSync)\n");
+ drbd_bm_set_all(mdev);
+ drbd_bm_write(mdev);
+ drbd_md_clear_flag(mdev,MDF_FullSync);
+ } else {
+ /* FIXME this still does not propagate io errors! */
+ drbd_bm_read(mdev);
+ }
+
+ if(test_bit(CRASHED_PRIMARY, &mdev->flags)) {
+ drbd_al_apply_to_bm(mdev);
+ drbd_al_to_on_disk_bm(mdev);
+ }
+ /* else {
+ FIXME wipe out on disk al!
+ } */
+
+
+ if(mdev->state.conn == Connected) {
+ drbd_send_sizes(mdev); // to start sync...
+ drbd_send_uuids(mdev);
+ drbd_send_state(mdev);
+ } else {
+ spin_lock_irq(&mdev->req_lock);
+ os = mdev->state;
+ ns.i = os.i;
+ /* If MDF_Consistent is not set go into inconsistent state,
+ otherwise investige MDF_WasUpToDate...
+ If MDF_WasUpToDate is not set go into Outdated disk state,
+ otherwise into Consistent state.
+ */
+ if(drbd_md_test_flag(mdev->bc,MDF_Consistent)) {
+ if(drbd_md_test_flag(mdev->bc,MDF_WasUpToDate)) {
+ ns.disk = Consistent;
+ } else {
+ ns.disk = Outdated;
+ }
+ } else {
+ ns.disk = Inconsistent;
+ }
+
+ if(drbd_md_test_flag(mdev->bc,MDF_PeerOutDated)) {
+ ns.pdsk = Outdated;
+ }
+
+ if( ns.disk == Consistent &&
+ ( ns.pdsk == Outdated || nbc->dc.fencing == DontCare ) ) {
+ ns.disk = UpToDate;
+ }
+
+ /* All tests on MDF_PrimaryInd, MDF_ConnectedInd,
+ MDF_Consistent and MDF_WasUpToDate must happen before
+ this point, because drbd_request_state() modifies these
+ flags. */
+
+ rv = _drbd_set_state(mdev, ns, ChgStateVerbose);
+ ns = mdev->state;
+ spin_unlock_irq(&mdev->req_lock);
+ after_state_ch(mdev,os,ns,ChgStateVerbose);
+
+ if(rv < SS_Success ) {
+ drbd_bm_unlock(mdev);
+ goto release_bdev3_fail;
+ }
+ }
+
+ drbd_bm_unlock(mdev);
+ drbd_md_sync(mdev);
+
+ drbd_nl_send_reply(req, NoError);
+ return;
+
+ release_bdev3_fail:
+ drbd_force_state(mdev,NS(disk,Diskless));
+ drbd_md_sync(mdev);
+ release_bdev2_fail:
+ bd_release(nbc->md_bdev);
+ release_bdev_fail:
+ bd_release(nbc->backing_bdev);
+ fail:
+ if (nbc) {
+ if (nbc->lo_file) fput(nbc->lo_file);
+ if (nbc->md_file) fput(nbc->md_file);
+ kfree(nbc);
+ }
+ if (resync_lru) lc_free(resync_lru);
+
+ drbd_nl_send_reply(req, retcode );
+}
+
+STATIC void drbd_nl_detach (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_request_state(mdev,NS(disk,Diskless));
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_net_conf (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ int i,ns;
+ enum ret_codes retcode;
+ struct net_conf *new_conf = NULL;
+ struct crypto_tfm* tfm = NULL;
+ struct hlist_head *new_tl_hash = NULL;
+ struct hlist_head *new_ee_hash = NULL;
+ struct Drbd_Conf *odev;
+ drbd_dev *mdev;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ new_conf = kmalloc(sizeof(struct net_conf),GFP_KERNEL);
+ if(!new_conf) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+
+ if(inc_net(mdev)) {
+ memcpy(new_conf,mdev->net_conf,sizeof(struct net_conf));
+ dec_local(mdev);
+ } else memset(new_conf,0,sizeof(struct net_conf));
+
+ if(nlp->flags & DRBD_NL_SET_DEFAULTS) {
+ new_conf->timeout = DRBD_TIMEOUT_DEF;
+ new_conf->try_connect_int = DRBD_CONNECT_INT_DEF;
+ new_conf->ping_int = DRBD_PING_INT_DEF;
+ new_conf->max_epoch_size = DRBD_MAX_EPOCH_SIZE_DEF;
+ new_conf->max_buffers = DRBD_MAX_BUFFERS_DEF;
+ new_conf->unplug_watermark= DRBD_UNPLUG_WATERMARK_DEF;
+ new_conf->sndbuf_size = DRBD_SNDBUF_SIZE_DEF;
+ new_conf->ko_count = DRBD_KO_COUNT_DEF;
+ new_conf->after_sb_0p = DRBD_AFTER_SB_0P_DEF;
+ new_conf->after_sb_1p = DRBD_AFTER_SB_1P_DEF;
+ new_conf->after_sb_2p = DRBD_AFTER_SB_2P_DEF;
+ new_conf->want_lose = 0;
+ new_conf->two_primaries = 0;
+ }
+
+ if (!net_conf_from_tags(mdev,nlp->tag_list,new_conf)) {
+ retcode=UnknownMandatoryTag;
+ goto fail;
+ }
+
+ if( mdev->state.role == Primary && new_conf->want_lose ) {
+ retcode=DiscardNotAllowed;
+ goto fail;
+ }
+
+#define M_ADDR(A) (((struct sockaddr_in *)&A->my_addr)->sin_addr.s_addr)
+#define M_PORT(A) (((struct sockaddr_in *)&A->my_addr)->sin_port)
+#define O_ADDR(A) (((struct sockaddr_in *)&A->peer_addr)->sin_addr.s_addr)
+#define O_PORT(A) (((struct sockaddr_in *)&A->peer_addr)->sin_port)
+ for(i=0;i<minor_count;i++) {
+ odev = minor_to_mdev(i);
+ if(!odev) continue;
+ if( mdev != odev && odev->state.conn > StandAlone &&
+ M_ADDR(new_conf) == M_ADDR(odev->net_conf) &&
+ M_PORT(new_conf) == M_PORT(odev->net_conf) ) {
+ retcode=LAAlreadyInUse;
+ goto fail;
+ }
+ if( mdev != odev && odev->state.conn > StandAlone &&
+ O_ADDR(new_conf) == O_ADDR(odev->net_conf) &&
+ O_PORT(new_conf) == O_PORT(odev->net_conf) ) {
+ retcode=OAAlreadyInUse;
+ goto fail;
+ }
+ }
+#undef M_ADDR
+#undef M_PORT
+#undef O_ADDR
+#undef O_PORT
+
+ if( new_conf->cram_hmac_alg[0] != 0) {
+ tfm = crypto_alloc_tfm(new_conf->cram_hmac_alg, 0);
+ if (tfm == NULL) {
+ retcode=CRAMAlgNotAvail;
+ goto fail;
+ }
+
+ if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST) {
+ retcode=CRAMAlgNotDigest;
+ goto fail;
+ }
+ }
+
+
+ ns = new_conf->max_epoch_size/8;
+ if (mdev->tl_hash_s != ns) {
+ new_tl_hash=kmalloc(ns*sizeof(void*), GFP_KERNEL);
+ if(!new_tl_hash) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+ memset(new_tl_hash, 0, ns*sizeof(void*));
+ }
+
+ ns = new_conf->max_buffers/8;
+ if (new_conf->two_primaries && ( mdev->ee_hash_s != ns ) ) {
+ new_ee_hash=kmalloc(ns*sizeof(void*), GFP_KERNEL);
+ if(!new_ee_hash) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+ memset(new_ee_hash, 0, ns*sizeof(void*));
+ }
+
+ /* IMPROVE:
+ We should warn the user if the LL_DEV is
+ used already. E.g. some FS mounted on it.
+ */
+
+ ((char*)new_conf->shared_secret)[SHARED_SECRET_MAX-1]=0;
+
+#if 0
+FIXME LGE
+ /* for the connection loss logic in drbd_recv
+ * I _need_ the resulting timeo in jiffies to be
+ * non-zero and different
+ *
+ * XXX maybe rather store the value scaled to jiffies?
+ * Note: MAX_SCHEDULE_TIMEOUT/HZ*HZ != MAX_SCHEDULE_TIMEOUT
+ * and HZ > 10; which is unlikely to change...
+ * Thus, if interrupted by a signal,
+ * sock_{send,recv}msg returns -EINTR,
+ * if the timeout expires, -EAGAIN.
+ */
+ // unlikely: someone disabled the timeouts ...
+ // just put some huge values in there.
+ if (!new_conf->ping_int)
+ new_conf->ping_int = MAX_SCHEDULE_TIMEOUT/HZ;
+ if (!new_conf->timeout)
+ new_conf->timeout = MAX_SCHEDULE_TIMEOUT/HZ*10;
+ if (new_conf->ping_int*10 < new_conf->timeout)
+ new_conf->timeout = new_conf->ping_int*10/6;
+ if (new_conf->ping_int*10 == new_conf->timeout)
+ new_conf->ping_int = new_conf->ping_int+1;
+#endif
+
+ drbd_sync_me(mdev);
+ drbd_thread_stop(&mdev->receiver); // conn = StadAlone afterwards
+ drbd_free_sock(mdev);
+
+ /* As soon as mdev->state.conn < Unconnected nobody can increase
+ the net_cnt. Wait until the net_cnt is 0. */
+ if ( wait_event_interruptible( mdev->cstate_wait,
+ atomic_read(&mdev->net_cnt) == 0 ) ) {
+ retcode=GotSignal;
+ goto fail;
+ }
+
+ /* Now we may touch net_conf */
+ if (mdev->net_conf) kfree(mdev->net_conf);
+ mdev->net_conf = new_conf;
+
+ mdev->send_cnt = 0;
+ mdev->recv_cnt = 0;
+
+ if(new_tl_hash) {
+ if (mdev->tl_hash) kfree(mdev->tl_hash);
+ mdev->tl_hash_s = mdev->net_conf->max_epoch_size/8;
+ mdev->tl_hash = new_tl_hash;
+ }
+
+ if(new_ee_hash) {
+ if (mdev->ee_hash) kfree(mdev->ee_hash);
+ mdev->ee_hash_s = mdev->net_conf->max_buffers/8;
+ mdev->ee_hash = new_ee_hash;
+ }
+
+ if ( mdev->cram_hmac_tfm ) {
+ crypto_free_tfm(mdev->cram_hmac_tfm);
+ }
+ mdev->cram_hmac_tfm = tfm;
+
+ retcode = drbd_request_state(mdev,NS(conn,Unconnected));
+
+ drbd_nl_send_reply(req, retcode);
+ return ;
+
+ fail:
+ if (tfm) crypto_free_tfm(tfm);
+ if (new_tl_hash) kfree(new_tl_hash);
+ if (new_ee_hash) kfree(new_ee_hash);
+ if (new_conf) kfree(new_conf);
+
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_disconnect (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+
+ retcode = _drbd_request_state(mdev,NS(conn,StandAlone),0); // silently.
+
+ if ( retcode == SS_NothingToDo ) goto done;
+ if ( retcode == SS_PrimaryNOP ) {
+ drbd_send_short_cmd(mdev, OutdateRequest);
+ wait_event(mdev->cstate_wait,
+ mdev->state.pdsk <= Outdated ||
+ mdev->state.conn < TearDown );
+ if( mdev->state.conn < TearDown ) goto done;
+
+ retcode = drbd_request_state(mdev,NS(conn,StandAlone));
+ }
+
+ if( retcode < SS_Success ) goto fail;
+
+ if ( mdev->cram_hmac_tfm ) {
+ crypto_free_tfm(mdev->cram_hmac_tfm);
+ mdev->cram_hmac_tfm = NULL;
+ }
+
+ done:
+ retcode = NoError;
+ fail:
+ drbd_md_sync(mdev);
+ drbd_nl_send_reply(req, retcode);
+ return ;
+}
+
+STATIC void drbd_nl_resize (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ struct resize rs;
+ drbd_dev *mdev;
+ int retcode=NoError;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ if (!resize_from_tags(mdev,nlp->tag_list,&rs)) {
+ retcode=UnknownMandatoryTag;
+ goto fail;
+ }
+
+ if (mdev->state.conn > Connected) {
+ retcode = NoResizeDuringResync;
+ goto fail;
+ }
+
+ if ( mdev->state.role == Secondary &&
+ mdev->state.peer == Secondary) {
+ retcode = APrimaryNodeNeeded;
+ goto fail;
+ }
+ mdev->bc->dc.disk_size = (sector_t)rs.resize_size;
+ drbd_bm_lock(mdev);
+ drbd_determin_dev_size(mdev);
+ drbd_md_sync(mdev);
+ drbd_bm_unlock(mdev);
+ if (mdev->state.conn == Connected) {
+ drbd_send_uuids(mdev); // to start sync...
+ drbd_send_sizes(mdev);
+ }
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_syncer_conf (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode=NoError;
+ struct syncer_conf sc;
+ drbd_dev *odev;
+ int err;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ memcpy(&sc,&mdev->sync_conf,sizeof(struct syncer_conf));
+
+ if(nlp->flags & DRBD_NL_SET_DEFAULTS) {
+ sc.rate = DRBD_RATE_DEF;
+ sc.after = DRBD_AFTER_DEF;
+ sc.al_extents = DRBD_AL_EXTENTS_DEF;
+ }
+
+ if (!syncer_conf_from_tags(mdev,nlp->tag_list,&sc)) {
+ retcode=UnknownMandatoryTag;
+ goto fail;
+ }
+
+ if( sc.after != -1) {
+ if( sc.after < -1 || minor_to_mdev(sc.after) == NULL ) {
+ retcode=SyncAfterInvalid;
+ goto fail;
+ }
+ odev = minor_to_mdev(sc.after); // check against loops in
+ while(1) {
+ if( odev == mdev ) {
+ retcode=SyncAfterCycle;
+ goto fail;
+ }
+ if( odev->sync_conf.after == -1 ) break; // no cycles.
+ odev = minor_to_mdev(odev->sync_conf.after);
+ }
+ }
+
+ ERR_IF (sc.rate < 1) sc.rate = 1;
+ ERR_IF (sc.al_extents < 7) sc.al_extents = 127; // arbitrary minimum
+#define AL_MAX ((MD_AL_MAX_SIZE-1) * AL_EXTENTS_PT)
+ if(sc.al_extents > AL_MAX) {
+ ERR("sc.al_extents > %d\n",AL_MAX);
+ sc.al_extents = AL_MAX;
+ }
+#undef AL_MAX
+
+ mdev->sync_conf.rate = sc.rate;
+ mdev->sync_conf.al_extents = sc.al_extents;
+
+ err = drbd_check_al_size(mdev);
+ drbd_md_sync(mdev);
+ if (err) {
+ retcode = KMallocFailed;
+ goto fail;
+ }
+
+ if (mdev->state.conn >= Connected)
+ drbd_send_sync_param(mdev,&sc);
+
+ drbd_alter_sa(mdev, sc.after);
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+ return;
+}
+
+STATIC void drbd_nl_invalidate (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_request_state(mdev,NS2(conn,StartingSyncT,
+ disk,Inconsistent));
+ fail:
+ drbd_nl_send_reply(req, retcode);
+ return;
+}
+
+STATIC void drbd_nl_invalidate_peer (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_request_state(mdev,NS2(conn,StartingSyncS,
+ pdsk,Inconsistent));
+ fail:
+ drbd_nl_send_reply(req, retcode);
+ return;
+}
+
+STATIC void drbd_nl_pause_sync (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode=NoError;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ if(!drbd_resync_pause(mdev, UserImposed)) retcode = PauseFlagAlreadySet;
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_resume_sync (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode=NoError;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ if(!drbd_resync_resume(mdev, UserImposed)) retcode = PauseFlagAlreadyClear;
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_suspend_io (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_request_state(mdev,NS(susp,1));
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_resume_io (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode=NoError;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ retcode = drbd_request_state(mdev,NS(susp,0));
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+STATIC void drbd_nl_outdate (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode;
+ drbd_state_t os,ns;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ spin_lock_irq(&mdev->req_lock);
+ os = mdev->state;
+ if( mdev->state.disk < Outdated ) {
+ retcode = -999;
+ } else {
+ retcode = _drbd_set_state(mdev,_NS(disk,Outdated),ChgStateVerbose);
+ }
+ ns = mdev->state;
+ spin_unlock_irq(&mdev->req_lock);
+ if (retcode==SS_Success) after_state_ch(mdev,os,ns, ChgStateVerbose);
+
+ if( retcode == -999 ) {
+ retcode = DiskLowerThanOutdated;
+ goto fail;
+ }
+
+ drbd_md_sync(mdev);
+
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+
+STATIC void drbd_nl_get_config (void *data)
+{
+ struct cn_msg *req = data;
+ struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req*)req->data;
+ drbd_dev *mdev;
+ int retcode=NoError,rr;
+ struct drbd_nl_cfg_reply* reply;
+ struct cn_msg *cn_reply;
+ unsigned short *tl;
+ int size = sizeof(struct cn_msg) + sizeof(struct drbd_nl_cfg_reply) +
+ disk_conf_tag_size + net_conf_tag_size + syncer_conf_tag_size + 2;
+
+ if( !(mdev = ensure_mdev(nlp)) ) {
+ retcode=MinorNotKnown;
+ goto fail;
+ }
+
+ if( !(cn_reply = kmalloc(size,GFP_KERNEL)) ) {
+ retcode=KMallocFailed;
+ goto fail;
+ }
+ reply = (struct drbd_nl_cfg_reply*) cn_reply->data;
+ tl = reply->tag_list;
+
+ if(inc_local(mdev)) {
+ tl = disk_conf_to_tags(mdev,&mdev->bc->dc,tl);
+ dec_local(mdev);
+ }
+
+ if(inc_net(mdev)) {
+ tl = net_conf_to_tags(mdev,mdev->net_conf,tl);
+ dec_net(mdev);
+ }
+ tl = syncer_conf_to_tags(mdev,&mdev->sync_conf,tl);
+
+ *tl++ = TT_END; /* Close the tag list */
+
+ cn_reply->id = req->id;
+ cn_reply->seq = req->seq;
+ cn_reply->ack = req->ack + 1;
+ cn_reply->len = (char*)tl - (char *)reply;
+ cn_reply->flags = 0;
+
+ reply->minor = nlp->drbd_minor;
+ reply->ret_code = retcode;
+
+ rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL);
+ if(rr) printk(KERN_INFO DEVICE_NAME " cn_netlink_send()=%d\n",rr);
+ return;
+ fail:
+ drbd_nl_send_reply(req, retcode);
+}
+
+// Generate the packet_number to callback table...
+typedef void (*cn_handler)(void*);
+
+static cn_handler cnd_table[] = {
+#define PACKET(name, fields) [ P_ ## name ] = & drbd_nl_ ## name,
+#define INTEGER(pn,pr,member)
+#define INT64(pn,pr,member)
+#define BIT(pn,pr,member)
+#define STRING(pn,pr,member,len)
+#include "linux/drbd_nl.h"
+};
+
+int __init drbd_nl_init()
+{
+ static struct cb_id cn_id_drbd = { CN_IDX_DRBD, 0 };
+ int i,err;
+
+ for(i=0;i<P_nl_after_last_packet;i++) {
+ cn_id_drbd.val = i;
+ err = cn_add_callback(&cn_id_drbd,"cn_drbd",cnd_table[i]);
+ if(err) {
+ printk(KERN_ERR DEVICE_NAME "cn_drbd failed to register\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+void drbd_nl_cleanup()
+{
+ static struct cb_id cn_id_drbd = { CN_IDX_DRBD, 0 };
+ int i;
+
+ for(i=0;i<P_nl_after_last_packet;i++) {
+ cn_id_drbd.val = i;
+ cn_del_callback(&cn_id_drbd);
+ }
+}
+
+void drbd_nl_send_reply( struct cn_msg *req,
+ int ret_code)
+{
+ char buffer[sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply)];
+ struct cn_msg *cn_reply = (struct cn_msg *) buffer;
+ struct drbd_nl_cfg_reply* reply = (struct drbd_nl_cfg_reply*)cn_reply->data;
+ int rr;
+
+ cn_reply->id = req->id;
+
+ cn_reply->seq = req->seq;
+ cn_reply->ack = req->ack + 1;
+ cn_reply->len = sizeof(struct drbd_nl_cfg_reply);
+ cn_reply->flags = 0;
+
+ reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor;
+ reply->ret_code = ret_code;
+
+ rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL);
+ if(rr) printk(KERN_INFO DEVICE_NAME " cn_netlink_send()=%d\n",rr);
+}
+
Modified: trunk/drbd/drbd_proc.c
===================================================================
--- trunk/drbd/drbd_proc.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_proc.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -172,8 +172,9 @@
STATIC int drbd_seq_show(struct seq_file *seq, void *v)
{
- int i;
+ int i,hole=0;
const char *sn;
+ drbd_dev *mdev;
seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d)\n%s\n",
API_VERSION,PRO_VERSION, drbd_buildtag());
@@ -192,10 +193,20 @@
*/
for (i = 0; i < minor_count; i++) {
- sn = conns_to_name(drbd_conf[i].state.conn);
+ mdev = minor_to_mdev(i);
+ if(!mdev) {
+ hole=1;
+ continue;
+ }
+ if( hole ) {
+ hole=0;
+ seq_printf( seq, "\n");
+ }
- if ( drbd_conf[i].state.conn == StandAlone &&
- drbd_conf[i].state.disk == Diskless) {
+ sn = conns_to_name(mdev->state.conn);
+
+ if ( mdev->state.conn == StandAlone &&
+ mdev->state.disk == Diskless) {
seq_printf( seq, "%2d: cs:Unconfigured\n", i);
} else {
seq_printf( seq,
@@ -203,40 +214,40 @@
" ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
"lo:%d pe:%d ua:%d ap:%d\n",
i, sn,
- roles_to_name(drbd_conf[i].state.role),
- roles_to_name(drbd_conf[i].state.peer),
- disks_to_name(drbd_conf[i].state.disk),
- disks_to_name(drbd_conf[i].state.pdsk),
- drbd_conf[i].state.susp ? 's' : 'r',
- drbd_conf[i].state.aftr_isp ? 'a' : '-',
- drbd_conf[i].state.peer_isp ? 'p' : '-',
- drbd_conf[i].state.user_isp ? 'u' : '-',
- drbd_conf[i].send_cnt/2,
- drbd_conf[i].recv_cnt/2,
- drbd_conf[i].writ_cnt/2,
- drbd_conf[i].read_cnt/2,
- drbd_conf[i].al_writ_cnt,
- drbd_conf[i].bm_writ_cnt,
- atomic_read(&drbd_conf[i].local_cnt),
- atomic_read(&drbd_conf[i].ap_pending_cnt) +
- atomic_read(&drbd_conf[i].rs_pending_cnt),
- atomic_read(&drbd_conf[i].unacked_cnt),
- atomic_read(&drbd_conf[i].ap_bio_cnt)
+ roles_to_name(mdev->state.role),
+ roles_to_name(mdev->state.peer),
+ disks_to_name(mdev->state.disk),
+ disks_to_name(mdev->state.pdsk),
+ mdev->state.susp ? 's' : 'r',
+ mdev->state.aftr_isp ? 'a' : '-',
+ mdev->state.peer_isp ? 'p' : '-',
+ mdev->state.user_isp ? 'u' : '-',
+ mdev->send_cnt/2,
+ mdev->recv_cnt/2,
+ mdev->writ_cnt/2,
+ mdev->read_cnt/2,
+ mdev->al_writ_cnt,
+ mdev->bm_writ_cnt,
+ atomic_read(&mdev->local_cnt),
+ atomic_read(&mdev->ap_pending_cnt) +
+ atomic_read(&mdev->rs_pending_cnt),
+ atomic_read(&mdev->unacked_cnt),
+ atomic_read(&mdev->ap_bio_cnt)
);
}
- if ( drbd_conf[i].state.conn == SyncSource ||
- drbd_conf[i].state.conn == SyncTarget ) {
- drbd_syncer_progress(drbd_conf+i,seq);
+ if ( mdev->state.conn == SyncSource ||
+ mdev->state.conn == SyncTarget ) {
+ drbd_syncer_progress(mdev,seq);
}
- if(drbd_conf[i].resync) {
- lc_printf_stats(seq,drbd_conf[i].resync);
+ if(mdev->resync) {
+ lc_printf_stats(seq,mdev->resync);
}
- if(drbd_conf[i].act_log) {
- lc_printf_stats(seq,drbd_conf[i].act_log);
+ if(mdev->act_log) {
+ lc_printf_stats(seq,mdev->act_log);
}
#if 0
- if(drbd_conf[i].resync) {
- lc_dump(drbd_conf[i].resync,seq,"rs_left",
+ if(mdev->resync) {
+ lc_dump(mdev->resync,seq,"rs_left",
resync_dump_detail);
}
#endif
Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_receiver.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -80,13 +80,13 @@
if( le->prev != la ) {
printk(KERN_ERR DEVICE_NAME
"%d: %s list fucked.\n",
- (int)(mdev-drbd_conf),t);
+ mdev_to_minor(mdev),t);
break;
}
if( forward++ > CHECK_LIST_LIMIT ) {
printk(KERN_ERR DEVICE_NAME
"%d: %s forward > 1000\n",
- (int)(mdev-drbd_conf),t);
+ mdev_to_minor(mdev),t);
break;
}
} while(le != list);
@@ -98,20 +98,20 @@
if( le->next != la ) {
printk(KERN_ERR DEVICE_NAME
"%d: %s list fucked.\n",
- (int)(mdev-drbd_conf),t);
+ mdev_to_minor(mdev),t);
break;
}
if( backward++ > CHECK_LIST_LIMIT ) {
printk(KERN_ERR DEVICE_NAME
"%d: %s backward > 1000\n",
- (int)(mdev-drbd_conf),t);
+ mdev_to_minor(mdev),t);
break;
}
} while(le != list);
if(forward != backward) {
printk(KERN_ERR DEVICE_NAME "%d: forward=%d, backward=%d\n",
- (int)(mdev-drbd_conf),forward,backward);
+ mdev_to_minor(mdev),forward,backward);
}
}
#endif
@@ -646,8 +646,8 @@
}
err = sock->ops->connect(sock,
- (struct sockaddr *)mdev->net_conf->other_addr,
- mdev->net_conf->other_addr_len, 0);
+ (struct sockaddr *)mdev->net_conf->peer_addr,
+ mdev->net_conf->peer_addr_len, 0);
if (err) {
sock_release(sock);
@@ -1590,7 +1590,7 @@
(((struct sockaddr_in *)mdev->net_conf->my_addr)
->sin_addr.s_addr);
ch_peer = (unsigned long)
- (((struct sockaddr_in *)mdev->net_conf->other_addr)
+ (((struct sockaddr_in *)mdev->net_conf->peer_addr)
->sin_addr.s_addr);
if ( ch_self < ch_peer ) rv = -1;
else if ( ch_self > ch_peer ) rv = 1;
@@ -1634,10 +1634,9 @@
case PanicPrimary:
hg = drbd_asb_recover_0p(mdev);
if( hg == -1 && mdev->state.role==Primary) {
- int sec = Secondary;
int got_mutex=!down_interruptible(&mdev->device_mutex);
- if (got_mutex) self = drbd_set_role(mdev,&sec);
- if (self || !got_mutex) {
+ if (got_mutex) self = drbd_set_role(mdev,Secondary,0);
+ if (self != SS_Success || !got_mutex) {
drbd_khelper(mdev,"pri-lost-after-sb");
drbd_panic("Panic by after-sb-1pri handler\n");
} else {
@@ -1672,10 +1671,9 @@
case PanicPrimary:
hg = drbd_asb_recover_0p(mdev);
if( hg == -1 ) {
- int sec = Secondary;
int got_mutex=!down_interruptible(&mdev->device_mutex);
- if (got_mutex) self = drbd_set_role(mdev,&sec);
- if (self || !got_mutex) {
+ if (got_mutex) self = drbd_set_role(mdev,Secondary,0);
+ if (self != SS_Success || !got_mutex) {
drbd_khelper(mdev,"pri-lost-after-sb");
drbd_panic("Panic by after-sb-2pri handler\n");
} else {
@@ -1986,20 +1984,20 @@
warn_if_differ_considerably(mdev, "lower level device sizes",
p_size, drbd_get_capacity(mdev->bc->backing_bdev));
warn_if_differ_considerably(mdev, "user requested size",
- p_usize, mdev->bc->u_size);
+ p_usize, mdev->bc->dc.disk_size);
if (mdev->state.conn == WFReportParams) {
/* this is first connect, or an otherwise expected
param exchange. choose the minimum */
- p_usize = min_not_zero(mdev->bc->u_size, p_usize);
+ p_usize = min_not_zero(mdev->bc->dc.disk_size, p_usize);
}
- my_usize = mdev->bc->u_size;
+ my_usize = mdev->bc->dc.disk_size;
- if( mdev->bc->u_size != p_usize ) {
- mdev->bc->u_size = p_usize;
+ if( mdev->bc->dc.disk_size != p_usize ) {
+ mdev->bc->dc.disk_size = p_usize;
INFO("Peer sets u_size to %lu KB\n",
- (unsigned long)mdev->bc->u_size);
+ (unsigned long)mdev->bc->dc.disk_size);
}
// Never shrink a device with usable data.
@@ -2010,7 +2008,7 @@
ERR("The peer's disk size is too small!\n");
drbd_force_state(mdev,NS(conn,StandAlone));
drbd_thread_stop_nowait(&mdev->receiver);
- mdev->bc->u_size = my_usize;
+ mdev->bc->dc.disk_size = my_usize;
return FALSE;
}
dec_local(mdev);
@@ -2463,7 +2461,7 @@
fp = DontCare;
if(inc_local(mdev)) {
- fp = mdev->bc->fencing;
+ fp = mdev->bc->dc.fencing;
dec_local(mdev);
}
@@ -2748,7 +2746,7 @@
int drbdd_init(struct Drbd_thread *thi)
{
drbd_dev *mdev = thi->mdev;
- int minor = (int)(mdev-drbd_conf);
+ int minor = mdev_to_minor(mdev);
int h;
sprintf(current->comm, "drbd%d_receiver", minor);
@@ -2991,7 +2989,7 @@
[StateChgReply]={sizeof(Drbd_RqS_Reply_Packet),got_RqSReply },
};
- sprintf(current->comm, "drbd%d_asender", (int)(mdev-drbd_conf));
+ sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
current->policy = SCHED_RR; /* Make this a realtime task! */
current->rt_priority = 2; /* more important than all other tasks */
Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_req.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -106,7 +106,7 @@
}
uptodate = req->rq_status & 0x0001;
- if( !uptodate && mdev->bc->on_io_error == Detach) {
+ if( !uptodate && mdev->bc->dc.on_io_error == Detach) {
drbd_set_out_of_sync(mdev,rsector, drbd_req_get_size(req));
// It should also be as out of sync on
// the other side! See w_io_error()
Deleted: trunk/drbd/drbd_sizeof_sanity_check.c
===================================================================
--- trunk/drbd/drbd_sizeof_sanity_check.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_sizeof_sanity_check.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,19 +0,0 @@
-#include <linux/drbd.h>
-#include <linux/kernel.h>
-
-#define COMPILETIME_ASSERT(x) \
- switch(0) { case 0:; case (x):; }
-#define SZO(type,size) \
-void __assert_sizeof_ ##type ## _eq_ ##size(void) { COMPILETIME_ASSERT(sizeof(struct type) == (size)); } \
-void __assert_sizeof_ ##type ## _modulo_8_eq_0(void) { COMPILETIME_ASSERT(sizeof(struct type) % 8 == 0); }
-
-SZO(disk_config, 32)
-SZO(net_config, 456)
-SZO(syncer_config, 16)
-SZO(ioctl_disk_config, 40)
-SZO(ioctl_net_config, 464)
-SZO(ioctl_syncer_config, 24)
-SZO(ioctl_wait, 16)
-SZO(ioctl_get_config, 576)
-SZO(ioctl_get_uuids, 48)
-
Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/drbd_worker.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -175,7 +175,7 @@
if (bio_rw(bio) == READA) goto pass_on;
if (error) {
drbd_chk_io_error(mdev,error); // handle panic and detach.
- if(mdev->bc->on_io_error == PassOn) goto pass_on;
+ if(mdev->bc->dc.on_io_error == PassOn) goto pass_on;
// ok, if we survived this, retry:
// FIXME sector ...
if (DRBD_ratelimit(5*HZ,5))
@@ -206,7 +206,7 @@
* a "we are diskless" param packet anyways, and the peer
* will then set the FullSync bit in the meta data ...
*/
- D_ASSERT(mdev->bc->on_io_error != PassOn);
+ D_ASSERT(mdev->bc->dc.on_io_error != PassOn);
drbd_req_free(req);
@@ -734,20 +734,24 @@
STATIC void drbd_global_lock(void)
{
+ drbd_dev *mdev;
int i;
local_irq_disable();
for (i=0; i < minor_count; i++) {
- spin_lock(&drbd_conf[i].req_lock);
+ if(!(mdev = minor_to_mdev(i))) continue;
+ spin_lock(&mdev->req_lock);
}
}
STATIC void drbd_global_unlock(void)
{
+ drbd_dev *mdev;
int i;
for (i=0; i < minor_count; i++) {
- spin_unlock(&drbd_conf[i].req_lock);
+ if(!(mdev = minor_to_mdev(i))) continue;
+ spin_unlock(&mdev->req_lock);
}
local_irq_enable();
}
@@ -841,7 +845,7 @@
while(1) {
if( odev->sync_conf.after == -1 ) return 1;
- odev = drbd_conf + odev->sync_conf.after;
+ odev = minor_to_mdev(odev->sync_conf.after);
if( odev->state.conn >= SyncSource &&
odev->state.conn <= PausedSyncT ) return 0;
}
@@ -859,7 +863,7 @@
int i, rv = 0;
for (i=0; i < minor_count; i++) {
- odev = drbd_conf + i;
+ if( !(odev = minor_to_mdev(i)) ) continue;
if (! _drbd_may_sync_now(odev)) {
rv |= _drbd_rs_pause(odev,AfterDependency);
}
@@ -880,7 +884,7 @@
int i, rv = 0;
for (i=0; i < minor_count; i++) {
- odev = drbd_conf + i;
+ if( !(odev = minor_to_mdev(i)) ) continue;
if ( odev->state.conn == PausedSyncS ||
odev->state.conn == PausedSyncT ) {
if (_drbd_may_sync_now(odev)) {
@@ -1020,7 +1024,7 @@
LIST_HEAD(work_list);
int intr,i;
- sprintf(current->comm, "drbd%d_worker", (int)(mdev-drbd_conf));
+ sprintf(current->comm, "drbd%d_worker", mdev_to_minor(mdev));
for (;;) {
intr = down_interruptible(&mdev->data.work.s);
Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/linux/drbd.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -27,42 +27,12 @@
#ifdef __KERNEL__
#include <linux/types.h>
-#include <linux/ioctl.h>
#else
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <sys/wait.h>
#include <limits.h>
#endif
-#ifdef __KERNEL__
-#define IN const
-#define OUT
-#define INOUT
-#else
-#define IN
-#define OUT const
-#define INOUT
-#endif
-
-/*
- - Never forget to place bigger members before the smaller ones,
- to avoid unaligned placement of members on 64 bit architectures.
- - Never forget to add explicit _pad members to make sizeof(struct)
- divisible by 8.
-*/
-
-#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
- 16 for IP, 16 for IPX,
- 24 for IPv6,
- about 80 for AX.25
- must be at least one bigger than
- the AF_UNIX size (see net/unix/af_unix.c
- :unix_mkname()).
- */
-#define CRYPTO_MAX_ALG_NAME 64
-#define SHARED_SECRET_MAX 64
-
enum io_error_handler {
PassOn,
Panic,
@@ -75,16 +45,6 @@
Stonith
};
-struct disk_config {
- IN __u64 disk_size;
- IN int lower_device;
- IN enum io_error_handler on_io_error;
- IN int meta_device;
- IN int meta_index;
- IN enum fencing_policy fencing;
- const int _pad;
-};
-
enum disconnect_handler {
Reconnect,
DropNetConf,
@@ -103,44 +63,15 @@
PanicPrimary
};
-struct net_config {
- IN char my_addr[MAX_SOCK_ADDR];
- IN char other_addr[MAX_SOCK_ADDR];
- IN char shared_secret[SHARED_SECRET_MAX];
- IN char cram_hmac_alg[CRYPTO_MAX_ALG_NAME];
- IN int my_addr_len;
- IN int other_addr_len;
- IN int timeout; // deci seconds
- IN int wire_protocol;
- IN int try_connect_int; /* seconds */
- IN int ping_int; /* seconds */
- IN int max_epoch_size;
- IN int max_buffers;
- IN int unplug_watermark;
- IN int sndbuf_size; /* socket send buffer size */
- IN int two_primaries;
- IN unsigned int ko_count;
- int want_lose;
- IN enum disconnect_handler on_disconnect;
- IN enum after_sb_handler after_sb_0p, after_sb_1p, after_sb_2p;
- const int _pad;
-};
-
-struct syncer_config {
- int rate; /* KB/sec */
- int after;
- int al_extents;
- const int _pad;
-};
-
/* KEEP the order, do not delete or insert!
* Or change the API_VERSION, too. */
enum ret_codes {
- NoError=0,
+ RetCodeBase=100,
+ NoError, // 101 ...
LAAlreadyInUse,
OAAlreadyInUse,
- LDFDInvalid,
- MDFDInvalid,
+ LDNameInvalid,
+ MDNameInvalid,
LDAlreadyInUse,
LDNoBlockDev,
MDNoBlockDev,
@@ -159,35 +90,22 @@
CRAMAlgNotDigest,
KMallocFailed,
DiscardNotAllowed,
+ HaveDiskConfig,
+ UnknownMandatoryTag,
+ MinorNotKnown,
StateNotAllowed,
GotSignal, // EINTR
+ NoResizeDuringResync,
+ APrimaryNodeNeeded,
+ SyncAfterInvalid,
+ SyncAfterCycle,
+ PauseFlagAlreadySet,
+ PauseFlagAlreadyClear,
+ DiskLowerThanOutdated,
+ FailedToClaimMyself,
+ AfterLastRetCode,
};
-struct ioctl_disk_config {
- struct disk_config config;
- OUT enum ret_codes ret_code;
- const int _pad;
-};
-
-struct ioctl_net_config {
- struct net_config config;
- OUT enum ret_codes ret_code;
- const int _pad;
-};
-
-struct ioctl_syncer_config {
- struct syncer_config config;
- OUT enum ret_codes ret_code;
- const int _pad;
-};
-
-struct ioctl_wait {
- IN int wfc_timeout;
- IN int degr_wfc_timeout;
- OUT int ret_code;
- int _pad;
-};
-
#define DRBD_PROT_A 1
#define DRBD_PROT_B 2
#define DRBD_PROT_C 3
@@ -284,21 +202,7 @@
# define BDEVNAME_SIZE 32
#endif
-struct ioctl_get_config {
- OUT __u64 disk_size_user;
- OUT char lower_device_name[BDEVNAME_SIZE];
- OUT char meta_device_name[BDEVNAME_SIZE];
- struct net_config nconf;
- struct syncer_config sconf;
- OUT int lower_device_major;
- OUT int lower_device_minor;
- OUT enum io_error_handler on_io_error;
- OUT enum fencing_policy fencing;
- OUT int meta_device_major;
- OUT int meta_device_minor;
- OUT int meta_index;
- OUT drbd_state_t state;
-};
+#define SHARED_SECRET_MAX 64
enum MetaDataFlags {
__MDF_Consistent,
@@ -327,13 +231,6 @@
#define UUID_JUST_CREATED ((__u64)4)
-struct ioctl_get_uuids {
- OUT __u64 uuid[UUID_SIZE];
- OUT __u64 current_size;
- OUT unsigned int flags;
- OUT unsigned int bits_set;
-};
-
#define DRBD_MAGIC 0x83740267
#define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC)
@@ -342,29 +239,25 @@
#define DRBD_MD_INDEX_FLEX_EXT -2
#define DRBD_MD_INDEX_FLEX_INT -3
-/* 'D' already taken by s390 dasd driver.
- * maybe we want to change to something else, and register it officially?
- */
-#define DRBD_IOCTL_LETTER 'D'
-#define DRBD_IOCTL_GET_VERSION _IOR( DRBD_IOCTL_LETTER, 0x00, int )
-#define DRBD_IOCTL_SET_STATE _IOW( DRBD_IOCTL_LETTER, 0x02, int )
-#define DRBD_IOCTL_SET_DISK_CONFIG _IOW( DRBD_IOCTL_LETTER, 0x06, struct ioctl_disk_config )
-#define DRBD_IOCTL_SET_NET_CONFIG _IOW( DRBD_IOCTL_LETTER, 0x07, struct ioctl_net_config )
-#define DRBD_IOCTL_UNCONFIG_NET _IO ( DRBD_IOCTL_LETTER, 0x08 )
-#define DRBD_IOCTL_GET_CONFIG _IOW( DRBD_IOCTL_LETTER, 0x0A, struct ioctl_get_config )
-#define DRBD_IOCTL_INVALIDATE _IO ( DRBD_IOCTL_LETTER, 0x0D )
-#define DRBD_IOCTL_INVALIDATE_REM _IO ( DRBD_IOCTL_LETTER, 0x0E )
-#define DRBD_IOCTL_SET_SYNC_CONFIG _IOW( DRBD_IOCTL_LETTER, 0x0F, struct ioctl_syncer_config )
-#define DRBD_IOCTL_SET_DISK_SIZE _IOW( DRBD_IOCTL_LETTER, 0x10, __u64 )
-#define DRBD_IOCTL_WAIT_CONNECT _IOR( DRBD_IOCTL_LETTER, 0x11, struct ioctl_wait )
-#define DRBD_IOCTL_WAIT_SYNC _IOR( DRBD_IOCTL_LETTER, 0x12, struct ioctl_wait )
-#define DRBD_IOCTL_UNCONFIG_DISK _IO ( DRBD_IOCTL_LETTER, 0x13 )
-#define DRBD_IOCTL_OUTDATE_DISK _IOW( DRBD_IOCTL_LETTER, 0x15, int )
-#define DRBD_IOCTL_GET_UUIDS _IOR( DRBD_IOCTL_LETTER, 0x16, struct ioctl_get_uuids )
-#define DRBD_IOCTL_PAUSE_SYNC _IO ( DRBD_IOCTL_LETTER, 0x17)
-#define DRBD_IOCTL_RESUME_SYNC _IO ( DRBD_IOCTL_LETTER, 0x18)
-#define DRBD_IOCTL_SUSPEND_IO _IOW( DRBD_IOCTL_LETTER, 0x19, int )
-#define DRBD_IOCTL_RESUME_IO _IOW( DRBD_IOCTL_LETTER, 0x1A, int )
+// Start of the new netlink/connector stuff
-#endif
+#define DRBD_NL_CREATE_DEVICE 0x01
+#define DRBD_NL_SET_DEFAULTS 0x02
+// The following line should be moved over to linux/connector.h
+// when the time comes
+#define CN_IDX_DRBD 0x4
+
+struct drbd_nl_cfg_req {
+ int drbd_minor;
+ int flags;
+ unsigned short tag_list[];
+};
+
+struct drbd_nl_cfg_reply {
+ int minor;
+ int ret_code; // enum ret_code or set_st_err_t
+ unsigned short tag_list[]; // only used with get_config()...
+};
+
+#endif
Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/drbd/linux/drbd_config.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -29,7 +29,7 @@
// undef if you need the workaround in drbd_receiver
#define HAVE_UML_TO_VIRT 1
-//#define DBG_ALL_SYMBOLS // no static functs, improves quality of OOPS traces
+#define DBG_ALL_SYMBOLS // no static functs, improves quality of OOPS traces
//#define DBG_SPINLOCKS // enables MUST_HOLD macro (assertions for spinlocks)
//#define DBG_ASSERTS // drbd_assert_breakpoint() function
Copied: trunk/drbd/linux/drbd_limits.h (from rev 2375, trunk/user/drbd_limits.h)
===================================================================
--- trunk/user/drbd_limits.h 2006-08-16 14:16:06 UTC (rev 2375)
+++ trunk/drbd/linux/drbd_limits.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -0,0 +1,118 @@
+/*
+ drbd_limits.h
+ This file is part of drbd by Philipp Reisner / Lars Ellenberg.
+*/
+
+/*
+ * Our current limitations.
+ * Some of them are hard limits,
+ * some of them are arbitrary range limits, that make it easier to provide
+ * feedback about nonsense settings for certain configurable values.
+ */
+
+#ifndef DRBD_LIMITS_H
+#define DRBD_LIMITS_H 1
+
+#define DEBUG_RANGE_CHECK 0
+
+#define DRBD_MINOR_COUNT_MIN 1
+#define DRBD_MINOR_COUNT_MAX 255
+
+#define DRBD_DIALOG_REFRESH_MIN 0
+#define DRBD_DIALOG_REFRESH_MAX 600
+
+/* valid port number */
+#define DRBD_PORT_MIN 1
+#define DRBD_PORT_MAX 0xffff
+
+/* startup { */
+ /* if you want more than 3.4 days, disable */
+#define DRBD_WFC_TIMEOUT_MIN 0
+#define DRBD_WFC_TIMEOUT_MAX 300000
+#define DRBD_WFC_TIMEOUT_DEF 0
+
+#define DRBD_DEGR_WFC_TIMEOUT_MIN 0
+#define DRBD_DEGR_WFC_TIMEOUT_MAX 300000
+#define DRBD_DEGR_WFC_TIMEOUT_DEF 60
+
+/* }*/
+
+/* net { */
+ /* timeout, unit centi seconds
+ * more than one minute timeout is not usefull */
+#define DRBD_TIMEOUT_MIN 1
+#define DRBD_TIMEOUT_MAX 600
+#define DRBD_TIMEOUT_DEF 60 // 6 seconds
+
+ /* active connection retries when WFConnection */
+#define DRBD_CONNECT_INT_MIN 1
+#define DRBD_CONNECT_INT_MAX 120
+#define DRBD_CONNECT_INT_DEF 10 //seconds
+
+ /* keep-alive probes when idle */
+#define DRBD_PING_INT_MIN 1
+#define DRBD_PING_INT_MAX 120
+#define DRBD_PING_INT_DEF 10
+
+ /* max number of write requests between write barriers */
+#define DRBD_MAX_EPOCH_SIZE_MIN 1
+#define DRBD_MAX_EPOCH_SIZE_MAX 20000
+#define DRBD_MAX_EPOCH_SIZE_DEF 2048
+
+ /* I don't think that a tcp send buffer of more than 10M is usefull */
+#define DRBD_SNDBUF_SIZE_MIN 1
+#define DRBD_SNDBUF_SIZE_MAX 10000000
+#define DRBD_SNDBUF_SIZE_DEF (2*65535)
+
+ /* @4k PageSize -> 128kB - 512MB */
+#define DRBD_MAX_BUFFERS_MIN 32
+#define DRBD_MAX_BUFFERS_MAX 131072
+#define DRBD_MAX_BUFFERS_DEF 2048
+
+ /* @4k PageSize -> 4kB - 512MB */
+#define DRBD_UNPLUG_WATERMARK_MIN 1
+#define DRBD_UNPLUG_WATERMARK_MAX 131072
+#define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16)
+
+ /* 0 is disabled.
+ * 200 should be more than enough even for very short timeouts */
+#define DRBD_KO_COUNT_MIN 0
+#define DRBD_KO_COUNT_MAX 200
+#define DRBD_KO_COUNT_DEF 0
+/* } */
+
+/* syncer { */
+ /* FIXME allow rate to be zero? */
+#define DRBD_RATE_MIN 1
+#define DRBD_RATE_MAX 700000
+#define DRBD_RATE_DEF 250 // kb/second
+
+ /* less than 7 would hit performance unneccessarily.
+ * 3833 is the largest prime that still does fit
+ * into 64 sectors of activity log */
+#define DRBD_AL_EXTENTS_MIN 7
+#define DRBD_AL_EXTENTS_MAX 3833
+#define DRBD_AL_EXTENTS_DEF 127
+
+#define DRBD_AFTER_MIN -1
+#define DRBD_AFTER_MAX 255
+#define DRBD_AFTER_DEF -1
+
+/* } */
+
+/* drbdsetup XY resize -d Z
+ * you are free to reduce the device size to nothing, if you want to.
+ * but more than 3998G are currently not possible */
+/* DRBD_MAX_SECTORS */
+#define DRBD_DISK_SIZE_SECT_MIN 0
+#define DRBD_DISK_SIZE_SECT_MAX (128LLU*1024*2 - 72)*512LLU*8*8
+#define DRBD_DISK_SIZE_SECT_DEF 0 // = disabled = no user size...
+
+#define DRBD_ON_IO_ERROR_DEF PassOn
+#define DRBD_FENCING_DEF DontCare
+#define DRBD_AFTER_SB_0P_DEF Disconnect
+#define DRBD_AFTER_SB_1P_DEF Disconnect
+#define DRBD_AFTER_SB_2P_DEF Disconnect
+
+#undef RANGE
+#endif
Copied: trunk/drbd/linux/drbd_nl.h (from rev 2375, trunk/user/drbd_nl.h)
===================================================================
--- trunk/user/drbd_nl.h 2006-08-16 14:16:06 UTC (rev 2375)
+++ trunk/drbd/linux/drbd_nl.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -0,0 +1,78 @@
+/*
+ PAKET( name,
+ TYPE ( pn, pr, member )
+ ...
+ )
+
+ You may never reissue one of the pn arguments
+*/
+
+#if !defined(PACKET) || !defined(STRING) || !defined(INTEGER) || !defined(BIT) || !defined(INT64)
+#error "The macros PACKET, STRING, INTEGER, INT64 and BIT needs to be defined"
+#endif
+
+PACKET(primary,
+ BIT( 1, T_MAY_IGNORE, overwrite_peer)
+)
+
+PACKET(secondary, )
+
+PACKET(disk_conf,
+ INT64( 2, T_MAY_IGNORE, disk_size)
+ STRING( 3, T_MANDATORY, backing_dev, 32)
+ STRING( 4, T_MANDATORY, meta_dev, 32)
+ INTEGER( 5, T_MANDATORY, meta_dev_idx)
+ INTEGER( 6, T_MAY_IGNORE, on_io_error)
+ INTEGER( 7, T_MAY_IGNORE, fencing)
+)
+
+PACKET(detach, )
+
+PACKET(net_conf,
+ STRING( 8, T_MANDATORY, my_addr, 128)
+ STRING( 9, T_MANDATORY, peer_addr, 128)
+ STRING( 10, T_MAY_IGNORE, shared_secret, SHARED_SECRET_MAX)
+ STRING( 11, T_MAY_IGNORE, cram_hmac_alg, SHARED_SECRET_MAX)
+ INTEGER( 14, T_MAY_IGNORE, timeout)
+ INTEGER( 15, T_MANDATORY, wire_protocol)
+ INTEGER( 16, T_MAY_IGNORE, try_connect_int)
+ INTEGER( 17, T_MAY_IGNORE, ping_int)
+ INTEGER( 18, T_MAY_IGNORE, max_epoch_size)
+ INTEGER( 19, T_MAY_IGNORE, max_buffers)
+ INTEGER( 20, T_MAY_IGNORE, unplug_watermark)
+ INTEGER( 21, T_MAY_IGNORE, sndbuf_size)
+ INTEGER( 22, T_MAY_IGNORE, ko_count)
+ INTEGER( 24, T_MAY_IGNORE, after_sb_0p)
+ INTEGER( 25, T_MAY_IGNORE, after_sb_1p)
+ INTEGER( 26, T_MAY_IGNORE, after_sb_2p)
+ BIT( 27, T_MAY_IGNORE, want_lose)
+ BIT( 28, T_MAY_IGNORE, two_primaries)
+)
+
+PACKET(disconnect, )
+
+PACKET(resize,
+ INT64( 29, T_MAY_IGNORE, resize_size)
+)
+
+PACKET(syncer_conf,
+ INTEGER( 30, T_MAY_IGNORE, rate)
+ INTEGER( 31, T_MAY_IGNORE, after)
+ INTEGER( 32, T_MAY_IGNORE, al_extents)
+)
+
+PACKET(invalidate, )
+PACKET(invalidate_peer, )
+PACKET(pause_sync, )
+PACKET(resume_sync, )
+PACKET(suspend_io, )
+PACKET(resume_io, )
+PACKET(outdate, )
+PACKET(get_config, )
+
+#undef PACKET
+#undef INTEGER
+#undef INT64
+#undef BIT
+#undef STRING
+
Copied: trunk/drbd/linux/drbd_tag_magic.h (from rev 2375, trunk/user/drbd_tag_magic.h)
===================================================================
--- trunk/user/drbd_tag_magic.h 2006-08-16 14:16:06 UTC (rev 2375)
+++ trunk/drbd/linux/drbd_tag_magic.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -0,0 +1,66 @@
+#ifndef DRBD_TAG_MAGIC_H
+#define DRBD_TAG_MAGIC_H
+
+#define TT_END 0
+#define TT_REMOVED 0xE000
+
+// declare packet_type enums
+enum packet_types {
+#define PACKET(name, fields) P_ ## name,
+#define INTEGER(pn,pr,member)
+#define INT64(pn,pr,member)
+#define BIT(pn,pr,member)
+#define STRING(pn,pr,member,len)
+#include "drbd_nl.h"
+ P_nl_after_last_packet,
+};
+
+// declate tag-list-sizes
+#define PACKET(name,fields) const int name ## _tag_size = 2 fields ;
+#define INTEGER(pn,pr,member) +4+4
+#define INT64(pn,pr,member) +4+8
+#define BIT(pn,pr,member) +4+1
+#define STRING(pn,pr,member,len) +4+len
+#include "drbd_nl.h"
+
+/* The two highest bits are used for the tag type */
+#define TT_MASK 0xC000
+#define TT_INTEGER 0x0000
+#define TT_INT64 0x4000
+#define TT_BIT 0x8000
+#define TT_STRING 0xC000
+/* The next bit indicates if processing of the tag is mandatory */
+#define T_MANDATORY 0x2000
+#define T_MAY_IGNORE 0x0000
+#define TN_MASK 0x1fff
+/* The remaining 13 bits are used to enumerate the tags */
+
+#define tag_type(T) ((T) & TT_MASK)
+#define tag_number(T) ((T) & TN_MASK)
+
+// declare tag enums
+#define PACKET(name, fields) fields
+enum drbd_tags {
+#define INTEGER(pn,pr,member) T_ ## member = pn | TT_INTEGER | pr ,
+#define INT64(pn,pr,member) T_ ## member = pn | TT_INT64 | pr ,
+#define BIT(pn,pr,member) T_ ## member = pn | TT_BIT | pr ,
+#define STRING(pn,pr,member,len) T_ ## member = pn | TT_STRING | pr ,
+#include "drbd_nl.h"
+};
+
+struct tag {
+ const char* name;
+ int type_n_flags;
+};
+
+// declare tag names
+#define PACKET(name, fields) fields
+const struct tag tag_descriptions[] = {
+#define INTEGER(pn,pr,member) [ pn ] = { #member, TT_INTEGER | pr },
+#define INT64(pn,pr,member) [ pn ] = { #member, TT_INT64 | pr },
+#define BIT(pn,pr,member) [ pn ] = { #member, TT_BIT | pr },
+#define STRING(pn,pr,member,len) [ pn ] = { #member, TT_STRING | pr },
+#include "drbd_nl.h"
+};
+
+#endif
Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/Makefile 2006-08-25 08:50:47 UTC (rev 2386)
@@ -17,7 +17,7 @@
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#
-CFLAGS = -g -O2 -c -W -Wall -I../drbd
+CFLAGS = -g -O2 -c -W -Wall -I../drbd -I$(KDIR)/include
CC = gcc
drbdadm-obj = drbdadm_scanner.o drbdadm_parser.o drbdadm_main.o \
@@ -29,7 +29,7 @@
drbdmeta-obj = drbdmeta.o drbdmeta_scanner.o drbdtool_common.o ../drbd/drbd_buildtag.o
-all: drbdsetup drbdadm drbdmeta drbdsetup_nl
+all: drbdadm drbdmeta drbdsetup_nl
drbdadm: $(drbdadm-obj)
$(CC) -o $@ $^
@@ -42,11 +42,11 @@
# for debug: flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
-drbdsetup_nl: drbdsetup_nl.o drbdtool_common.o
+drbdsetup_nl: drbdsetup_nl.o drbdtool_common.o ../drbd/drbd_strings.o
$(CC) -o $@ $^
-drbdsetup: $(drbdsetup-obj)
- $(CC) -o $@ $^
+#drbdsetup: $(drbdsetup-obj)
+# $(CC) -o $@ $^
drbdmeta: $(drbdmeta-obj)
$(CC) -o $@ $^
@@ -75,13 +75,13 @@
rm -f $(PREFIX)/sbin/drbdadm
###dependencies
-drbdsetup.o: drbdtool_common.h drbd_limits.h
+drbdsetup.o: drbdtool_common.h ../drbd/linux/drbd_limits.h
drbdtool_common.o: drbdtool_common.h
drbdadm_main.o: drbdtool_common.h drbdadm.h
drbdadm_adjust.o: drbdtool_common.h drbdadm.h
-drbdadm_parser.o: drbdtool_common.h drbdadm.h drbd_limits.h
+drbdadm_parser.o: drbdtool_common.h drbdadm.h ../drbd/linux/drbd_limits.h
drbdadm_scanner.o: drbdadm.h drbdadm_parser.h
-drbdsetup.o: drbdtool_common.h drbd_limits.h
+drbdsetup.o: drbdtool_common.h ../drbd/linux/drbd_limits.h
drbdsetup.o: ../drbd/linux/drbd.h ../drbd/linux/drbd_config.h
drbdmeta.o: drbdtool_common.h drbd_endian.h
drbdadm_usage_cnt.o: drbdadm.h drbd_endian.h
Deleted: trunk/user/drbd_limits.h
===================================================================
--- trunk/user/drbd_limits.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbd_limits.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,80 +0,0 @@
-/*
- drbd_limits.h
- This file is part of drbd by Philipp Reisner / Lars Ellenberg.
-*/
-
-/*
- * Our current limitations.
- * Some of them are hard limits,
- * some of them are arbitrary range limits, that make it easier to provide
- * feedback about nonsense settings for certain configurable values.
- */
-
-#ifndef DRBD_LIMITS_H
-#define DRBD_LIMITS_H 1
-
-#define DEBUG_RANGE_CHECK 0
-
-#define RANGE(what,min,max) \
-const unsigned long long DRBD_ ## what ## _MIN = (min); \
-const unsigned long long DRBD_ ## what ## _MAX = (max)
-
-RANGE(MINOR_COUNT,1,255);
-RANGE(DIALOG_REFRESH,0,600);
-
-/* valid port number */
-RANGE(PORT,1,0xffff);
-
-
-/* startup { */
- /* if you want more than 3.4 days, disable */
- RANGE(WFC_TIMEOUT,0,300000);
- RANGE(DEGR_WFC_TIMEOUT,0,300000);
-/* }*/
-
-/* net { */
- /* timeout, unit centi seconds
- * more than one minute timeout is not usefull */
- RANGE(TIMEOUT,1,600);
-
- /* active connection retries when WFConnection */
- RANGE(CONNECT_INT,1,120);
-
- /* keep-alive probes when idle */
- RANGE(PING_INT,1,120);
-
- /* max number of write requests between write barriers */
- RANGE(MAX_EPOCH_SIZE,1,20000);
-
- /* I don't think that a tcp send buffer of more than 10M is usefull */
- RANGE(SNDBUF_SIZE, 1, 10000000);
-
- /* @4k PageSize -> 128kB - 512MB */
- RANGE(MAX_BUFFERS, 32, 131072);
-
- /* @4k PageSize -> 4kB - 512MB */
- RANGE(UNPLUG_WATERMARK, 1, 131072);
-
- /* 0 is disabled.
- * 200 should be more than enough even for very short timeouts */
- RANGE(KO_COUNT,0, 200);
-/* } */
-
-/* syncer { */
- /* FIXME allow rate to be zero? */
- RANGE(RATE,1,700000);
-
- /* less than 7 would hit performance unneccessarily.
- * 3833 is the largest prime that still does fit
- * into 64 sectors of activity log */
- RANGE(AL_EXTENTS, 7, 3833);
-/* } */
-
-/* drbdsetup XY resize -d Z
- * you are free to reduce the device size to nothing, if you want to.
- * but more than 3998G are currently not possible */
-/* DRBD_MAX_SECTORS */
-RANGE(DISK_SIZE_SECT, 0, (128LLU*1024*2 - 72)*512LLU*8*8 );
-
-#undef RANGE
-#endif
Deleted: trunk/user/drbd_nl.h
===================================================================
--- trunk/user/drbd_nl.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbd_nl.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,79 +0,0 @@
-/*
- PAKET( name,
- TYPE ( pn, pr, member )
- ...
- )
-
- You may never reissue one of the pn arguments
-*/
-
-#if !defined(PACKET) || !defined(STRING) || !defined(INTEGER) || !defined(BIT) || !defined(INT64)
-#error "The macros PACKET, STRING, INTEGER, INT64 and BIT needs to be defined"
-#endif
-
-PACKET(primary,
- BIT( 1, T_MAY_IGNORE, overwrite_peer)
-)
-
-PACKET(secondary, )
-
-PACKET(disk_conf,
- INT64( 2, T_MAY_IGNORE, disk_size)
- INTEGER( 3, T_MANDATORY, backing_dev)
- INTEGER( 4, T_MANDATORY, meta_dev)
- INTEGER( 5, T_MANDATORY, meta_dev_idx)
- INTEGER( 6, T_MAY_IGNORE, on_io_error)
- INTEGER( 7, T_MAY_IGNORE, fencing)
-)
-
-PACKET(detach, )
-
-PACKET(net_conf,
- STRING( 8, T_MANDATORY, my_addr, 128)
- STRING( 9, T_MANDATORY, peer_addr, 128)
- STRING( 10, T_MAY_IGNORE, shared_secret, 128)
- STRING( 11, T_MAY_IGNORE, cram_hmac_alg, 128)
- INTEGER( 12, T_MANDATORY, my_addr_len)
- INTEGER( 13, T_MANDATORY, peer_addr_len)
- INTEGER( 14, T_MAY_IGNORE, timeout)
- INTEGER( 15, T_MANDATORY, wire_protocol)
- INTEGER( 16, T_MAY_IGNORE, try_connect_int)
- INTEGER( 17, T_MAY_IGNORE, ping_int)
- INTEGER( 18, T_MAY_IGNORE, max_epoch_size)
- INTEGER( 19, T_MAY_IGNORE, max_buffers)
- INTEGER( 20, T_MAY_IGNORE, unplug_watermark)
- INTEGER( 21, T_MAY_IGNORE, sndbuf_size)
- INTEGER( 22, T_MAY_IGNORE, ko_count)
- INTEGER( 24, T_MAY_IGNORE, after_sb_0p)
- INTEGER( 25, T_MAY_IGNORE, after_sb_1p)
- INTEGER( 26, T_MAY_IGNORE, after_sb_2p)
- BIT( 27, T_MAY_IGNORE, want_lose)
- BIT( 28, T_MAY_IGNORE, two_primaries)
-)
-
-PACKET(disconnect, )
-
-PACKET(resize,
- INT64( 29, T_MAY_IGNORE, resize_size)
-)
-
-PACKET(syncer_conf,
- INTEGER( 30, T_MAY_IGNORE, sync_rate)
- INTEGER( 31, T_MAY_IGNORE, sync_after)
- INTEGER( 32, T_MAY_IGNORE, al_extents)
-)
-
-PACKET(invalidate, )
-PACKET(invalidate_peer, )
-PACKET(pause_sync, )
-PACKET(resume_sync, )
-PACKET(suspend_io, )
-PACKET(resume_io, )
-PACKET(outdate, )
-
-#undef PACKET
-#undef INTEGER
-#undef INT64
-#undef BIT
-#undef STRING
-
Deleted: trunk/user/drbd_tag_magic.h
===================================================================
--- trunk/user/drbd_tag_magic.h 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbd_tag_magic.h 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,72 +0,0 @@
-#ifndef DRBD_TAG_MAGIC_H
-#define DRBD_TAG_MAGIC_H
-
-#define TT_END 0
-
-// declare packet_type enums
-enum packet_types {
-#define PACKET(name, fields) P_ ## name,
-#define INTEGER(pn,pr,member)
-#define INT64(pn,pr,member)
-#define BIT(pn,pr,member)
-#define STRING(pn,pr,member,len)
-#include "drbd_nl.h"
-};
-
-// declate structs
-#define PACKET(name, fields) struct name { fields };
-#define INTEGER(pn,pr,member) int member;
-#define INT64(pn,pr,member) __u64 member;
-#define BIT(pn,pr,member) unsigned member : 1;
-#define STRING(pn,pr,member,len) unsigned char member[len];
-#include "drbd_nl.h"
-
-// declate tag-list-sizes
-#define PACKET(name,fields) const int name ## _tag_size = 2 fields ;
-#define INTEGER(pn,pr,member) +4+4
-#define INT64(pn,pr,member) +4+8
-#define BIT(pn,pr,member) +4+1
-#define STRING(pn,pr,member,len) +4+len
-#include "drbd_nl.h"
-
-/* The two highest bits are used for the tag type */
-#define TT_MASK 0xC000
-#define TT_INTEGER 0x0000
-#define TT_INT64 0x4000
-#define TT_BIT 0x8000
-#define TT_STRING 0xC000
-/* The next bit indicates if processing of the tag is mandatory */
-#define T_MANDATORY 0x2000
-#define T_MAY_IGNORE 0x0000
-#define TN_MASK 0x1fff
-/* The remaining 13 bits are used to enumerate the tags */
-
-#define tag_type(T) ((T) & TT_MASK)
-#define tag_number(T) ((T) & TN_MASK)
-
-// declare tag enums
-#define PACKET(name, fields) fields
-enum drbd_tags {
-#define INTEGER(pn,pr,member) T_ ## member = pn | TT_INTEGER | pr ,
-#define INT64(pn,pr,member) T_ ## member = pn | TT_INT64 | pr ,
-#define BIT(pn,pr,member) T_ ## member = pn | TT_BIT | pr ,
-#define STRING(pn,pr,member,len) T_ ## member = pn | TT_STRING | pr ,
-#include "drbd_nl.h"
-};
-
-struct tag {
- const char* name;
- int type_n_flags;
-};
-
-// declare tag names
-#define PACKET(name, fields) fields
-const struct tag tag_descriptions[] = {
-#define INTEGER(pn,pr,member) [ pn ] = { #member, TT_INTEGER | pr },
-#define INT64(pn,pr,member) [ pn ] = { #member, TT_INT64 | pr },
-#define BIT(pn,pr,member) [ pn ] = { #member, TT_BIT | pr },
-#define STRING(pn,pr,member,len) [ pn ] = { #member, TT_STRING | pr },
-#include "drbd_nl.h"
-};
-
-#endif
Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbdadm_parser.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -30,7 +30,7 @@
#include <string.h>
#include "drbdadm.h"
-#include "drbd_limits.h"
+#include "linux/drbd_limits.h"
#include "drbdtool_common.h"
#include "drbdadm_parser.h"
Deleted: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbdsetup.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -1,1669 +0,0 @@
-/*
- drbdsetup.c
-
- This file is part of drbd by Philipp Reisner.
-
- Copyright (C) 1999-2006, Philipp Reisner <philipp.reisner at linbit.com>.
- Copyright (C) 2002-2006, Lars Ellenberg <lars.ellenberg at linbit.com>.
- Copyright (C) 2001-2006, LINBIT Information Technologies GmbH.
-
- Copyright (C) 2000, Fábio Olivé Leite <olive at conectiva.com.br>.
- Added sanity checks before using the device.
-
- drbd is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- drbd is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with drbd; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <linux/drbd.h>
-#include <linux/drbd_config.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <mntent.h>
-#include "drbdtool_common.h"
-#include "drbd_limits.h"
-
-/* Default values */
-#define DEF_NET_TIMEOUT 60 // 6 seconds
-#define DEF_NET_TRY_CON_I 10 // 10 seconds
-#define DEF_NET_PING_I 10 // 10 seconds
-#define DEF_SYNC_RATE 250
-#define DEF_SYNC_AFTER -1
-#define DEF_WFC_TIMEOUT 0 // forever
-#define DEF_DEGR_WFC_TIMEOUT 60 // 60 Seconds
-#define DEF_SYNC_WFC_TIMEOUT 8 // 8 seconds
-#define DEF_SYNC_DEGR_WFC_TIMEOUT 4 // 4 seconds
-#define DEF_SYNC_AL_EXTENTS 127
-#define DEF_MAX_EPOCH_SIZE 2048 // entries
-#define DEF_MAX_BUFFERS 2048 // entries
-#define DEF_SNDBUF_SIZE (2*65535) // ~128KB
-#define DEF_DISK_SIZE 0
-#define DEF_ON_IO_ERROR PassOn
-#define DEF_KO_COUNT 0
-#define DEF_ON_DISCONNECT Reconnect
-#define DEF_FENCING DontCare
-#define DEF_TWO_PRIMARIES 0
-#define DEF_AFTER_SB_0P Disconnect
-#define DEF_AFTER_SB_1P Disconnect
-#define DEF_AFTER_SB_2P Disconnect
-#define DEF_UNPLUG_WATERMARK (DEF_MAX_BUFFERS/16)
-
-#if 0
-# define ioctl(X...) (fprintf(stderr,"ioctl(%s)\n",#X),0);
-# define PRINT_ARGV do { \
- int i; \
- fprintf(stderr,"# argv (optind=%i argc=%i) in %s:%i:\n#",\
- optind, argc, __FUNCTION__, __LINE__); \
- for (i=optind; i < argc; i++) \
- fprintf(stderr," %s",argv[i]); \
- fprintf(stderr,"\n"); \
-} while(0)
-#else
-# define PRINT_ARGV
-#endif
-
-/* avoid warnings with -W for unused function arguments;
- * alternative use __attribute((unused))
-#define UNUSED(x) (void)(x == x)
- */
-
-// some globals
-char* cmdname = 0;
-
-struct drbd_cmd {
- const char* cmd;
- int (* function)(int, char**, int, struct option*);
- char **args;
- struct option *options;
-};
-
-int cmd_primary(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_secondary(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_wait_sync(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_wait_connect(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_invalidate(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_invalidate_rem(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_down(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_net_conf(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_disk_conf(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_disk_size(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_outdate(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_disconnect(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_show(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_syncer(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_pause_sync(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_resume_sync(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_detach(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_state(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_cstate(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_dstate(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_show_gi(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_get_gi(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_suspend_io(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_resume_io(int drbd_fd,char** argv,int argc,struct option *options);
-
-
-struct drbd_cmd commands[] = {
- {"primary", cmd_primary, 0,
- (struct option[]) {
- { "do-what-I-say",no_argument, 0, 'd' },
- { "overwrite-data-of-peer",no_argument, 0, 'o' },
- { 0, 0, 0, 0 } } },
- {"secondary", cmd_secondary, 0, 0, },
- {"wait_sync", cmd_wait_sync, 0,
- (struct option[]) {
- { "wfc-timeout",required_argument, 0, 't' },
- { "degr-wfc-timeout",required_argument,0,'d'},
- { 0, 0, 0, 0 } } },
- {"wait_connect", cmd_wait_connect, 0,
- (struct option[]) {
- { "wfc-timeout",required_argument, 0, 't' },
- { "degr-wfc-timeout",required_argument,0,'d'},
- { 0, 0, 0, 0 } } },
- {"invalidate", cmd_invalidate, 0, 0, },
- {"invalidate_remote", cmd_invalidate_rem,0, 0, },
- {"syncer", cmd_syncer, 0,
- (struct option[]) {
- { "after", required_argument, 0, 'a' },
- { "rate", required_argument, 0, 'r' },
- { "al-extents", required_argument, 0, 'e' },
- { 0, 0, 0, 0 } } },
- {"pause-sync", cmd_pause_sync, 0, 0, },
- {"resume-sync", cmd_resume_sync, 0, 0, },
- {"down", cmd_down, 0, 0, },
- {"detach", cmd_detach, 0, 0, },
- {"net", cmd_net_conf, (char *[]){"local_addr","remote_addr","protocol",0},
- (struct option[]) {
- { "timeout", required_argument, 0, 't' },
- { "max-epoch-size", required_argument, 0, 'e' },
- { "max-buffers",required_argument, 0, 'b' },
- { "unplug-watermark",required_argument, 0, 'u' },
- { "connect-int",required_argument, 0, 'c' },
- { "ping-int", required_argument, 0, 'i' },
- { "sndbuf-size",required_argument, 0, 'S' },
- { "ko-count", required_argument, 0, 'k' },
- { "on-disconnect",required_argument, 0, 'd' },
- { "allow-two-primaries",no_argument, 0, 'm' },
- { "cram-hmac-alg",required_argument, 0, 'a' },
- { "shared-secret",required_argument, 0, 'x' },
- { "after-sb-0pri",required_argument, 0, 'A' },
- { "after-sb-1pri",required_argument, 0, 'B' },
- { "after-sb-2pri",required_argument, 0, 'C' },
- { "discard-my-data", no_argument, 0, 'D' },
- { 0, 0, 0, 0 } } },
- {"disk", cmd_disk_conf,(char *[]){"lower_dev","meta_data_dev",
- "meta_data_index",0},
- (struct option[]) {
- { "size", required_argument, 0, 'd' },
- { "on-io-error",required_argument, 0, 'e' },
- { "fencing", required_argument, 0, 'f' },
- { 0, 0, 0, 0 } } },
- {"resize", cmd_disk_size, 0,
- (struct option[]) {
- { "size", required_argument, 0, 'd' },
- { 0, 0, 0, 0 } } },
- {"outdate", cmd_outdate, 0, 0, },
- {"disconnect", cmd_disconnect, 0, 0, },
- {"state", cmd_state, 0, 0, },
- {"cstate", cmd_cstate, 0, 0, },
- {"dstate", cmd_dstate, 0, 0, },
- {"show-gi", cmd_show_gi, 0, 0, },
- {"get-gi", cmd_get_gi, 0, 0, },
- {"show", cmd_show, 0, 0, },
- {"suspend-io", cmd_suspend_io, 0, 0, },
- {"resume-io", cmd_resume_io, 0, 0, },
-};
-
-const char *eh_names[] = {
- [PassOn] = "pass_on",
- [Panic] = "panic",
- [Detach] = "detach"
-};
-
-const char *dh_names[] = {
- [Reconnect] = "reconnect",
- [DropNetConf] = "stand_alone",
- // [FreezeIO] = "freeze_io" // TODO on the kernel side...
-};
-
-const char *fencing_names[] = {
- [DontCare] = "dont-care",
- [Resource] = "resource-only",
- [Stonith] = "resource-and-stonith"
-};
-
-const char *asb0p_names[] = {
- [Disconnect] = "disconnect",
- [DiscardYoungerPri] = "discard-younger-primary",
- [DiscardOlderPri] = "discard-older-primary",
- [DiscardLeastChg] = "discard-least-changes",
- [DiscardLocal] = "discard-local",
- [DiscardRemote] = "discard-remote"
-};
-
-const char *asb1p_names[] = {
- [Disconnect] = "disconnect",
- [Consensus] = "consensus",
- [DiscardSecondary] = "discard-secondary",
- [PanicPrimary] = "panic-primary"
-};
-
-const char *asb2p_names[] = {
- [Disconnect] = "disconnect",
- [PanicPrimary] = "panic"
-};
-
-int _lookup_handler(const char* text, const char** handlers, int size)
-{
- int i;
-
- for(i=0;i<size;i++) {
- if (handlers[i]==0) continue;
- if (strcmp(text,handlers[i])==0) {
- return i;
- }
- }
- return -1;
-}
-
-#define lookup_handler(A,B) _lookup_handler(A,B,ARRY_SIZE(B))
-
-unsigned long resolv(const char* name)
-{
- unsigned long retval;
-
- if((retval = inet_addr(name)) == INADDR_NONE )
- {
- struct hostent *he;
- he = gethostbyname(name);
- if (!he)
- {
- PERROR("can not resolv the hostname");
- exit(20);
- }
- retval = ((struct in_addr *)(he->h_addr_list[0]))->s_addr;
- }
- return retval;
-}
-
-/* NOTE all values are _unsigned_ */
-unsigned long long
-m_strtoll_range(const char *s, const char def_unit, const char *name,
- const unsigned long long min, const unsigned long long max)
-{
- unsigned long long r = m_strtoll(s, def_unit);
- char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
- if (min > r || r > max)
- {
- fprintf(stderr, "%s %s => %llu%s out of range [%llu..%llu]%s\n",
- name, s, r, unit, min, max, unit);
- exit(20);
- }
- if (DEBUG_RANGE_CHECK)
- {
- fprintf(stderr,
- "OK: %s %s => %llu%s in range [%llu..%llu]%s.\n",
- name, s, r, unit, min, max, unit);
- }
- return r;
-}
-
-const char* addr_part(const char* s)
-{
- static char buffer[200];
- char *b;
-
- b=strchr(s,':');
- if(b)
- {
- strncpy(buffer,s,b-s);
- buffer[b-s]=0;
- return buffer;
- }
- return s;
-}
-
-int port_part(const char* s)
-{
- char *b;
-
- b=strchr(s,':');
- if(b)
- return m_strtoll_range(b+1,1, "port", DRBD_PORT_MIN, DRBD_PORT_MAX);
-
- return 7788;
-}
-
-int already_in_use_tab(const char* dev_name,const char* tab_name)
-{
- FILE* tab;
- struct mntent* entry;
-
-
- if( ! (tab=setmntent(tab_name,"r")) )
- return 0;
-
- while( (entry=getmntent(tab)) )
- {
- if( !strcmp(entry->mnt_fsname, dev_name) )
- {
- endmntent(tab);
- return 1;
- }
- }
-
- endmntent(tab);
-
- return 0;
-}
-
-int already_in_use(const char* dev_name)
-{
- return already_in_use_tab(dev_name,"/etc/mtab") ||
- already_in_use_tab(dev_name,"/proc/mounts");
-}
-
-void print_command_usage(int i, const char *addinfo)
- // CAUTION no range check for i
-{
- char **args;
- struct option *options;
-#define maxcol 70 // plus initial tab ...
- static char line[maxcol+1];
- int col,prevcol;
-
- prevcol=col=0;
-
- col += snprintf(line+col, maxcol-col, " %s", commands[i].cmd);
- if ((args = commands[i].args)) {
- while (*args)
- col += snprintf(line+col, maxcol-col, " %s", *args++);
- }
- if (col > maxcol) {
- printf("%s\n\t",line);
- col=0;
- }
- prevcol=col;
- if ((options = commands[i].options)) {
- while (options->name) {
- if (options->has_arg == required_argument) {
- col += snprintf(line+col, maxcol-col, " [{--%s|-%c} val]",
- options->name, options->val);
- } else {
- col += snprintf(line+col, maxcol-col, " [{--%s|-%c}]",
- options->name, options->val);
- }
- if (col >= maxcol) {
- line[prevcol]=0;
- printf("%s\n\t",line);
- prevcol=col=0;
- } else {
- prevcol=col;
- options++;
- }
- }
- }
- line[col]=0;
- printf("%s\n",line);
- if (addinfo) {
- printf("%s\n",addinfo);
- exit(20);
- }
-}
-
-void print_usage(const char* addinfo)
-{
- size_t i;
-
- printf("\nUSAGE: %s device command arguments options\n\n"
- "Device is usually /dev/drbdX or /dev/drbd/X.\n"
- "Commands, arguments and options are:\n",cmdname);
-
-
- for (i = 0; i < ARRY_SIZE(commands); i++)
- print_command_usage(i, 0);
-
- printf("\nAvailable on-io-error handlers:");
- for(i=0;i<ARRY_SIZE(eh_names);i++) {
- printf(" %s",eh_names[i]);
- if(i < ARRY_SIZE(eh_names)-1) printf(",");
- }
-
- printf("\nAvailable on-disconnect handlers:");
- for(i=0;i<ARRY_SIZE(dh_names);i++) {
- printf(" %s",dh_names[i]);
- if(i < ARRY_SIZE(dh_names)-1) printf(",");
- }
-
- printf("\nAvailable fencing policies:");
- for(i=0;i<ARRY_SIZE(fencing_names);i++) {
- printf(" %s",fencing_names[i]);
- if(i < ARRY_SIZE(fencing_names)-1) printf(",");
- }
-
- printf("\n\nVersion: "REL_VERSION" (api:%d)\n%s\n",
- API_VERSION, drbd_buildtag());
- if (addinfo)
- printf("\n%s\n",addinfo);
-
- exit(20);
-}
-
-int open_drbd_device(const char* device)
-{
- int err,drbd_fd,version = 0;
-
- drbd_fd = dt_lock_open_drbd(device,NULL,0);
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_VERSION,&version);
- if(err)
- {
- PERROR("ioctl(,GET_VERSION,) failed");
- exit(20);
- }
-
- if (version != API_VERSION)
- {
- fprintf(stderr,"\tVersion tags of drbdsetup and drbd kernel module are not matching!\n"
- "\tAPI_VERSION: drbdsetup:%d -- drbd module:%d\n"
- "\tPlease check your installation!\n", API_VERSION, version);
- exit(20);
- }
-
- return drbd_fd;
-}
-
-int scan_disk_options(char **argv,
- int argc,
- struct ioctl_disk_config* cn,
- struct option *options)
-{
- cn->config.disk_size = 0; /* default not known */
- cn->config.on_io_error = DEF_ON_IO_ERROR;
- cn->config.fencing = DEF_FENCING;
-
- if(argc==0) return 0;
-
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- c = getopt_long(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 'd':
- cn->config.disk_size = m_strtoll_range(optarg,'K', "size",
- DRBD_DISK_SIZE_SECT_MIN>>1,
- DRBD_DISK_SIZE_SECT_MAX>>1 ) << 1;
- break;
- case 'e':
- cn->config.on_io_error=lookup_handler(optarg,eh_names);
- if( cn->config.on_io_error == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid on-io-error handler.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 'f':
- cn->config.fencing = lookup_handler(optarg,fencing_names);
- if( cn->config.fencing == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid fency policy.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
- return 0;
-}
-
-int scan_net_options(char **argv,
- int argc,
- struct ioctl_net_config* cn,
- struct option *options)
-{
- cn->config.timeout = DEF_NET_TIMEOUT;
- cn->config.try_connect_int = DEF_NET_TRY_CON_I;
- cn->config.ping_int = DEF_NET_PING_I;
- cn->config.max_epoch_size = DEF_MAX_EPOCH_SIZE;
- cn->config.max_buffers = DEF_MAX_BUFFERS;
- cn->config.sndbuf_size = DEF_SNDBUF_SIZE ;
- cn->config.on_disconnect = DEF_ON_DISCONNECT;
- cn->config.two_primaries = DEF_TWO_PRIMARIES;
- cn->config.cram_hmac_alg[0] = 0;
- cn->config.shared_secret[0] = 0;
- cn->config.after_sb_0p = DEF_AFTER_SB_0P;
- cn->config.after_sb_1p = DEF_AFTER_SB_1P;
- cn->config.after_sb_2p = DEF_AFTER_SB_2P;
- cn->config.want_lose = 0;
- cn->config.ko_count = DEF_KO_COUNT;
- cn->config.unplug_watermark = DEF_UNPLUG_WATERMARK;
-
- if(argc==0) return 0;
-
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- c = getopt_long(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 't':
- cn->config.timeout = m_strtoll_range(optarg,1, "timeout",
- DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
- break;
- case 'e':
- cn->config.max_epoch_size = m_strtoll_range(optarg,1,
- "max-epoch-size",
- DRBD_MAX_EPOCH_SIZE_MIN, DRBD_MAX_EPOCH_SIZE_MAX);
- break;
- case 'b':
- cn->config.max_buffers = m_strtoll_range(optarg,1, "max-buffers",
- DRBD_MAX_BUFFERS_MIN, DRBD_MAX_BUFFERS_MAX);
- break;
- case 'u':
- cn->config.unplug_watermark = m_strtoll_range(optarg,1, "unplug-watermark",
- DRBD_UNPLUG_WATERMARK_MIN, DRBD_UNPLUG_WATERMARK_MAX);
- break;
- case 'c':
- cn->config.try_connect_int = m_strtoll_range(optarg,1, "connect-int",
- DRBD_CONNECT_INT_MIN, DRBD_CONNECT_INT_MAX);
- break;
- case 'i':
- cn->config.ping_int = m_strtoll_range(optarg,1, "ping-int",
- DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
- break;
- case 'S':
- cn->config.sndbuf_size = m_strtoll_range(optarg,1, "sndbuf-size",
- DRBD_SNDBUF_SIZE_MIN, DRBD_SNDBUF_SIZE_MAX);
- break;
- case 'k':
- cn->config.ko_count = m_strtoll_range(optarg,1, "ko-count",
- DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
- break;
- case 'm':
- cn->config.two_primaries = 1;
- break;
- case 'd':
- cn->config.on_disconnect = lookup_handler(optarg,dh_names);
- if( cn->config.on_disconnect == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid on-disconnect handler.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 'a':
- strncpy(cn->config.cram_hmac_alg,optarg,CRYPTO_MAX_ALG_NAME);
- break;
- case 'x':
- strncpy(cn->config.shared_secret,optarg,SHARED_SECRET_MAX);
- break;
- case 'A':
- cn->config.after_sb_0p = lookup_handler(optarg,asb0p_names);
- if( cn->config.after_sb_0p == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid after-sb-0pri handler.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 'B':
- cn->config.after_sb_1p = lookup_handler(optarg,asb1p_names);
- if( cn->config.after_sb_0p == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid after-sb-1pri handler.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 'C':
- cn->config.after_sb_2p = lookup_handler(optarg,asb2p_names);
- if( cn->config.after_sb_0p == -1U ) {
- fprintf(stderr,"%s: '%s' is an invalid after-sb-2pri handler.\n",
- cmdname,optarg);
- return 20;
- }
- break;
- case 'D':
- cn->config.want_lose = 1;
- break;
-
-
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
-
- /* sanity checks of the timeouts */
-
- if(cn->config.timeout >= cn->config.try_connect_int * 10 ||
- cn->config.timeout >= cn->config.ping_int * 10)
- {
- fprintf(stderr,"The timeout has to be smaller than "
- "connect-int and ping-int.\n");
- return 20;
- }
- return 0;
-}
-
-void print_config_ioctl_err(int err_no)
-{
- const char *etext[] = {
- [NoError]="No further Information available.",
- [LAAlreadyInUse]="Local address(port) already in use.",
- [OAAlreadyInUse]="Remote address(port) already in use.",
- [LDFDInvalid]="Filedescriptor for lower device is invalid.",
- [MDFDInvalid]="Filedescriptor for meta device is invalid.",
- [LDAlreadyInUse]="Lower device already in use.",
- [LDNoBlockDev]="Lower device is not a block device.",
- [MDNoBlockDev]="Meta device is not a block device.",
- [LDOpenFailed]="Open of lower device failed.",
- [MDOpenFailed]="Open of meta device failed.",
- [LDDeviceTooSmall]="Low.dev. smaller than requested DRBD-dev. size.",
- [MDDeviceTooSmall]="Meta device too small.",
- [LDNoConfig]="You have to use the disk command first.",
- [LDMounted]="Lower device is already mounted.",
- [MDMounted]="Meta device is already mounted.",
- [LDMDInvalid]="Lower device / meta device / index combination invalid.",
- [LDDeviceTooLarge]="Currently we only support devices up to 3.998TB.\n"
- "(up to 2TB in case you do not have CONFIG_LBD set)",
- "Contact office at linbit.com, if you need more.",
- [MDIOError]="IO error(s) orruced during initial access to meta-data.\n",
- [MDInvalid]="No valid meta-data signature found.\n"
- "Use 'drbdadm create-md res' to initialize meta-data area.\n",
- [CRAMAlgNotAvail]="The 'cram-hmac-alg' you specified is not known in "
- "the kernel.\n",
- [CRAMAlgNotDigest]="The 'cram-hmac-alg' you specified is not a digest.",
- [KMallocFailed]="kmalloc() failed. Out of memory?",
- [DiscardNotAllowed]="--discard-my-data not allowed when primary."
- };
-
- if (err_no<0 || (size_t)err_no>ARRY_SIZE(etext)) err_no=0;
- fprintf(stderr,"%s\n",etext[err_no]);
-}
-
-int check_if_blk_dev(int fd,const char* dev_name)
-{
- struct stat lower_stat;
- int err;
-
- err=fstat(fd, &lower_stat);
- if(err)
- {
- PERROR("fstat(%s) failed", dev_name);
- return 20;
- }
- if(!S_ISBLK(lower_stat.st_mode))
- {
- fprintf(stderr, "%s is not a block device!\n", dev_name);
- return 20;
- }
-
- return 0;
-}
-
-int do_disk_conf(int drbd_fd,
- const char* lower_dev_name,
- const char* meta_dev_name,
- struct ioctl_disk_config* cn)
-{
- int lower_device,meta_device,err;
-
- if(already_in_use(lower_dev_name))
- {
- fprintf(stderr,"Lower device (%s) is already mounted\n",lower_dev_name);
- return 20;
- }
-
- if((lower_device = open(lower_dev_name,O_RDWR))==-1)
- {
- PERROR("Can not open lower device '%s'", lower_dev_name);
- return 20;
- }
-
- err = check_if_blk_dev(lower_device,lower_dev_name);
- if(err) return err;
-
- if(!strcmp(meta_dev_name,"internal")) {
- meta_dev_name = lower_dev_name;
- }
-
- if((meta_device = open(meta_dev_name,O_RDWR))==-1)
- {
- PERROR("Can not open meta data device '%s'", meta_dev_name);
- return 20;
- }
-
- err = check_if_blk_dev(meta_device,meta_dev_name);
- if(err) return err;
-
- cn->config.lower_device=lower_device;
- cn->config.meta_device=meta_device;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_SET_DISK_CONFIG,cn);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,SET_DISK_CONFIG,) failed");
- if(err == EINVAL) print_config_ioctl_err(cn->ret_code);
- return 20;
- }
- return 0;
-}
-
-
-int do_net_conf(int drbd_fd,
- const char* proto,
- const char* local_addr,
- const char* remote_addr,
- struct ioctl_net_config* cn)
-{
- struct sockaddr_in *other_addr;
- struct sockaddr_in *my_addr;
- int err;
-
- if(proto[1] != 0)
- {
- fprintf(stderr,"Invalid protocol specifier '%s'.\n",proto);
- return 20;
- }
- switch(proto[0])
- {
- case 'a':
- case 'A':
- cn->config.wire_protocol = DRBD_PROT_A;
- break;
- case 'b':
- case 'B':
- cn->config.wire_protocol = DRBD_PROT_B;
- break;
- case 'c':
- case 'C':
- cn->config.wire_protocol = DRBD_PROT_C;
- break;
- default:
- fprintf(stderr,"Invalid protocol specifier '%s'.\n",proto);
- return 20;
- }
-
- cn->config.my_addr_len = sizeof(struct sockaddr_in);
- my_addr = (struct sockaddr_in *)cn->config.my_addr;
- my_addr->sin_port = htons(port_part(local_addr));
- my_addr->sin_family = AF_INET;
- my_addr->sin_addr.s_addr = resolv(addr_part(local_addr));
-
- cn->config.other_addr_len = sizeof(struct sockaddr_in);
- other_addr = (struct sockaddr_in *)cn->config.other_addr;
- other_addr->sin_port = htons(port_part(remote_addr));
- other_addr->sin_family = AF_INET;
- other_addr->sin_addr.s_addr = resolv(addr_part(remote_addr));
-
- err=ioctl(drbd_fd,DRBD_IOCTL_SET_NET_CONFIG,cn);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,SET_NET_CONFIG,) failed");
- if(err == EINVAL) print_config_ioctl_err(cn->ret_code);
- return 20;
- }
- return 0;
-}
-
-
-
-int set_state(int drbd_fd,drbd_role_t state)
-{
- int err, arg = state;
- err=ioctl(drbd_fd,DRBD_IOCTL_SET_STATE,&arg);
- if(err) {
- err=errno;
- PERROR("ioctl(,SET_STATE,) failed");
- switch(err)
- {
- case EBUSY:
- fprintf(stderr,"Someone has opened the device for RW access!\n");
- break;
- case EIO:
- fprintf(stderr,"%s\n", set_st_err_name(arg));
- break;
- }
- return 20;
- }
- return 0;
-}
-
-
-int cmd_primary(int drbd_fd,char** argv,int argc,struct option *options)
-{
- drbd_role_t newstate=Primary;
-
- if(argc > 0)
- {
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- /* --do-what-I-say have to be spelled out */
- c = getopt_long_only(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 'o':
- if (strcmp("--overwrite-data-of-peer",argv[optind-1])) {
- fprintf(stderr,"%s\nYou have to spell out --overwrite-data-of-peer, if you mean it\n",
- argv[optind-1]);
- return 20;
- }
- newstate |= DontBlameDrbd;
- break;
- case 'd':
- fprintf(stderr,
-"--do-what-I-say was renamed to --overwrite-data-of-peer, since that is\n"
-"less ambiguous.\n"
-"Only do it if you really know what you are doing. DRBD is going to save\n"
-"this fact to its metadata, and it will really overwrite the peer's copy\n"
-"of data with the local copy.\n");
- return 20;
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
- }
-
- return set_state(drbd_fd,newstate);
-}
-
-int cmd_secondary(int drbd_fd,char **argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- return set_state(drbd_fd,Secondary);
-}
-
-int wait_on(int drbd_fd,char** argv,int argc,int wfct,int dwfct, int req,
- struct option *options)
-{
- int err;
- struct ioctl_wait p;
-
- p.wfc_timeout=wfct;
- p.degr_wfc_timeout=dwfct;
-
- if(argc > 0)
- {
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- c = getopt_long(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 't':
- p.wfc_timeout = m_strtoll_range(optarg,1, "wfc-timeout",
- DRBD_WFC_TIMEOUT_MIN, DRBD_WFC_TIMEOUT_MAX);
- break;
- case 'd':
- p.degr_wfc_timeout = m_strtoll_range(optarg,1,
- "degr-wfc-timeout",
- DRBD_DEGR_WFC_TIMEOUT_MIN,
- DRBD_DEGR_WFC_TIMEOUT_MAX);
- break;
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
- }
- err=ioctl(drbd_fd,req,&p);
- if(errno == ETIME) exit(5);
- if(err)
- {
- PERROR("ioctl(,WAIT_*,) failed");
- exit(20);
- }
- return !p.ret_code;
-}
-
-int cmd_wait_connect(int drbd_fd,char** argv,int argc,struct option *options)
-{
- return wait_on(drbd_fd,argv,argc,
- DEF_WFC_TIMEOUT,
- DEF_DEGR_WFC_TIMEOUT,
- DRBD_IOCTL_WAIT_CONNECT,options);
-}
-
-int cmd_wait_sync(int drbd_fd,char** argv,int argc,struct option *options)
-{
- return wait_on(drbd_fd,argv,argc,
- DEF_SYNC_WFC_TIMEOUT,
- DEF_SYNC_DEGR_WFC_TIMEOUT,
- DRBD_IOCTL_WAIT_SYNC,options);
-}
-
-int cmd_syncer(int drbd_fd,char** argv,int argc,struct option *options)
-{
- struct ioctl_syncer_config cn;
- int err;
-
- /*
- struct ioctl_get_config current_cn;
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_CONFIG,¤t_cn);
- if(err)
- {
- PERROR("ioctl(,GET_CONFIG,) failed");
- return 20;
- }
-
- cn.config.rate = current_cn.sconf.rate;
- cn.config.after = current_cn.sconf.after;
- cn.config.al_extents = current_cn.sconf.al_extents;
- */
- cn.config.rate = DEF_SYNC_RATE;
- cn.config.after = DEF_SYNC_AFTER;
- cn.config.al_extents = DEF_SYNC_AL_EXTENTS;
-
-
- if(argc > 0)
- {
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- c = getopt_long(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 'r':
- cn.config.rate=m_strtoll_range(optarg,'K', "rate",
- DRBD_RATE_MIN, DRBD_RATE_MAX);
- break;
- case 'a':
- cn.config.after=m_strtoll(optarg,1);
- break;
- case 'e':
- cn.config.al_extents=m_strtoll_range(optarg,1, "al-extents",
- DRBD_AL_EXTENTS_MIN, DRBD_AL_EXTENTS_MAX);
- break;
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
- }
-
-
- if (cn.config.al_extents < 7)
- cn.config.al_extents = 127;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_SET_SYNC_CONFIG,&cn);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,SET_SYNC_CONFIG,) failed");
- if(err == EBADMSG) fprintf(stderr,"Sync-after cycle found!\n");
- if(err == ERANGE) fprintf(stderr,"Sync-after to small or big.\n");
- return 20;
- }
-
- return 0;
-}
-
-int cmd_pause_sync(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_PAUSE_SYNC);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,PAUSE_SYNC,) failed");
- if(err == EINPROGRESS) fprintf(stderr,"Pause flag is already set!\n");
- return 20;
- }
- return 0;
-}
-
-int cmd_resume_sync(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_RESUME_SYNC);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,RESUME_SYNC,) failed");
- if(err == EINPROGRESS) fprintf(stderr,"Pause flag is not set!\n");
- return 20;
- }
- return 0;
-}
-
-int cmd_invalidate(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_INVALIDATE);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,INVALIDATE,) failed");
- if(err==EINPROGRESS)
- fprintf(stderr,"Only in 'Connected' cstate possible.\n");
- return 20;
- }
- return 0;
-}
-
-int cmd_invalidate_rem(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_INVALIDATE_REM);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,INVALIDATE_REM,) failed");
- if(err==EINPROGRESS)
- fprintf(stderr,"Only in 'Connected' cstate possible.\n");
- return 20;
- }
- return 0;
-}
-
-int cmd_outdate(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
- int reason;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_OUTDATE_DISK,&reason);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,OUTDATE_DISK,) failed");
- if(err==EIO)
- {
- fprintf(stderr,"%s\n",set_st_err_name(reason));
- if(reason == SS_NoUpToDateDisk) return 17;
- }
- return 20;
- }
- return 0;
-}
-
-int cmd_down(int drbd_fd,char** argv,int argc,struct option *options)
-{
- int err;
- err = cmd_secondary(drbd_fd,argv,argc,options);
- if (!err) err = cmd_disconnect(drbd_fd,argv,argc,options);
- if (!err) err = cmd_detach(drbd_fd,argv,argc,options);
- return err;
-}
-
-int cmd_detach(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_UNCONFIG_DISK);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,UNCONFIG_DISK,) failed");
- if(err==EBUSY)
- fprintf(stderr,"Not possible during resynchronisation.\n");
- if(err==ENETRESET)
- fprintf(stderr,"Not possible, since the device is in primary state\n"
- "and not connected.\n");
- if(err==ENODATA)
- fprintf(stderr,"Not possible, since the device is in primary state\n"
- "and has no local disk.\n");
- if(err==ENXIO)
- fprintf(stderr," - Do not shoot yourself in the foot. -\n"
- "A system without backing storage is not possible.\n");
- return 20;
- }
- return 0;
-}
-
-int cmd_disconnect(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_UNCONFIG_NET);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,UNCONFIG_NET,) failed");
- if(err==ENXIO)
- fprintf(stderr,"Device is not configured!\n");
- return 20;
- }
- return 0;
-
-}
-
-int cmd_net_conf(int drbd_fd,char** argv,int argc,struct option *options)
-{
- struct ioctl_net_config cn;
- int retval;
-
- retval=scan_net_options(argv,argc,&cn,options);
- if(retval) return retval;
-
- return do_net_conf(drbd_fd,argv[5],argv[3],argv[4],&cn);
-}
-
-int cmd_disk_conf(int drbd_fd, char **argv, int argc, struct option *options)
-{
- struct ioctl_disk_config cn;
- int retval, mi = 0;
-
- retval = scan_disk_options(argv, argc, &cn, options);
- if (retval)
- return retval;
-
- if (argc == 5) {
- /* short variant, index and other options omitted */
- if (!strcmp("internal", argv[4])) {
- mi = DRBD_MD_INDEX_FLEX_INT;
- } else {
- fprintf(stderr, "meta_index missing.\n");
- }
- } else {
- /* index or any options given. check the index */
- if (!strcmp("internal", argv[4])) {
- /* in drbd8, internal is always flexible */
- if (!strncmp("flex", argv[5], 4) ||
- !strcmp("-1", argv[5]) ||
- !strcmp("internal", argv[5]))
- {
- mi = DRBD_MD_INDEX_FLEX_INT;
- } else {
- fprintf(stderr, "invalid meta_index for 'internal'.\n");
- return 20;
- }
- } else {
- if (!strncmp("flex", argv[5], 4)) {
- mi = DRBD_MD_INDEX_FLEX_EXT;
- } else {
- mi = m_strtoll(argv[5], 1);
- if (mi < 0) {
- fprintf(stderr, "meta_index may not be negative.\n");
- return 20;
- }
- }
- }
- }
- //FIXME check that mi*128M is not bigger than meta device!
- cn.config.meta_index = mi;
- return do_disk_conf(drbd_fd, argv[3], argv[4], &cn);
-}
-
-int cmd_disk_size(int drbd_fd,char** argv,int argc,struct option *options)
-{
- __u64 u_size=0; // unit: sectors.
- int err;
-
- if(argc > 0)
- {
- while(1)
- {
- int c;
-
- PRINT_ARGV;
- c = getopt_long(argc,argv,make_optstring(options,'-'),options,0);
- if(c == -1) break;
- switch(c)
- {
- case 'd':
- u_size=m_strtoll_range(optarg,'K', "size",
- DRBD_DISK_SIZE_SECT_MIN>>1,
- DRBD_DISK_SIZE_SECT_MAX>>1 ) << 1;
- break;
- case 1: // non option argument. see getopt_long(3)
- fprintf(stderr,"%s: Unexpected nonoption argument '%s'\n",cmdname,optarg);
- case '?':
- return 20;
- }
- }
- }
-
- err=ioctl(drbd_fd,DRBD_IOCTL_SET_DISK_SIZE,u_size);
- if(err)
- {
- PERROR("ioctl(,SET_DISK_SIZE,) failed");
- if(err==EBUSY) {
- fprintf(stderr,"Online resizing is not allowed during resync.");
- }
- if(err==EINPROGRESS) {
- fprintf(stderr,"One node must be primary to do online resizing.");
- }
- return 20;
- }
-
- return 0;
-}
-
-const char* guess_dev_name(const char* dir,unsigned int g_major,unsigned int g_minor)
-{
- DIR* device_dir;
- struct dirent* dde;
- struct stat sb;
- static char dev_name[50];
-
- device_dir=opendir(dir);
-
- if(!device_dir) goto err_out;
-
- while((dde=readdir(device_dir)))
- {
- snprintf(dev_name,50,"%s/%s",dir,dde->d_name);
- if(stat(dev_name,&sb)) continue;
-
- if(S_ISBLK(sb.st_mode))
- {
- if (g_major == major(sb.st_rdev) &&
- g_minor == minor(sb.st_rdev) )
- {
- closedir(device_dir);
- return dev_name;
- }
- }
- }
-
- rewinddir(device_dir);
-
- while((dde=readdir(device_dir)))
- {
- snprintf(dev_name,50,"%s/%s",dir,dde->d_name);
- if(stat(dev_name,&sb)) continue;
-
- if(!strcmp(dde->d_name,".")) continue;
- if(!strcmp(dde->d_name,"..")) continue;
- if(!strcmp(dde->d_name,"fd")) continue;
- if(!strcmp(dde->d_name,"shm")) continue;
- if(S_ISLNK(sb.st_mode)) continue;
-
- if(S_ISDIR(sb.st_mode))
- {
- char subdir[50];
-
- if(snprintf(subdir,50,"%s/%s",dir,dde->d_name)==49)
- { /* recursion is too deep */
- strcpy(dev_name,"can not guess name");
- return dev_name;
- }
-
- if(guess_dev_name(subdir,g_major,g_minor)) return dev_name;
- }
- }
-
- closedir(device_dir);
- err_out:
- return NULL;
-}
-
-const char* check_dev_name(const char* dev_name , int major, int minor)
-{
- // this is because the SmartArray (Compaq, HP, whatever...) driver
- // returns a closing bracket in the device name...
-
- if(!dev_name || !dev_name[0] || index(dev_name,')') )
- {
- dev_name = guess_dev_name("/dev",major,minor);
- }
- if(dev_name) return dev_name;
- else return "n.a.";
-}
-
-int cmd_show(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_config cn;
- struct sockaddr_in *other_addr;
- struct sockaddr_in *my_addr;
- struct stat sb;
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_CONFIG,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_CONFIG,) failed");
- return 20;
- }
-
-#define SHOW_I(T,U,M,D) \
-printf("\t" T "\t%d",M); \
-if(M==D) printf(" _is_default"); \
-printf("; \t# " U "\n")
-
-#define SHOW_IU(T,U1,U2,M,D) \
-printf("\t" T "\t%d"U1,M); \
-if(M==D) printf(" _is_default"); \
-printf("; \t# " U2 "\n")
-
-#define SHOW_H(T,M,D,H) \
-printf("\t" T "\t%s",H[M]); \
-if(M==D) printf(" _is_default"); \
-printf(";\n")
-
-#define SHOW_S(T,M,D) \
-printf("\t" T "\t\"%s\"",M); \
-if(!strcmp(M,D)) printf(" _is_default"); \
-printf(";\n")
-
- if( cn.state.disk == Diskless && cn.state.conn == StandAlone)
- {
- printf("# not configured.\n");
- }
-
- if( cn.state.disk > Diskless)
- {
- printf("disk {\n");
- SHOW_H("on-io-error",cn.on_io_error,DEF_ON_IO_ERROR,eh_names);
- SHOW_H("fencing\t",cn.fencing,DEF_FENCING,fencing_names);
- if( cn.disk_size_user ) printf("\tsize\t%luK;\n",
- (unsigned long)cn.disk_size_user);
- printf("}\n");
- }
-
- if( cn.state.conn > StandAlone)
- {
- printf("protocol %c;\n",'A'-1+cn.nconf.wire_protocol);
- printf("net {\n");
- SHOW_I("timeout\t","1/10 seconds",cn.nconf.timeout,DEF_NET_TIMEOUT);
- SHOW_I("connect-int","seconds", cn.nconf.try_connect_int, DEF_NET_TRY_CON_I);
- SHOW_I("ping-int","seconds", cn.nconf.ping_int, DEF_NET_PING_I);
- SHOW_I("max-epoch-size","write requests", cn.nconf.max_epoch_size, DEF_MAX_EPOCH_SIZE);
- SHOW_I("max-buffers","pages", cn.nconf.max_buffers, DEF_MAX_BUFFERS);
- SHOW_I("unplug-watermark","write requests", cn.nconf.unplug_watermark, DEF_UNPLUG_WATERMARK);
- SHOW_I("sndbuf-size","byte", cn.nconf.sndbuf_size, DEF_SNDBUF_SIZE);
- SHOW_I("ko-count","1", cn.nconf.ko_count, DEF_KO_COUNT);
- // SHOW_H("on-disconnect",cn.nconf.on_disconnect,DEF_ON_DISCONNECT,dh_names);
- SHOW_H("after-sb-0pri",cn.nconf.after_sb_0p,DEF_AFTER_SB_0P,asb0p_names);
- SHOW_H("after-sb-1pri",cn.nconf.after_sb_1p,DEF_AFTER_SB_0P,asb1p_names);
- SHOW_H("after-sb-2pri",cn.nconf.after_sb_2p,DEF_AFTER_SB_0P,asb2p_names);
- SHOW_S("cram-hmac-alg",cn.nconf.cram_hmac_alg,"");
- SHOW_S("shared-secret",cn.nconf.shared_secret,"");
- if( cn.nconf.two_primaries ) printf("\tallow-two-primaries;\n");
- if( cn.nconf.want_lose ) printf("\tdiscard-my-data;\n");
- printf("}\n");
- }
-
- if( cn.state.disk > Diskless || cn.state.conn > StandAlone)
- {
- printf("syncer {\n");
- SHOW_IU("rate\t","K","(K)Byte/second", cn.sconf.rate, DEF_SYNC_RATE);
- SHOW_I("after\t","minor", cn.sconf.after, DEF_SYNC_AFTER);
- SHOW_I("al-extents","4MByte", cn.sconf.al_extents, DEF_SYNC_AL_EXTENTS);
- printf("}\n");
-
- err=fstat(drbd_fd,&sb);
- if(err)
- {
- PERROR("fstat() failed");
- return 20;
- }
- printf("_this_host {\n");
- printf("\tdevice\t\t\"/dev/drbd%d\";\n",minor(sb.st_rdev));
- printf("\tdisk\t\t\"/dev/%s\" _major %d _minor %d;\n",
- check_dev_name(cn.lower_device_name,cn.lower_device_major,
- cn.lower_device_minor),
- cn.lower_device_major,
- cn.lower_device_minor);
-
- if( cn.lower_device_major == cn.meta_device_major &&
- cn.lower_device_minor == cn.meta_device_minor ) {
- printf("\tmeta-disk\tinternal;\n");
- } else {
- if( cn.meta_index == DRBD_MD_INDEX_FLEX_EXT ) {
- printf("\tflexible-meta-disk\t\"%s\" _major %d _minor %d;\n",
- check_dev_name(cn.meta_device_name,cn.meta_device_major,
- cn.meta_device_minor),
- cn.meta_device_major,
- cn.meta_device_minor);
- } else {
- printf("\tmeta-disk\t\"%s\" [%d] _major %d _minor %d;\n",
- check_dev_name(cn.meta_device_name,cn.meta_device_major,
- cn.meta_device_minor),
- cn.meta_index,
- cn.meta_device_major,
- cn.meta_device_minor);
- }
- }
-
- if( cn.state.conn > StandAlone) {
- my_addr = (struct sockaddr_in *)cn.nconf.my_addr;
- printf("\taddress\t\t%s:%d;\n",
- inet_ntoa(my_addr->sin_addr),
- ntohs(my_addr->sin_port));
- }
- printf("}\n");
- }
-
- if( cn.state.conn > StandAlone)
- {
- other_addr = (struct sockaddr_in *)cn.nconf.other_addr;
- printf("_remote_host {\n");
- printf("\taddress\t%s:%d;\n",
- inet_ntoa(other_addr->sin_addr),
- ntohs(other_addr->sin_port));
- printf("}\n");
- }
-
- return 0;
-}
-
-int cmd_state(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_config cn;
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_CONFIG,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_CONFIG,) failed");
- return 20;
- }
-
- if( cn.state.conn == StandAlone && cn.state.disk == Diskless)
- {
- fprintf(stderr,"Not configured\n");
- return 10;
- }
-
- printf("%s/%s\n",roles_to_name(cn.state.role),
- roles_to_name(cn.state.peer));
-
- return 0;
-}
-
-int cmd_cstate(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_config cn;
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_CONFIG,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_CONFIG,) failed");
- return 20;
- }
-
- if( cn.state.conn == StandAlone && cn.state.disk == Diskless)
- {
- fprintf(stderr,"Not configured\n");
- return 10;
- }
-
- printf("%s\n",conns_to_name(cn.state.conn));
-
- return 0;
-}
-
-int cmd_dstate(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_config cn;
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_CONFIG,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_CONFIG,) failed");
- return 20;
- }
-
- if( cn.state.conn == StandAlone && cn.state.disk == Diskless)
- {
- fprintf(stderr,"Not configured\n");
- return 10;
- }
-
- printf("%s/%s\n",disks_to_name(cn.state.disk),disks_to_name(cn.state.pdsk));
-
- return 0;
-}
-
-int cmd_get_gi(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_uuids cn;
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_UUIDS,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_GEN_UUIDS,) failed");
- return 20;
- }
-
- dt_print_uuids(cn.uuid, cn.flags);
-
- return 0;
-}
-
-int cmd_show_gi(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- struct ioctl_get_uuids cn;
- char ppb[10];
- int err;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_GET_UUIDS,&cn);
- if(err)
- {
- PERROR("ioctl(,GET_GEN_UUIDS,) failed");
- return 20;
- }
-
- dt_pretty_print_uuids(cn.uuid, cn.flags);
-
- printf("current agreed size: %s\n", ppsize(ppb, cn.current_size >> 1));
- printf("%u bits set in the bitmap [ %s out of sync ]\n",
- cn.bits_set, ppsize(ppb, cn.bits_set * 4));
-
- return 0;
-}
-
-int cmd_suspend_io(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
- int reason;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_SUSPEND_IO, &reason);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,DRBD_IOCTL_SUSPEND_IO) failed");
- if(err==EIO)
- {
- fprintf(stderr,"%s\n",set_st_err_name(reason));
- }
- return 20;
- }
-
- return 0;
-}
-
-int cmd_resume_io(int drbd_fd,char** argv __attribute((unused)),int argc __attribute((unused)),struct option *options __attribute((unused)))
-{
- int err;
- int reason;
-
- err=ioctl(drbd_fd,DRBD_IOCTL_RESUME_IO, &reason);
- if(err)
- {
- err=errno;
- PERROR("ioctl(,DRBD_IOCTL_RESUME_IO) failed");
- if(err==EIO)
- {
- fprintf(stderr,"%s\n",set_st_err_name(reason));
- }
- return 20;
- }
-
- return 0;
-}
-
-int main(int argc, char** argv)
-{
- int drbd_fd;
- int num_of_args;
- int help = 0;
- int err;
- size_t i;
- char **args;
-
- if ( (cmdname = strrchr(argv[0],'/')) )
- argv[0] = ++cmdname;
- else
- cmdname = argv[0];
-
- /* == '-' catches -h, --help, and similar */
- if (argc > 1 && (!strcmp(argv[1],"help") || argv[1][0] == '-'))
- help = 1;
- if (argc < 3) print_usage(argc==1 ? 0 : " Insufficient arguments");
-
- chdir("/");
-
- for(i=0;i<ARRY_SIZE(commands);i++)
- {
- if(strcmp(argv[2],commands[i].cmd)==0)
- {
- num_of_args=0;
- if((args=commands[i].args))
- {
- while(*args++) num_of_args++;
- }
- if (0 == strcmp(argv[2],"disk") && (argc == 5) &&
- 0 == strcmp(argv[4],"internal") ) {
- --num_of_args;
- /* don't require that stupid "-1" */
- }
- if (help || argc-3 < num_of_args)
- print_command_usage(i,help?"":"Not enough arguments.");
- if (argc-3-num_of_args>0 && commands[i].options==0)
- {
- fprintf(stderr,"Too many arguments or options.\n");
- return 20;
- }
-
- if (strncmp ("/dev/drbd", argv[1], 9))
- {
- fprintf (stderr,
- " | NOTE: we now have officially asigned"
- " device name and major number.\n"
- " | Please use /dev/drbd*; if neccessary"
- " create the device nodes first.\n"
- " | To do so: for i in `seq 0 15` ;"
- " do mknod -m 0660 /dev/drbd$i b 147 $i; done\n");
- }
- drbd_fd=open_drbd_device(argv[1]);
-
- opterr = 1; /* let getopt() print error messages */
- optind = 3+num_of_args;
- err = commands[i].function(drbd_fd,argv,argc,
- commands[i].options);
- close(drbd_fd); // explicit close on drbd device!
- return err;
- }
- }
- fprintf(stderr,"%s is not a command\n",argv[2]);
- return 20;
-}
Modified: trunk/user/drbdsetup_nl.c
===================================================================
--- trunk/user/drbdsetup_nl.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbdsetup_nl.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -28,29 +28,40 @@
#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <mntent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+
+#include <linux/netlink.h>
+#include <linux/connector.h>
+
#include <linux/drbd.h>
#include <linux/drbd_config.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <mntent.h>
+#include <linux/drbd_tag_magic.h>
+#include <linux/drbd_limits.h>
+
#include "drbdtool_common.h"
-#include "drbd_limits.h"
-#include "drbd_tag_magic.h"
+
+
struct drbd_tag_list {
+ struct nlmsghdr *nl_header;
+ struct cn_msg *cn_header;
+ struct drbd_nl_cfg_req* drbd_p_header;
unsigned short *tag_list_start;
unsigned short *tag_list_cpos;
int tag_size;
@@ -71,6 +82,7 @@
int (*convert_function)(struct drbd_option *,
struct drbd_tag_list *,
char *);
+ void (*show_function)(struct drbd_option *,unsigned short*);
union {
struct {
const unsigned long long min;
@@ -81,6 +93,7 @@
struct {
const char** handler_names;
const int number_of_handlers;
+ const int def;
} handler_param;
};
};
@@ -88,12 +101,41 @@
struct drbd_cmd {
const char* cmd;
const int packet_id;
- int (*function)(struct drbd_cmd *, int, char **);
+ int (*function)(struct drbd_cmd *, int, int, char **);
struct drbd_argument *args;
struct drbd_option *options;
};
+// Connector functions
+int open_cn();
+int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
+int send_tag_list_cn(int, struct drbd_tag_list *, const int, int, int);
+int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
+void close_cn(int sk_nl);
+
+// other functions
+void print_command_usage(int i, const char *addinfo);
+// command functions
+int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
+int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
+// convert functions for arguments
+int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+// convert functions for options
+int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+// show functions for options
+void show_numeric(struct drbd_option *od, unsigned short* tp);
+void show_handler(struct drbd_option *od, unsigned short* tp);
+void show_bit(struct drbd_option *od, unsigned short* tp);
+void show_string(struct drbd_option *od, unsigned short* tp);
+
+
const char *on_error[] = {
[PassOn] = "pass_on",
[Panic] = "panic",
@@ -127,35 +169,21 @@
[PanicPrimary] = "panic"
};
-// other functions
-void print_command_usage(int i, const char *addinfo);
-// command functions
-int generic_config_cmd(struct drbd_cmd *cm, int argc, char **argv);
-// convert functions for arguments
-int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-// convert functions for options
-int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-
#define EN(N) \
- conv_numeric, { .numeric_param = { N ## _min, N ## _max, N ## _default } }
-#define EN0 conv_numeric, { .numeric_param = { 0, -1, 0, 0 } }
-#define EH(N) \
- conv_handler, { .handler_param = { N, ARRY_SIZE(N) } }
-#define EB conv_bit, { }
+ conv_numeric, show_numeric, \
+ { .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \
+ DRBD_ ## N ## _DEF ,0 } }
+#define EH(N,D) \
+ conv_handler, show_handler, { .handler_param = { N, ARRY_SIZE(N), \
+ DRBD_ ## D ## _DEF } }
+#define EB conv_bit, show_bit, { }
+#define ES conv_string, show_string, { }
-
-
-
struct drbd_cmd commands[] = {
{"primary", P_primary, generic_config_cmd, NULL,
(struct drbd_option[]) {
- { "overwrite-data-of-peer",'o',T_disk_size, EB },
- { NULL,0,0,NULL, { } }, }, },
+ { "overwrite-data-of-peer",'o',T_overwrite_peer, EB },
+ { NULL,0,0,NULL,NULL, { } }, }, },
{"secondary", P_secondary, generic_config_cmd, NULL, NULL },
@@ -166,10 +194,10 @@
{ "meta_data_index", T_meta_dev_idx, conv_md_idx },
{ NULL, 0, NULL}, },
(struct drbd_option[]) {
- { "size",'d', T_disk_size, EN0 },
- { "on-io-error",'e', T_on_io_error, EH(on_error) },
- { "fencing",'f', T_fencing, EH(fencing_n) },
- { NULL,0,0,NULL, { } }, }, },
+ { "size",'d', T_disk_size, EN(DISK_SIZE_SECT) },
+ { "on-io-error",'e', T_on_io_error, EH(on_error,ON_IO_ERROR) },
+ { "fencing",'f', T_fencing, EH(fencing_n,FENCING) },
+ { NULL,0,0,NULL,NULL, { } }, }, },
{"detach", P_detach, generic_config_cmd, NULL, NULL },
@@ -180,36 +208,36 @@
{ "protocol", T_wire_protocol,conv_protocol },
{ NULL, 0, NULL}, },
(struct drbd_option[]) {
- { "timeout",'t', T_timeout, EN0 },
- { "max-epoch-size",'e',T_max_epoch_size,EN0 },
- { "max-buffers",'b', T_max_buffers, EN0 },
- { "unplug-watermark",'u',T_unplug_watermark, EN0 },
- { "connect-int",'c', T_try_connect_int, EN0 },
- { "ping-int",'i', T_ping_int, EN0 },
- { "sndbuf-size",'S', T_sndbuf_size, EN0 },
- { "ko-count",'k', T_ko_count, EN0 },
+ { "timeout",'t', T_timeout, EN(TIMEOUT) },
+ { "max-epoch-size",'e',T_max_epoch_size,EN(MAX_EPOCH_SIZE) },
+ { "max-buffers",'b', T_max_buffers, EN(MAX_BUFFERS) },
+ { "unplug-watermark",'u',T_unplug_watermark, EN(UNPLUG_WATERMARK) },
+ { "connect-int",'c', T_try_connect_int, EN(CONNECT_INT) },
+ { "ping-int",'i', T_ping_int, EN(PING_INT) },
+ { "sndbuf-size",'S', T_sndbuf_size, EN(SNDBUF_SIZE) },
+ { "ko-count",'k', T_ko_count, EN(KO_COUNT) },
{ "allow-two-primaries",'m',T_two_primaries, EB },
- { "cram-hmac-alg",'a', T_cram_hmac_alg, EN0 },
- { "shared-secret",'x', T_shared_secret, EN0 },
- { "after-sb-0pri",'A', T_after_sb_0p, EH(asb0p_n) },
- { "after-sb-1pri",'B', T_after_sb_1p, EH(asb1p_n) },
- { "after-sb-2pri",'C', T_after_sb_2p, EH(asb2p_n) },
+ { "cram-hmac-alg",'a', T_cram_hmac_alg, ES },
+ { "shared-secret",'x', T_shared_secret, ES },
+ { "after-sb-0pri",'A', T_after_sb_0p,EH(asb0p_n,AFTER_SB_0P) },
+ { "after-sb-1pri",'B', T_after_sb_1p,EH(asb1p_n,AFTER_SB_1P) },
+ { "after-sb-2pri",'C', T_after_sb_2p,EH(asb2p_n,AFTER_SB_2P) },
{ "discard-my-data",'D', T_want_lose, EB },
- { NULL,0,0,NULL, { } }, }, },
+ { NULL,0,0,NULL,NULL, { } }, }, },
{"disconnect", P_disconnect, generic_config_cmd, NULL, NULL },
{"resize", P_resize, generic_config_cmd, NULL,
(struct drbd_option[]) {
- { "size",'s',T_resize_size, EN0 },
- { NULL,0,0,NULL, { } }, }, },
+ { "size",'s',T_resize_size, EN(DISK_SIZE_SECT) },
+ { NULL,0,0,NULL,NULL, { } }, }, },
{"syncer", P_syncer_conf, generic_config_cmd, NULL,
(struct drbd_option[]) {
- { "rate",'r',T_sync_rate, EN0 },
- { "after",'a',T_sync_after, EN0 },
- { "al-extents",'e',T_al_extents, EN0 },
- { NULL,0,0,NULL, { } }, }, },
+ { "rate",'r',T_rate, EN(RATE) },
+ { "after",'a',T_after, EN(AFTER) },
+ { "al-extents",'e',T_al_extents, EN(AL_EXTENTS) },
+ { NULL,0,0,NULL,NULL, { } }, }, },
{"invalidate", P_invalidate, generic_config_cmd, NULL, NULL },
{"invalidate-remote", P_invalidate_peer, generic_config_cmd, NULL, NULL },
@@ -226,28 +254,80 @@
{"cstate", cmd_cstate, 0, 0, },
{"dstate", cmd_dstate, 0, 0, },
{"show-gi", cmd_show_gi, 0, 0, },
- {"get-gi", cmd_get_gi, 0, 0, },
- {"show", cmd_show, 0, 0, },
- */
+ {"get-gi", cmd_get_gi, 0, 0, }, */
+ {"show", P_get_config, show_cmd, NULL, NULL },
};
+#define EM(C) [ C - RetCodeBase ]
+
+static const char *error_messages[] = {
+ EM(NoError) = "No further Information available.",
+ EM(LAAlreadyInUse) = "Local address(port) already in use.",
+ EM(OAAlreadyInUse) = "Remote address(port) already in use.",
+ EM(LDNameInvalid) = "Can not open backing device.",
+ EM(MDNameInvalid) = "Can not open meta device.",
+ EM(LDAlreadyInUse) = "Lower device already in use.",
+ EM(LDNoBlockDev) = "Lower device is not a block device.",
+ EM(MDNoBlockDev) = "Meta device is not a block device.",
+ EM(LDOpenFailed) = "Open of lower device failed.",
+ EM(MDOpenFailed) = "Open of meta device failed.",
+ EM(LDDeviceTooSmall) = "Low.dev. smaller than requested DRBD-dev. size.",
+ EM(MDDeviceTooSmall) = "Meta device too small.",
+ EM(LDNoConfig) = "You have to use the disk command first.",
+ EM(LDMounted) = "Lower device is already mounted.",
+ EM(MDMounted) = "Meta device is already mounted.",
+ EM(LDMDInvalid) = "Lower device / meta device / index combination invalid.",
+ EM(LDDeviceTooLarge) = "Currently we only support devices up to 3.998TB.\n"
+ "(up to 2TB in case you do not have CONFIG_LBD set)"
+ "Contact office at linbit.com, if you need more.",
+ EM(MDIOError) = "IO error(s) orruced during initial access to meta-data.\n",
+ EM(MDInvalid) = "No valid meta-data signature found.\n)"
+ "Use 'drbdadm create-md res' to initialize meta-data area.\n",
+ EM(CRAMAlgNotAvail) = "The 'cram-hmac-alg' you specified is not known in )"
+ "the kernel.\n",
+ EM(CRAMAlgNotDigest) = "The 'cram-hmac-alg' you specified is not a digest.",
+ EM(KMallocFailed) = "kmalloc() failed. Out of memory?",
+ EM(DiscardNotAllowed) = "--discard-my-data not allowed when primary.",
+ EM(HaveDiskConfig) = "HaveDiskConfig",
+ EM(UnknownMandatoryTag) = "UnknownMandatoryTag",
+ EM(MinorNotKnown) = "MinorNotKnown",
+ EM(StateNotAllowed) = "StateNotAllowed",
+ EM(GotSignal) = "GotSignal",
+ EM(NoResizeDuringResync) = "Resize not allowed during resync.",
+ EM(APrimaryNodeNeeded) = "Need the a primary node to resize.",
+ EM(SyncAfterInvalid) = "The sync after minor number is invalid",
+ EM(SyncAfterCycle-) = "This would cause a sync-after dependency cycle",
+ EM(PauseFlagAlreadySet) = "PauseFlagAlreadySet",
+ EM(PauseFlagAlreadyClear) = "PauseFlagAlreadyClear",
+ EM(DiskLowerThanOutdated) = "DiskLowerThanOutdated",
+ EM(FailedToClaimMyself) = "FailedToClaimMyself",
+};
+
char* cmdname = 0;
-void dump_tag_list(struct drbd_tag_list *tl)
+int dump_tag_list(unsigned short *tlc)
{
- unsigned short *tlc = tl->tag_list_start;
enum drbd_tags tag;
+ unsigned int tag_nr;
int len;
int integer;
char bit;
__u64 int64;
char* string;
+ int found_unknown=0;
- while(*tlc != TT_END) {
- tag = *tlc++;
- printf("(%2d) %16s = ",tag_number(tag),
- tag_descriptions[tag_number(tag)].name);
+ while( (tag = *tlc++ ) != TT_END) {
len = *tlc++;
+ if(tag == TT_REMOVED) goto skip;
+
+ tag_nr = tag_number(tag);
+ if(tag_nr<ARRY_SIZE(tag_descriptions)) {
+ string = tag_descriptions[tag_nr].name;
+ } else {
+ string = "unknown tag";
+ found_unknown=1;
+ }
+ printf("# (%2d) %16s = ",tag_nr,string);
switch(tag_type(tag)) {
case TT_INTEGER:
integer = *(int*)tlc;
@@ -267,16 +347,24 @@
break;
}
printf(" \t[len: %u]\n",len);
+ skip:
tlc = (unsigned short*)((char*)tlc + len);
}
+
+ return found_unknown;
}
struct drbd_tag_list *create_tag_list(int size)
{
struct drbd_tag_list *tl;
-
+
tl = malloc(sizeof(struct drbd_tag_list));
- tl->tag_list_start = malloc(size);
+ tl->nl_header = malloc(NLMSG_SPACE( sizeof(struct cn_msg) +
+ sizeof(struct drbd_nl_cfg_req) +
+ size) );
+ tl->cn_header = NLMSG_DATA(tl->nl_header);
+ tl->drbd_p_header = (struct drbd_nl_cfg_req*) tl->cn_header->data;
+ tl->tag_list_start = tl->drbd_p_header->tag_list;
tl->tag_list_cpos = tl->tag_list_start;
tl->tag_size = size;
@@ -298,7 +386,7 @@
void free_tag_list(struct drbd_tag_list *tl)
{
- free(tl->tag_list_start);
+ free(tl->nl_header);
free(tl);
}
@@ -322,8 +410,10 @@
fprintf(stderr, "%s is not a block device!\n", arg);
return 20;
}
+
+ close(device_fd);
- add_tag(tl,ad->tag,&device_fd,sizeof(device_fd));
+ add_tag(tl,ad->tag,arg,strlen(arg)+1); // include the null byte.
return 0;
}
@@ -391,18 +481,7 @@
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = resolv(addr_part(arg));
- switch(ad->tag) {
- case T_my_addr:
- add_tag(tl,T_my_addr,&addr,addr_len);
- add_tag(tl,T_my_addr_len,&addr_len,sizeof(addr_len));
- break;
- case T_peer_addr:
- add_tag(tl,T_peer_addr,&addr,addr_len);
- add_tag(tl,T_peer_addr_len,&addr_len,sizeof(addr_len));
- break;
- default:
- fprintf(stderr, "internal error in conv_address()\n");
- }
+ add_tag(tl,ad->tag,&addr,addr_len);
return 0;
}
@@ -445,7 +524,6 @@
int i;
char unit[] = {0,0};
-
l = m_strtoll(arg, default_unit);
if (min > l || l > max) {
@@ -488,12 +566,19 @@
return 0;
}
+int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
+{
+ add_tag(tl,od->tag,arg,strlen(arg)+1);
+
+ return 0;
+}
+
struct option * make_longoptions(struct drbd_option* od)
{
static struct option buffer[20];
int i=0;
- while(od->name) {
+ while(od && od->name) {
buffer[i].name = od->name;
buffer[i].has_arg = tag_type(od->tag) == TT_BIT ?
no_argument : required_argument ;
@@ -504,6 +589,20 @@
}
od++;
}
+
+ // The two omnipresent options:
+ buffer[i].name = "set-defaults";
+ buffer[i].has_arg = 0;
+ buffer[i].flag = NULL;
+ buffer[i].val = '(';
+ i++;
+
+ buffer[i].name = "create-device";
+ buffer[i].has_arg = 0;
+ buffer[i].flag = NULL;
+ buffer[i].val = ')';
+ i++;
+
buffer[i].name = NULL;
buffer[i].has_arg = 0;
buffer[i].flag = NULL;
@@ -522,17 +621,44 @@
return NULL;
}
-int generic_config_cmd(struct drbd_cmd *cm, int argc, char **argv)
+void print_config_error( struct drbd_nl_cfg_reply *reply)
{
+ int err_no = reply->ret_code;
+
+ if (err_no == NoError) return;
+ if (err_no == SS_Success) return;
+
+ if ( ( err_no >= AfterLastRetCode || err_no <= RetCodeBase ) &&
+ ( err_no > SS_TowPrimaries || err_no < SS_CW_FailedByPeer) ) {
+ fprintf(stderr,"Error code %d unknown.\n"
+ "You should updated the drbd userland tools.\n",err_no);
+ } else {
+ if(err_no > RetCodeBase ) {
+ fprintf(stderr,"Failure: (%d) %s\n",err_no,
+ error_messages[err_no-RetCodeBase]);
+ } else {
+ fprintf(stderr,"State change failed: (%d) %s\n",
+ err_no, set_st_err_name(err_no));
+ }
+ }
+}
+
+#define RCV_SIZE NLMSG_SPACE(sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply))
+
+int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
+{
+ char buffer[ RCV_SIZE ];
+ struct drbd_nl_cfg_reply *reply;
struct drbd_argument *ad = cm->args;
struct drbd_option *od;
static struct option *lo;
struct drbd_tag_list *tl;
- int c,i=0,rv=0;
+ int c,i=0,rv=0,sk_nl;
+ int flags=0;
tl = create_tag_list(4096);
- while(ad->name) {
+ while(ad && ad->name) {
if(argc < i+1) {
fprintf(stderr,"Missing argument '%s'\n", ad->name);
print_command_usage(cm-commands, "");
@@ -545,23 +671,245 @@
}
lo = make_longoptions(cm->options);
+ opterr=0;
while( (c=getopt_long(argc,argv,make_optstring(lo,0),lo,0)) != -1 ) {
od = find_opt_by_short_name(cm->options,c);
if(od) rv |= od->convert_function(od,tl,optarg);
else {
- fprintf(stderr,"opt for short '%c' (%d) not found\n",
- c,c);
- rv=20;
+ if(c=='(') flags |= DRBD_NL_SET_DEFAULTS;
+ else if(c==')') flags |= DRBD_NL_CREATE_DEVICE;
+ else {
+ fprintf(stderr,
+ "%s: unrecognized option '%s'\n",
+ cmdname, argv[optind-1]);
+ rv=20;
+ }
}
if(rv) break;
}
- if(rv == 0) dump_tag_list(tl);
+ add_tag(tl,TT_END,NULL,0); // close the tag list
+
+ if(rv == 0) {
+ // dump_tag_list(tl->tag_list_start);
+ sk_nl = open_cn();
+ if(sk_nl < 0) return 20;
+
+ send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,flags);
+
+ receive_cn(sk_nl, (struct nlmsghdr*)buffer, RCV_SIZE );
+ close_cn(sk_nl);
+ reply = (struct drbd_nl_cfg_reply *)
+ ((struct cn_msg *)NLMSG_DATA(buffer))->data;
+ print_config_error(reply);
+ }
free_tag_list(tl);
return rv;
}
+#define ASSERT(exp) if (!(exp)) \
+ fprintf(stderr,"ASSERT( " #exp " ) in %s:%d\n", __FILE__,__LINE__);
+
+void show_numeric(struct drbd_option *od, unsigned short* tp)
+{
+ long long val;
+
+ switch(tag_type(*tp++)) {
+ case TT_INTEGER:
+ ASSERT( *tp++ == sizeof(int) );
+ val = *(int*)tp;
+ break;
+ case TT_INT64:
+ ASSERT( *tp++ == sizeof(__u64) );
+ val = *(__u64*)tp;
+ break;
+ default:
+ ASSERT(0);
+ val=0;
+ }
+
+ printf("\t%s\t\t%lld",od->name,val);
+ if(val == (long long) od->numeric_param.def) printf(" _is_default");
+ printf(";\n");
+}
+
+void show_handler(struct drbd_option *od, unsigned short* tp)
+{
+ const char** handler_names = od->handler_param.handler_names;
+ int i;
+
+ ASSERT( tag_type(*tp++) == TT_INTEGER );
+ ASSERT( *tp++ == sizeof(int) );
+ i = *(int*)tp;
+ printf("\t%s\t\t%s",od->name,handler_names[i]);
+ if( i == (long long)od->numeric_param.def) printf(" _is_default");
+ printf(";\n");
+}
+
+void show_bit(struct drbd_option *od, unsigned short* tp)
+{
+ ASSERT( tag_type(*tp++) == TT_BIT );
+ ASSERT( *tp++ == sizeof(char) );
+ if(*(char*)tp) printf("\t%s;\n",od->name);
+}
+
+void show_string(struct drbd_option *od, unsigned short* tp)
+{
+ ASSERT( tag_type(*tp++) == TT_STRING );
+ if( *tp++ > 0) printf("\t%s\t\t\"%s\";\n",od->name,(char*)tp);
+}
+
+unsigned short *look_for_tag(unsigned short *tlc, unsigned short tag)
+{
+ enum drbd_tags t;
+ int len;
+
+ while( (t = *tlc) != TT_END ) {
+ if(t == tag) return tlc;
+ tlc++;
+ len = *tlc++;
+ tlc = (unsigned short*)((char*)tlc + len);
+ }
+ return NULL;
+}
+
+void print_options(struct drbd_option *od, unsigned short *tlc, const char* sect_name)
+{
+ unsigned short *tp;
+ int opened = 0;
+
+ while(od->name) {
+ tp = look_for_tag(tlc,od->tag);
+ if(tp) {
+ if(!opened) {
+ opened=1;
+ printf("%s {\n",sect_name);
+ }
+ od->show_function(od,tp);
+ *tp = TT_REMOVED;
+ }
+ od++;
+ }
+ if(opened) {
+ printf("}\n");
+ }
+}
+
+char* consume_tag_string(enum drbd_tags tag, unsigned short *tlc)
+{
+ unsigned short *tp;
+ tp = look_for_tag(tlc,tag);
+ if(tp) {
+ *tp++ = TT_REMOVED;
+ if( *tp++ > 0) return (char*)tp;
+ }
+ return "";
+}
+
+int consume_tag_int(enum drbd_tags tag, unsigned short *tlc)
+{
+ unsigned short *tp;
+ tp = look_for_tag(tlc,tag);
+ if(tp) {
+ *tp++ = TT_REMOVED;
+ tp++;
+ return *(int *)tp;
+ }
+ return 0;
+}
+
+int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
+{
+ char buffer[ 4096 ];
+ struct drbd_tag_list *tl;
+ struct drbd_nl_cfg_reply *reply;
+ struct sockaddr_in *addr;
+ int sk_nl;
+ unsigned short *rtl;
+
+ int idx;
+ char* str;
+
+ ASSERT(cm->packet_id == P_get_config);
+
+ if(argc > 1) {
+ fprintf(stderr,"Ignoring excess arguments\n");
+
+ }
+
+ tl = create_tag_list(2);
+ add_tag(tl,TT_END,NULL,0); // close the tag list
+
+ sk_nl = open_cn();
+ if(sk_nl < 0) return 20;
+
+ send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,0);
+
+ receive_cn(sk_nl, (struct nlmsghdr*)buffer, 4096 );
+ close_cn(sk_nl);
+ reply = (struct drbd_nl_cfg_reply *)
+ ((struct cn_msg *)NLMSG_DATA(buffer))->data;
+
+ rtl = reply->tag_list;
+
+ // find all commands that have options and print those...
+ for ( cm = commands ; cm < commands + ARRY_SIZE(commands) ; cm++ ) {
+ if(cm->options)
+ print_options(cm->options, rtl, cm->cmd);
+ }
+
+ // start of spagethi code...
+ idx = consume_tag_int(T_wire_protocol,rtl);
+ if(idx) printf("protocol %c;\n",'A'+idx-1);
+ str = consume_tag_string(T_backing_dev,rtl);
+ if(str) {
+ printf("_this_host {\n");
+ printf("\tdevice\t\t\"/dev/drbd%d\";\n",minor);
+ printf("\tdisk\t\t\"%s\";\n",str);
+ idx=consume_tag_int(T_meta_dev_idx,rtl);
+ switch(idx) {
+ case DRBD_MD_INDEX_INTERNAL:
+ case DRBD_MD_INDEX_FLEX_INT:
+ printf("\tmeta-disk\tinternal;\n");
+ consume_tag_string(T_meta_dev,rtl);
+ break;
+ case DRBD_MD_INDEX_FLEX_EXT:
+ printf("\tflexible-meta-disk\t\"%s\";\n",
+ consume_tag_string(T_meta_dev,rtl));
+ break;
+ default:
+ printf("\tmeta-disk\t\"%s\" [ %d ];\n",
+ consume_tag_string(T_meta_dev,rtl),idx);
+ }
+ str = consume_tag_string(T_my_addr,rtl);
+ if(str) {
+ addr = (struct sockaddr_in *)str;
+ printf("\taddress\t\t%s:%d;\n",
+ inet_ntoa(addr->sin_addr),
+ ntohs(addr->sin_port));
+ }
+ printf("}\n");
+ }
+
+ str = consume_tag_string(T_peer_addr,rtl);
+ if(str) {
+ printf("_remote_host {\n");
+ addr = (struct sockaddr_in *)str;
+ printf("\taddress\t\t%s:%d;\n",
+ inet_ntoa(addr->sin_addr),
+ ntohs(addr->sin_port));
+ printf("}\n");
+ }
+
+ if(dump_tag_list(reply->tag_list)) {
+ printf("# Found unknown tags, you should update your\n"
+ "# userland tools\n");
+ }
+
+ return 0;
+}
+
void print_command_usage(int i, const char *addinfo)
// CAUTION no range check for i
{
@@ -641,6 +989,8 @@
for (i = 0; i < ARRY_SIZE(commands); i++)
print_command_usage(i, 0);
+ printf("\nGeneral options: --create-device, --set-defaults\n");
+
print_handler("\non-io-error handlers:",on_error,ARRY_SIZE(on_error));
print_handler("\nfencing policies:",fencing_n,ARRY_SIZE(fencing_n));
print_handler("\nafter-sb-0pri handler:",asb0p_n,ARRY_SIZE(asb0p_n));
@@ -658,11 +1008,100 @@
exit(20);
}
+int open_cn()
+{
+ int sk_nl;
+ int err;
+ struct sockaddr_nl my_nla;
+
+ sk_nl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+ if (sk_nl == -1) {
+ perror("socket() failed");
+ return -1;
+ }
+
+ my_nla.nl_family = AF_NETLINK;
+ my_nla.nl_groups = -1; //CN_IDX_DRBD;
+ my_nla.nl_pid = getpid();
+
+ err = bind(sk_nl, (struct sockaddr *)&my_nla, sizeof(my_nla));
+ if (err == -1) {
+ err = errno;
+ perror("bind() failed");
+ if(err == ENOENT) {
+ fprintf(stderr,"DRBD driver not present in the kernel?\n");
+ }
+ return -1;
+ }
+
+ return sk_nl;
+}
+
+
+int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
+{
+ struct cn_msg *cn_hdr;
+ cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr);
+ int rr;
+
+ /* fill the netlink header */
+ nl_hdr->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr));
+ nl_hdr->nlmsg_type = NLMSG_DONE;
+ nl_hdr->nlmsg_flags = 0;
+ nl_hdr->nlmsg_seq = 0;
+ nl_hdr->nlmsg_pid = getpid();
+ /* fill the connector header */
+ cn_hdr->id.idx = CN_IDX_DRBD;
+ cn_hdr->seq = 0;
+ cn_hdr->ack = 0;
+ cn_hdr->len = size - sizeof(struct nlmsghdr) - sizeof(struct cn_msg);
+
+ rr = send(sk_nl,nl_hdr,nl_hdr->nlmsg_len,0);
+ if( rr != (ssize_t)nl_hdr->nlmsg_len) {
+ perror("send() failed");
+ return -1;
+ }
+ return rr;
+}
+
+int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
+{
+ int rr;
+
+ rr = recv(sk_nl,nl_hdr,size,0);
+
+ if( rr < 0 ) {
+ perror("recv() failed");
+ return -1;
+ }
+ return rr;
+}
+
+int send_tag_list_cn(int sk_nl, struct drbd_tag_list *tl, const int packet_id, int minor, int flags)
+{
+ tl->cn_header->id.val = packet_id;
+ tl->drbd_p_header->drbd_minor = minor;
+ tl->drbd_p_header->flags = flags;
+
+ return send_cn(sk_nl, tl->nl_header, (char*)tl->tag_list_cpos -
+ (char*)tl->nl_header);
+}
+
+void close_cn(int sk_nl)
+{
+ close(sk_nl);
+}
+
int main(int argc, char** argv)
{
int help = 0;
unsigned int i;
+ int minor;
+ int drbd_fd,lock_fd;
+ struct drbd_cmd *cmd;
+ chdir("/");
+
if ( (cmdname = strrchr(argv[0],'/')) )
argv[0] = ++cmdname;
else
@@ -671,15 +1110,25 @@
/* == '-' catches -h, --help, and similar */
if (argc > 1 && (!strcmp(argv[1],"help") || argv[1][0] == '-'))
help = 1;
+
if (argc < 3) print_usage(argc==1 ? 0 : " Insufficient arguments");
- chdir("/");
-
+ cmd=NULL;
for(i=0;i<ARRY_SIZE(commands);i++) {
if(strcmp(argv[2],commands[i].cmd)==0) {
- commands[i].function(commands+i,argc-3,argv+3);
+ cmd = commands+i;
+ break;
}
}
+ if(cmd) {
+ drbd_fd = dt_lock_open_drbd(argv[1], &lock_fd, 1 );
+ minor=dt_minor_of_dev(argv[1]);
+ commands[i].function(commands+i,minor,argc-3,argv+3);
+ dt_close_drbd_unlock(drbd_fd,lock_fd);
+ } else {
+ print_usage("invalid command");
+ }
+
return 0;
}
Modified: trunk/user/drbdtool_common.c
===================================================================
--- trunk/user/drbdtool_common.c 2006-08-23 10:19:26 UTC (rev 2385)
+++ trunk/user/drbdtool_common.c 2006-08-25 08:50:47 UTC (rev 2386)
@@ -4,6 +4,7 @@
#include <asm/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
+#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
More information about the drbd-cvs
mailing list