diff --git a/iscsi-scst/kernel/event.c b/iscsi-scst/kernel/event.c index 9ccd9e1ee..f8791913f 100644 --- a/iscsi-scst/kernel/event.c +++ b/iscsi-scst/kernel/event.c @@ -25,6 +25,9 @@ #include "iscsi_trace_flag.h" #include "iscsi.h" +struct net *iscsi_net_ns; +EXPORT_SYMBOL(iscsi_net_ns); + /* See also commit 2d4bc93368f5 ("netlink: extended ACK reporting") */ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) struct netlink_ext_ack; @@ -191,6 +194,8 @@ out_unlock: int __init event_init(void) { + iscsi_net_ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)) nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, THIS_MODULE); @@ -198,7 +203,7 @@ int __init event_init(void) nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, NULL, THIS_MODULE); #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, 1, + nl = netlink_kernel_create(iscsi_net_ns, NETLINK_ISCSI_SCST, 1, event_recv_skb, NULL, THIS_MODULE); #else { @@ -207,18 +212,24 @@ int __init event_init(void) .groups = 1, }; #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) - nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, + nl = netlink_kernel_create(iscsi_net_ns, NETLINK_ISCSI_SCST, THIS_MODULE, &cfg); #else - nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, &cfg); + nl = netlink_kernel_create(iscsi_net_ns, NETLINK_ISCSI_SCST, + &cfg); #endif } #endif - if (!nl) { - PRINT_ERROR("%s", "netlink_kernel_create() failed"); - return -ENOMEM; - } else - return 0; + if (!nl) + goto drop_ns; + + return 0; + +drop_ns: + PRINT_ERROR("%s", "netlink_kernel_create() failed"); + kobj_ns_drop(KOBJ_NS_TYPE_NET, iscsi_net_ns); + iscsi_net_ns = NULL; + return -ENOMEM; } void event_exit(void) @@ -229,4 +240,6 @@ void event_exit(void) #else netlink_kernel_release(nl); #endif + kobj_ns_drop(KOBJ_NS_TYPE_NET, iscsi_net_ns); + iscsi_net_ns = NULL; } diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index d45e31443..a8a24b1ea 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -39,6 +39,8 @@ #define iscsi_sense_unexpected_unsolicited_data ABORTED_COMMAND, 0x0C, 0x0C #define iscsi_sense_incorrect_amount_of_data ABORTED_COMMAND, 0x0C, 0x0D +struct net; + struct iscsi_sess_params { int initial_r2t; int immediate_data; @@ -666,6 +668,7 @@ static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu) } extern struct scst_tgt_template iscsi_template; +extern struct net *iscsi_net_ns; /* * Skip this command if result is true. Must be called under diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index 7d9cf30f9..3375c92f2 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -1812,7 +1812,7 @@ struct isert_portal *isert_portal_create(void) cm_id = rdma_create_id(isert_cm_evt_handler, portal, RDMA_PS_TCP, IB_QPT_RC); #else - cm_id = rdma_create_id(&init_net, isert_cm_evt_handler, portal, + cm_id = rdma_create_id(iscsi_net_ns, isert_cm_evt_handler, portal, RDMA_PS_TCP, IB_QPT_RC); #endif if (IS_ERR(cm_id)) { diff --git a/scst/include/backport.h b/scst/include/backport.h index 39a9d03a6..368360e5d 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -792,6 +792,23 @@ enum umh_wait { }; #endif +/* */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +/* + * See also commit a685e08987d1 ("Delay struct net freeing while there's a + * sysfs instance refering to it") # v3.0. + */ +static inline void *kobj_ns_grab_current(enum kobj_ns_type type) +{ + return &init_net; +} + +static inline void kobj_ns_drop(enum kobj_ns_type type, void *ns) +{ +} +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) && \ diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 30820bfe7..46213f17f 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -179,6 +179,7 @@ static const enum scst_exec_context srpt_send_context = SCST_CONTEXT_DIRECT; static struct ib_client srpt_client; static struct scst_tgt_template srpt_template; +static struct net *srpt_net_ns; static struct rdma_cm_id *rdma_cm_id; static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch, @@ -4679,6 +4680,8 @@ static int __init srpt_init_module(void) goto out_unregister_target; } + srpt_net_ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); + if (rdma_cm_port) { struct sockaddr_in addr; @@ -4690,38 +4693,48 @@ static int __init srpt_init_module(void) rdma_cm_id = rdma_create_id(srpt_rdma_cm_handler, NULL, RDMA_PS_TCP, IB_QPT_RC); #else - rdma_cm_id = rdma_create_id(&init_net, srpt_rdma_cm_handler, + rdma_cm_id = rdma_create_id(srpt_net_ns, srpt_rdma_cm_handler, NULL, RDMA_PS_TCP, IB_QPT_RC); #endif if (IS_ERR(rdma_cm_id)) { + ret = PTR_ERR(rdma_cm_id); rdma_cm_id = NULL; pr_err("RDMA/CM ID creation failed\n"); - goto out_unregister_client; + goto drop_ns; } /* We will listen on any RDMA device. */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = cpu_to_be16(rdma_cm_port); - if (rdma_bind_addr(rdma_cm_id, (void *)&addr)) { + ret = rdma_bind_addr(rdma_cm_id, (void *)&addr); + if (ret) { pr_err("Binding RDMA/CM ID to port %u failed\n", rdma_cm_port); - goto out_unregister_client; + goto destroy_id; } - if (rdma_listen(rdma_cm_id, 128)) { + ret = rdma_listen(rdma_cm_id, 128); + if (ret) { pr_err("rdma_listen() failed\n"); - goto out_unregister_client; + goto destroy_id; } } - return 0; -out_unregister_client: +destroy_id: + if (rdma_cm_id) + rdma_destroy_id(rdma_cm_id); + +drop_ns: + kobj_ns_drop(KOBJ_NS_TYPE_NET, srpt_net_ns); + srpt_net_ns = NULL; ib_unregister_client(&srpt_client); + out_unregister_target: scst_unregister_target_template(&srpt_template); + out: return ret; } @@ -4732,7 +4745,12 @@ static void __exit srpt_cleanup_module(void) if (rdma_cm_id) rdma_destroy_id(rdma_cm_id); + + kobj_ns_drop(KOBJ_NS_TYPE_NET, srpt_net_ns); + srpt_net_ns = NULL; + ib_unregister_client(&srpt_client); + scst_unregister_target_template(&srpt_template); }