From: Petr Tesarik <ptesarik@suse.com>
Subject: kABI: protect struct smc_link
Patch-mainline: never, kabi
References: bnc#1117947, LTC#173662
Upstream commit 60e03c62c5db22c5eb63bcb6ce226cf05f4ee47c adds new
fields to struct smc_link. However, this structure is embedded
inside struct smc_link_group, so its cannot be resized without
moving following fields inside that structure.
Thankfully, there is a one-to-one correspondence between a link
and its link group, because there can be currently only one link
per group. The extra fields can be added at the end of struct
smc_link_group, which is allocated dynamically, and its size
should never be needed by another module.
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
net/smc/smc_core.h | 7 +++++++
net/smc/smc_llc.c | 23 ++++++++++++++---------
2 files changed, 21 insertions(+), 9 deletions(-)
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -108,6 +108,9 @@ struct smc_link {
int llc_testlink_time; /* testlink interval */
struct completion llc_confirm_rkey; /* wait 4 rx of cnf rkey */
int llc_confirm_rkey_rc; /* rc from cnf rkey msg */
+};
+
+struct smc_link_extra {
struct completion llc_delete_rkey; /* wait 4 rx of del rkey */
int llc_delete_rkey_rc; /* rc from del rkey msg */
struct mutex llc_delete_rkey_mutex; /* serialize usage */
@@ -210,6 +213,10 @@ struct smc_link_group {
/* ISM device for VLAN reg. */
};
};
+#ifndef __GENKSYMS__
+ struct smc_link_extra lnk_extra[SMC_LINKS_PER_LGR_MAX];
+ /* smc_link fields added after kABI freeze */
+#endif
};
/* Find the connection associated with the given alert token in the link group.
--- a/net/smc/smc_llc.c
+++ b/net/smc/smc_llc.c
@@ -531,9 +531,11 @@ static void smc_llc_rx_delete_rkey(struc
int i, max;
if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
- link->llc_delete_rkey_rc = llc->hd.flags &
+ struct smc_link_group *lgr = smc_get_lgr(link);
+ struct smc_link_extra *extra = &lgr->lnk_extra[SMC_SINGLE_LINK];
+ extra->llc_delete_rkey_rc = llc->hd.flags &
SMC_LLC_FLAG_RKEY_NEG;
- complete(&link->llc_delete_rkey);
+ complete(&extra->llc_delete_rkey);
} else {
max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX);
for (i = 0; i < max; i++) {
@@ -624,6 +626,7 @@ out:
int smc_llc_link_init(struct smc_link *link)
{
struct smc_link_group *lgr = smc_get_lgr(link);
+ struct smc_link_extra *extra = &lgr->lnk_extra[SMC_SINGLE_LINK];
link->llc_wq = alloc_ordered_workqueue("llc_wq-%x:%x)", WQ_MEM_RECLAIM,
*((u32 *)lgr->id),
link->link_id);
@@ -634,8 +637,8 @@ int smc_llc_link_init(struct smc_link *l
init_completion(&link->llc_add);
init_completion(&link->llc_add_resp);
init_completion(&link->llc_confirm_rkey);
- init_completion(&link->llc_delete_rkey);
- mutex_init(&link->llc_delete_rkey_mutex);
+ init_completion(&extra->llc_delete_rkey);
+ mutex_init(&extra->llc_delete_rkey_mutex);
init_completion(&link->llc_testlink_resp);
INIT_DELAYED_WORK(&link->llc_testlink_wrk, smc_llc_testlink_work);
return 0;
@@ -693,22 +696,24 @@ int smc_llc_do_confirm_rkey(struct smc_l
int smc_llc_do_delete_rkey(struct smc_link *link,
struct smc_buf_desc *rmb_desc)
{
+ struct smc_link_group *lgr = smc_get_lgr(link);
+ struct smc_link_extra *extra = &lgr->lnk_extra[SMC_SINGLE_LINK];
int rc;
- mutex_lock(&link->llc_delete_rkey_mutex);
- reinit_completion(&link->llc_delete_rkey);
+ mutex_lock(&extra->llc_delete_rkey_mutex);
+ reinit_completion(&extra->llc_delete_rkey);
rc = smc_llc_send_delete_rkey(link, rmb_desc);
if (rc)
goto out;
/* receive DELETE RKEY response from server over RoCE fabric */
- rc = wait_for_completion_interruptible_timeout(&link->llc_delete_rkey,
+ rc = wait_for_completion_interruptible_timeout(&extra->llc_delete_rkey,
SMC_LLC_WAIT_TIME);
- if (rc <= 0 || link->llc_delete_rkey_rc)
+ if (rc <= 0 || extra->llc_delete_rkey_rc)
rc = -EFAULT;
else
rc = 0;
out:
- mutex_unlock(&link->llc_delete_rkey_mutex);
+ mutex_unlock(&extra->llc_delete_rkey_mutex);
return rc;
}