From 53fdc293e25190a7712d214a17c30b6a02189bee Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 10 Mar 2019 01:18:17 +0000 Subject: [PATCH] scst: Use a per-cpu counter for sessions Make scst_alloc_session() initialize sess->refcnt to 1 instead of 0. Compensate this by removing an scst_get() call from __scst_register_session(). git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8026 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 2 +- scst/src/scst_lib.c | 22 +++++++++++++++++++--- scst/src/scst_main.c | 2 ++ scst/src/scst_priv.h | 9 ++------- scst/src/scst_targ.c | 5 ++--- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index a3f608932..fec636745 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -1909,7 +1909,7 @@ struct scst_session { spinlock_t sess_list_lock; /* protects sess_cmd_list, etc */ - atomic_t refcnt; /* get/put counter */ + struct percpu_ref refcnt; /* get/put counter */ /* * Alive commands for this session. ToDo: make it part of the common diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index d726c84e7..4dd415c08 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -6995,11 +6995,18 @@ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev) return; } +static void scst_sess_release(struct percpu_ref *ref) +{ + struct scst_session *sess = container_of(ref, typeof(*sess), refcnt); + + scst_sched_session_free(sess); +} + struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask, const char *initiator_name) { struct scst_session *sess; - int i; + int i, ret; TRACE_ENTRY(); @@ -7011,7 +7018,11 @@ struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask, sess->init_phase = SCST_SESS_IPH_INITING; sess->shut_phase = SCST_SESS_SPH_READY; - atomic_set(&sess->refcnt, 0); + ret = percpu_ref_init(&sess->refcnt, scst_sess_release, + PERCPU_REF_INIT_ATOMIC, GFP_KERNEL); + if (ret < 0) + goto out_free; + percpu_ref_switch_to_percpu(&sess->refcnt); mutex_init(&sess->tgt_dev_list_mutex); for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { struct list_head *head = &sess->sess_tgt_dev_list[i]; @@ -7038,7 +7049,7 @@ struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask, sess->initiator_name = kstrdup(initiator_name, gfp_mask); if (sess->initiator_name == NULL) { PRINT_ERROR("%s", "Unable to dup sess->initiator_name"); - goto out_free; + goto out_free_refcnt; } if (atomic_read(&scst_measure_latency)) { @@ -7054,6 +7065,9 @@ out: out_free_name: kfree(sess->initiator_name); +out_free_refcnt: + percpu_ref_exit(&sess->refcnt); + out_free: kmem_cache_free(scst_sess_cachep, sess); sess = NULL; @@ -7103,6 +7117,8 @@ void scst_free_session(struct scst_session *sess) if (sess->sess_name != sess->initiator_name) kfree(sess->sess_name); + percpu_ref_exit(&sess->refcnt); + kmem_cache_free(scst_sess_cachep, sess); TRACE_EXIT(); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 2c662ae8f..8941186e0 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -2676,6 +2676,8 @@ static void __exit exit_scst(void) scst_event_exit(); + rcu_barrier(); + #define DEINIT_CACHEP(p) do { \ kmem_cache_destroy(p); \ p = NULL; \ diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 9b1edb170..e0d378e0e 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -720,17 +720,12 @@ void scst_sched_session_free(struct scst_session *sess); static inline void scst_sess_get(struct scst_session *sess) { - atomic_inc(&sess->refcnt); - TRACE_DBG("Incrementing sess %p refcnt (new value %d)", - sess, atomic_read(&sess->refcnt)); + percpu_ref_get(&sess->refcnt); } static inline void scst_sess_put(struct scst_session *sess) { - TRACE_DBG("Decrementing sess %p refcnt (new value %d)", - sess, atomic_read(&sess->refcnt)-1); - if (atomic_dec_and_test(&sess->refcnt)) - scst_sched_session_free(sess); + percpu_ref_put(&sess->refcnt); } struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 53aa4c651..b06826b51 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -8173,7 +8173,6 @@ static struct scst_session *__scst_register_session(struct scst_tgt *tgt, int at scst_sess_set_tgt_priv(sess, tgt_priv); sess->sess_mq = mq; - scst_sess_get(sess); /* one for registered session */ scst_sess_get(sess); /* one held until sess is inited */ if (atomic) { @@ -8372,7 +8371,7 @@ void scst_unregister_session(struct scst_session *sess, int wait, spin_unlock_irqrestore(&scst_mgmt_lock, flags); - scst_sess_put(sess); + percpu_ref_kill(&sess->refcnt); if (wait) { TRACE_DBG("Waiting for session %p to complete", sess); @@ -8464,7 +8463,7 @@ int scst_global_mgmt_thread(void *arg) switch (sess->shut_phase) { case SCST_SESS_SPH_SHUTDOWN: - sBUG_ON(atomic_read(&sess->refcnt) != 0); + sBUG_ON(!percpu_ref_is_zero(&sess->refcnt)); scst_free_session_callback(sess); break; default: