[Drbd-dev] DRBD on container, lxc

Ken-ichirou MATSUZAWA chamas at h4.dion.ne.jp
Mon Mar 21 02:10:59 CET 2011


 Hello Evgeniy, list

I did not know where I should post, here is my starting point. I
started to try DRBD on lxc but did not work. I thought first thing
to do is makeing connector to net namespace aware. Appended patch
may have many issue but I noticed only a few though. 

First this does not add connector sock to struct net, but just
holding sock as a list and send message to all net namespace. I
referred lib/kobject_uevent.c

Next I could not know the plan of relationship sock and work queue,
that is, call cn_queue_alloc_dev() with NULL sock.

Finaly, is this a correct way to run DRBD on lxc?

Would I ask your advice on something?
thanks,


---

 drivers/connector/connector.c |  191 +++++++++++++++++++++++++++++++++++------
 include/linux/connector.h     |    6 ++
 2 files changed, 171 insertions(+), 26 deletions(-)

diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 05117f1..38f4abe 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -32,6 +32,7 @@
 #include <linux/spinlock.h>
 
 #include <net/sock.h>
+#include <net/net_namespace.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <zbr at ioremap.net>");
@@ -42,6 +43,78 @@ static struct cn_dev cdev;
 
 static int cn_already_initialized;
 
