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
This commit is contained in:
Bart Van Assche
2019-03-10 01:18:17 +00:00
parent 26d7fd0e3a
commit 53fdc293e2
5 changed files with 26 additions and 14 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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; \

View File

@@ -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,

View File

@@ -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: