diff --git a/drivers/ub/urma/ubcore/ubmgr/ubmgr_ping.c b/drivers/ub/urma/ubcore/ubmgr/ubmgr_ping.c index a8a83c229e7450cb4e458e2b99447eeeb9f0d8db..fdea2a7376797165250691d9373e1ad531c9f1af 100644 --- a/drivers/ub/urma/ubcore/ubmgr/ubmgr_ping.c +++ b/drivers/ub/urma/ubcore/ubmgr/ubmgr_ping.c @@ -46,7 +46,7 @@ struct ubmgr_ping_ctx { /* Hash func */ struct ubmgr_ping_tjetty_entry { struct ubcore_tjetty *tjetty; - struct kref kref; + refcount_t ref; struct hlist_node node; }; @@ -81,15 +81,12 @@ __ping_tjetty_new_entry(struct ubcore_device *dev, union ubcore_eid *dst_eid, return ERR_PTR(-ENOMEM); entry->tjetty = tjetty; - kref_init(&entry->kref); + refcount_set(&entry->ref, 1); return entry; } -static void __ping_tjetty_free_entry(struct kref *kref) +static void ping_tjetty_free_entry(struct ubmgr_ping_tjetty_entry *entry) { - struct ubmgr_ping_tjetty_entry *entry = - container_of(kref, struct ubmgr_ping_tjetty_entry, kref); - ubcore_unimport_jetty(entry->tjetty); } @@ -103,7 +100,7 @@ __ping_tjetty_find(struct hlist_head *bucket, union ubcore_eid *dst_eid, if (memcmp(&entry->tjetty->cfg.id.eid, dst_eid, sizeof(union ubcore_eid)) == 0 && entry->tjetty->cfg.id.id == remote_id) { - kref_get(&entry->kref); + refcount_inc(&entry->ref); return entry; } } @@ -131,7 +128,7 @@ static void __ping_tjetty_clear(struct hlist_head *bucket) hlist_for_each_entry_safe(entry, tmp, bucket, node) { hlist_del(&entry->node); - __ping_tjetty_free_entry(&entry->kref); + ping_tjetty_free_entry(entry); kfree(entry); } } @@ -170,7 +167,7 @@ ping_tjetty_find_or_create(struct ubmgr_ping_ctx *ctx, if (entry_added != entry) { ubcore_log_info("Tjetty already imported. deid:" EID_FMT ".\n", EID_ARGS(*dst_eid)); - __ping_tjetty_free_entry(&entry->kref); + ping_tjetty_free_entry(entry); kfree(entry); return entry_added; } @@ -181,19 +178,17 @@ ping_tjetty_find_or_create(struct ubmgr_ping_ctx *ctx, static void ping_tjetty_put(struct ubmgr_ping_ctx *ctx, struct ubmgr_ping_tjetty_entry *entry) { - unsigned long flag; - bool last = false; - - spin_lock_irqsave(&ctx->tjetty_lock, flag); - if (kref_read(&entry->kref) == 1) { + /* + * Drop the reference and, when it was the last one, remove the entry + * from the hash before the jetty is unimported: the lookup side holds + * the same lock, so it can no longer find an entry that is going away. + */ + if (refcount_dec_and_lock(&entry->ref, &ctx->tjetty_lock)) { hlist_del(&entry->node); - last = true; - } - spin_unlock_irqrestore(&ctx->tjetty_lock, flag); - - kref_put(&entry->kref, __ping_tjetty_free_entry); - if (last) + spin_unlock(&ctx->tjetty_lock); + ping_tjetty_free_entry(entry); kfree(entry); + } } static void ping_tjetty_clear(struct ubmgr_ping_ctx *ctx)