+#ifdef CONFIG_NET
+struct cn_sock {
+	struct list_head list;
+	struct sock *sk;
+};
+static DEFINE_SPINLOCK(cn_sock_lock);
+
+static int send_firm_group(struct cn_msg *msg, u32 group, gfp_t gfp_mask)
+{
+	unsigned int size;
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct cn_msg *data;
+	struct cn_dev *dev = &cdev;
+	struct cn_sock *cn_sk;
+	int err = 0;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(cn_sk, &dev->nls_list, list) {
+		struct sock *nls = cn_sk->sk;
+
+		size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+		skb = alloc_skb(size, gfp_mask);
+		if (!skb) {
+			err =  -ENOMEM;
+			goto nlmsg_failure;
+		}
+
+		nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
+		data = NLMSG_DATA(nlh);
+		memcpy(data, msg, sizeof(*data) + msg->len);
+		NETLINK_CB(skb).dst_group = group;
+
+		err = netlink_broadcast(nls, skb, 0, group, gfp_mask);
+		if (err && err != -ESRCH)
+			goto nlmsg_failure;
+
+		err = 0;
+	}
+
+nlmsg_failure:
+	rcu_read_unlock();
+
+	return err;
+}
+
+#else /* CONFIG_NET */
+static int send_firm_group(struct cn_msg *msg, u32 group, gfp_t gfp_mask)
+{
+	unsigned int size;
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct cn_msg *data;
+	struct cn_dev *dev = &cdev;
+	
+	if (!netlink_has_listeners(dev->nls, group))
+		return -ESRCH;
+
+	size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+	skb = alloc_skb(size, gfp_mask);
+	if (!skb)
+		return -ENOMEM;
+
+	nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
+	data = NLMSG_DATA(nlh);
+	memcpy(data, msg, sizeof(*data) + msg->len);
+	NETLINK_CB(skb).dst_group = group;
+
+	return netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
+}
+#endif /* CONFIG_NET */
+
 /*
  * msg->seq and msg->ack are used to determine message genealogy.
  * When someone sends message it puts there locally unique sequence
@@ -66,10 +139,6 @@ static int cn_already_initialized;
 int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 {
 	struct cn_callback_entry *__cbq;
-	unsigned int size;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct cn_msg *data;
 	struct cn_dev *dev = &cdev;
 	u32 group = 0;
 	int found = 0;
@@ -92,28 +161,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 		group = __group;
 	}
 
-	if (!netlink_has_listeners(dev->nls, group))
-		return -ESRCH;
-
-	size = NLMSG_SPACE(sizeof(*msg) + msg->len);
-
-	skb = alloc_skb(size, gfp_mask);
-	if (!skb)
-		return -ENOMEM;
-
-	nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
-
-	data = NLMSG_DATA(nlh);
-
-	memcpy(data, msg, sizeof(*data) + msg->len);
-
-	NETLINK_CB(skb).dst_group = group;
-
-	return netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
-
-nlmsg_failure:
-	kfree_skb(skb);
-	return -EINVAL;
+	return send_firm_group(msg, group, gfp_mask);
 }
 EXPORT_SYMBOL_GPL(cn_netlink_send);
 
@@ -272,6 +320,96 @@ static const struct file_operations cn_file_ops = {
 	.release = single_release
 };
 
+#ifdef CONFIG_NET
+static int cn_net_init(struct net *net)
+{
+	struct cn_dev *dev = &cdev;
+	struct cn_sock *cn_sk;
+
+	cn_sk = kzalloc(sizeof(struct cn_sock), GFP_KERNEL);
+	if (!cn_sk)
+		return -ENOMEM;
+
+	cn_sk->sk = netlink_kernel_create(net, NETLINK_CONNECTOR,
+					 CN_NETLINK_USERS + 0xf,
+					 dev->input, NULL, THIS_MODULE);
+	if (!cn_sk->sk) {
+		printk(KERN_ERR
+		       "connector: unable to create netlink socket!\n");
+		kfree(cn_sk);
+		return -EIO;
+	}
+
+	spin_lock(&cn_sock_lock);
+	list_add_tail_rcu(&cn_sk->list, &dev->nls_list);
+	spin_unlock(&cn_sock_lock);
+
+	proc_net_fops_create(net, "connector", S_IRUGO, &cn_file_ops);
+
+ 	return 0;
+}
+
+static void cn_net_exit(struct net *net) {
+	struct cn_dev *dev = &cdev;
+	struct cn_sock *cn_sk;
+	int found = 0;
+
+	spin_lock(&cn_sock_lock);
+	list_for_each_entry(cn_sk, &dev->nls_list, list) {
+		if (sock_net(cn_sk->sk) == net) {
+			list_del_rcu(&cn_sk->list);
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock(&cn_sock_lock);
+
+	if (!found)
+		return;
+
+	proc_net_remove(net, "connector");
+	netlink_kernel_release(cn_sk->sk);
+	kfree(cn_sk);
+}
+
+static struct pernet_operations cn_net_ops = {
+	.init = cn_net_init,
+	.exit = cn_net_exit,
+};
+
+static int __devinit cn_init(void)
+{
+	int err = 0;
+	struct cn_dev *dev = &cdev;
+
+	INIT_LIST_HEAD(&dev->nls_list);
+	dev->input = cn_rx_skb;
+
+	dev->cbdev = cn_queue_alloc_dev("cqueue", NULL);
+	if (!dev->cbdev)
+		return -EINVAL;
+
+	err = register_pernet_subsys(&cn_net_ops);
+	if (err) {
+		cn_queue_free_dev(dev->cbdev);
+		return err;
+	}
+
+	cn_already_initialized = 1;
+	
+	return 0;
+}
+
+static void __devexit cn_fini(void)
+{
+	struct cn_dev *dev = &cdev;
+
+	cn_already_initialized = 0;
+	unregister_pernet_subsys(&cn_net_ops);
+	cn_queue_free_dev(dev->cbdev);
+}
+	
+#else /* CONFIG_NET */
 static int __devinit cn_init(void)
 {
 	struct cn_dev *dev = &cdev;
@@ -308,6 +446,7 @@ static void __devexit cn_fini(void)
 	cn_queue_free_dev(dev->cbdev);
 	netlink_kernel_release(dev->nls);
 }
+#endif /* CONFIG_NET */
 
 subsys_initcall(cn_init);
 module_exit(cn_fini);
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 7e8ca75..e0b9f4c 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -122,7 +122,13 @@ struct cn_dev {
 	struct cb_id id;
 
 	u32 seq, groups;
+
+#ifdef CONFIG_NET
+	struct list_head nls_list;
+#else /* CONFIG_NET */
 	struct sock *nls;
+#endif /* CONFIG_NET */
+
 	void (*input) (struct sk_buff *skb);
 
 	struct cn_queue_dev *cbdev;
-- 
1.7.2.5



More information about the drbd-dev mailing list