Commit 3af7ff93 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'smc-last-part-of-termination-improvements'



Karsten Graul says:

====================
last part of termination improvements

Patches 1 and 2 finish the set of termination patches, introducing
a reboot handler that terminates all link groups. Patch 3 adds an
rcu_barrier before the module is unloaded, and patch 4 is cleanup.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c39e342a ab8536ca
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/in.h>
#include <linux/sched/signal.h>
#include <linux/if_vlan.h>
#include <linux/rcupdate_wait.h>

#include <net/sock.h>
#include <net/tcp.h>
@@ -2038,22 +2039,28 @@ static int __init smc_init(void)
	if (rc)
		goto out_pernet_subsys;

	rc = smc_core_init();
	if (rc) {
		pr_err("%s: smc_core_init fails with %d\n", __func__, rc);
		goto out_pnet;
	}

	rc = smc_llc_init();
	if (rc) {
		pr_err("%s: smc_llc_init fails with %d\n", __func__, rc);
		goto out_pnet;
		goto out_core;
	}

	rc = smc_cdc_init();
	if (rc) {
		pr_err("%s: smc_cdc_init fails with %d\n", __func__, rc);
		goto out_pnet;
		goto out_core;
	}

	rc = proto_register(&smc_proto, 1);
	if (rc) {
		pr_err("%s: proto_register(v4) fails with %d\n", __func__, rc);
		goto out_pnet;
		goto out_core;
	}

	rc = proto_register(&smc_proto6, 1);
@@ -2085,6 +2092,8 @@ out_proto6:
	proto_unregister(&smc_proto6);
out_proto:
	proto_unregister(&smc_proto);
out_core:
	smc_core_exit();
out_pnet:
	smc_pnet_exit();
out_pernet_subsys:
@@ -2095,14 +2104,15 @@ out_pernet_subsys:

static void __exit smc_exit(void)
{
	smc_core_exit();
	static_branch_disable(&tcp_have_smc);
	smc_ib_unregister_client();
	sock_unregister(PF_SMC);
	smc_core_exit();
	smc_ib_unregister_client();
	proto_unregister(&smc_proto6);
	proto_unregister(&smc_proto);
	smc_pnet_exit();
	unregister_pernet_subsys(&smc_net_ops);
	rcu_barrier();
}

module_init(smc_init);
+0 −2
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@
#include "smc_cdc.h"
#include "smc_close.h"

#define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME	(5 * HZ)

/* release the clcsock that is assigned to the smc_sock */
void smc_clcsock_release(struct smc_sock *smc)
{
+39 −0
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#include <linux/if_vlan.h>
#include <linux/random.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/reboot.h>
#include <net/tcp.h>
#include <net/sock.h>
#include <rdma/ib_verbs.h>
@@ -39,6 +41,9 @@ static struct smc_lgr_list smc_lgr_list = { /* established link groups */
	.num = 0,
};

static atomic_t lgr_cnt;		/* number of existing link groups */
static DECLARE_WAIT_QUEUE_HEAD(lgrs_deleted);

static void smc_buf_free(struct smc_link_group *lgr, bool is_rmb,
			 struct smc_buf_desc *buf_desc);

@@ -319,6 +324,8 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
		rc = smc_wr_create_link(lnk);
		if (rc)
			goto destroy_qp;
		atomic_inc(&lgr_cnt);
		atomic_inc(&ini->ib_dev->lnk_cnt);
	}
	smc->conn.lgr = lgr;
	spin_lock_bh(lgr_lock);
@@ -406,6 +413,8 @@ static void smc_link_clear(struct smc_link *lnk)
	smc_ib_destroy_queue_pair(lnk);
	smc_ib_dealloc_protection_domain(lnk);
	smc_wr_free_link_mem(lnk);
	if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
		wake_up(&lnk->smcibdev->lnks_deleted);
}

static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
@@ -492,6 +501,8 @@ static void smc_lgr_free(struct smc_link_group *lgr)
	} else {
		smc_link_clear(&lgr->lnk[SMC_SINGLE_LINK]);
		put_device(&lgr->lnk[SMC_SINGLE_LINK].smcibdev->ibdev->dev);
		if (!atomic_dec_return(&lgr_cnt))
			wake_up(&lgrs_deleted);
	}
	kfree(lgr);
}
@@ -729,6 +740,15 @@ void smc_smcr_terminate_all(struct smc_ib_device *smcibdev)
		list_del_init(&lgr->list);
		__smc_lgr_terminate(lgr, false);
	}

	if (smcibdev) {
		if (atomic_read(&smcibdev->lnk_cnt))
			wait_event(smcibdev->lnks_deleted,
				   !atomic_read(&smcibdev->lnk_cnt));
	} else {
		if (atomic_read(&lgr_cnt))
			wait_event(lgrs_deleted, !atomic_read(&lgr_cnt));
	}
}

/* Determine vlan of internal TCP socket.
@@ -1263,8 +1283,27 @@ static void smc_lgrs_shutdown(void)
	spin_unlock(&smcd_dev_list.lock);
}

static int smc_core_reboot_event(struct notifier_block *this,
				 unsigned long event, void *ptr)
{
	smc_lgrs_shutdown();

	return 0;
}

static struct notifier_block smc_reboot_notifier = {
	.notifier_call = smc_core_reboot_event,
};

int __init smc_core_init(void)
{
	atomic_set(&lgr_cnt, 0);
	return register_reboot_notifier(&smc_reboot_notifier);
}

/* Called (from smc_exit) when module is removed */
void smc_core_exit(void)
{
	unregister_reboot_notifier(&smc_reboot_notifier);
	smc_lgrs_shutdown();
}
+1 −0
Original line number Diff line number Diff line
@@ -318,6 +318,7 @@ void smc_conn_free(struct smc_connection *conn);
int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini);
void smcd_conn_free(struct smc_connection *conn);
void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr);
int smc_core_init(void);
void smc_core_exit(void);

static inline struct smc_link_group *smc_get_lgr(struct smc_link *link)
+3 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/random.h>
#include <linux/workqueue.h>
#include <linux/scatterlist.h>
#include <linux/wait.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>

@@ -543,7 +544,8 @@ static void smc_ib_add_dev(struct ib_device *ibdev)

	smcibdev->ibdev = ibdev;
	INIT_WORK(&smcibdev->port_event_work, smc_ib_port_event_work);

	atomic_set(&smcibdev->lnk_cnt, 0);
	init_waitqueue_head(&smcibdev->lnks_deleted);
	spin_lock(&smc_ib_devices.lock);
	list_add_tail(&smcibdev->list, &smc_ib_devices.list);
	spin_unlock(&smc_ib_devices.lock);
Loading