On 01/05/2012 08:38 PM, Mike Christie wrote:
> On 12/28/2011 02:36 AM, Mike Christie wrote:
>> On 12/22/2011 04:44 PM, pmullaney wrote:
>>> Hi all,
>>>
>>> Running into problems running under lxc. I am running iscsid in the
>>> container and when it
>>> attempts to connect to the netlink iscsi socket it is getting a
>>> connection refused(111) and
>>> the following in the log:
>>>
>>> sendmsg: bug? ctrl_fd 5
>>>
>>> which causes iscsid to exit.
>>>
>>> Any thoughts on what could be wrong?
>>>
>>
>> The iscsi netlink code never returns  111/ECONNREFUSED.
>>
>> It looks like the netlink code will return this when the netlink socket
>> is not setup.
>>
> 
> Ok, I think we need to modify the iscsi netlink socket to support
> multiple namespaces.
> 
> Have not been able to get this working in fedora 16 exactly, so this is
> just a guess based on looking at the code and git commits.
> 

Here is a patch that should implement the needed functionality on the
netlink side. It is not optimal though, but should give us an idea if we
are on the right track.

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com.
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index c1b172b..b09e02e 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -79,6 +79,14 @@ struct iscsi_internal {
 	struct transport_container session_cont;
 };
 
+struct iscsi_nl_sock {
+	struct list_head list;
+	struct sock *sk;
+};
+
+static LIST_HEAD(iscsi_nl_sock_list);
+static DEFINE_SPINLOCK(iscsi_nl_sock_lock);
+
 static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
 static struct workqueue_struct *iscsi_eh_timer_workq;
 
@@ -599,7 +607,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
 			       NULL,
 			       NULL);
 
-static struct sock *nls;
 static DEFINE_MUTEX(rx_queue_mutex);
 
 static LIST_HEAD(sesslist);
@@ -1332,7 +1339,27 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt)
 static int
 iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
 {
-	return nlmsg_multicast(nls, skb, 0, group, gfp);
+	struct iscsi_nl_sock *nlsk;
+	struct sk_buff *cloned_skb;
+	int err, rc = 0;
+
+	spin_lock_bh(&iscsi_nl_sock_lock);
+	list_for_each_entry(nlsk, &iscsi_nl_sock_list, list) {
+		/* TODO change locking */
+		cloned_skb = skb_clone(skb, GFP_ATOMIC);
+		if (!cloned_skb) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		err = nlmsg_multicast(nlsk->sk, cloned_skb, 0, group,
+				      GFP_ATOMIC);
+		if (err && !rc)
+			rc = err;
+	}
+	spin_unlock_bh(&iscsi_nl_sock_lock);
+	kfree_skb(skb);
+	return rc;
 }
 
 int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
@@ -2673,6 +2700,55 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
 }
 EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
 
+static int iscsi_pernet_init(struct net *net)
+{
+	struct iscsi_nl_sock *nlsk;
+
+	nlsk = kzalloc(sizeof(*nlsk), GFP_KERNEL);
+	if (!nlsk)
+		return -ENOMEM;
+
+	nlsk->sk = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1,
+					 iscsi_if_rx, NULL, THIS_MODULE);
+	if (!nlsk->sk) {
+		printk(KERN_ERR "iscsi class: Could not create netlink "
+		       "socket.\n");
+		kfree(nlsk);
+		return -ENODEV;
+	}
+
+	spin_lock_bh(&iscsi_nl_sock_lock);
+	list_add_tail(&nlsk->list, &iscsi_nl_sock_list);
+	spin_unlock_bh(&iscsi_nl_sock_lock);
+	return 0;
+}
+
+static void iscsi_pernet_exit(struct net *net)
+{
+	struct iscsi_nl_sock *nlsk;
+
+	spin_lock_bh(&iscsi_nl_sock_lock);
+	list_for_each_entry(nlsk, &iscsi_nl_sock_list, list) {
+		if (sock_net(nlsk->sk) == net)
+			goto found;
+	}
+
+	spin_unlock_bh(&iscsi_nl_sock_lock);
+	return;
+
+found:
+	list_del(&nlsk->list);
+	spin_unlock_bh(&iscsi_nl_sock_lock);
+
+	netlink_kernel_release(nlsk->sk);
+	kfree(nlsk);
+}
+
+static struct pernet_operations iscsi_pernet_ops = {
+	.init	= iscsi_pernet_init,
+	.exit	= iscsi_pernet_exit,
+};
+
 static __init int iscsi_transport_init(void)
 {
 	int err;
@@ -2706,21 +2782,18 @@ static __init int iscsi_transport_init(void)
 	if (err)
 		goto unregister_conn_class;
 
-	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
-				    NULL, THIS_MODULE);
-	if (!nls) {
-		err = -ENOBUFS;
+	err = register_pernet_subsys(&iscsi_pernet_ops);
+	if (err)
 		goto unregister_session_class;
-	}
 
 	iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
 	if (!iscsi_eh_timer_workq)
-		goto release_nls;
+		goto  unregister_pernet;
 
 	return 0;
 
-release_nls:
-	netlink_kernel_release(nls);
+unregister_pernet:
+	unregister_pernet_subsys(&iscsi_pernet_ops);
 unregister_session_class:
 	transport_class_unregister(&iscsi_session_class);
 unregister_conn_class:
@@ -2739,7 +2812,7 @@ unregister_transport_class:
 static void __exit iscsi_transport_exit(void)
 {
 	destroy_workqueue(iscsi_eh_timer_workq);
-	netlink_kernel_release(nls);
+	unregister_pernet_subsys(&iscsi_pernet_ops);
 	transport_class_unregister(&iscsi_connection_class);
 	transport_class_unregister(&iscsi_session_class);
 	transport_class_unregister(&iscsi_host_class);

Reply via email to