mirror of
https://github.com/SCST-project/scst.git
synced 2026-06-09 23:22:33 +00:00
Merge branch 'svn-trunk'
This commit is contained in:
+7
-5
@@ -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
|
||||
@@ -2876,11 +2876,13 @@ struct scst_device {
|
||||
/* Device lock */
|
||||
spinlock_t dev_lock ____cacheline_aligned_in_smp;
|
||||
|
||||
#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
|
||||
/* How many cmds alive on this dev */
|
||||
atomic_t dev_cmd_count;
|
||||
#endif
|
||||
/* One more than the number of commands associated with this device. */
|
||||
struct percpu_ref dev_cmd_count;
|
||||
|
||||
struct work_struct free_work;
|
||||
|
||||
struct completion *dev_freed_cmpl;
|
||||
|
||||
/*
|
||||
* Maximum count of uncompleted commands that an initiator could
|
||||
* queue on this device. Then it will start getting TASK QUEUE FULL
|
||||
|
||||
@@ -2547,7 +2547,6 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be held and activities suspended */
|
||||
static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun)
|
||||
{
|
||||
int res, i;
|
||||
@@ -2556,7 +2555,6 @@ static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_assert_activity_suspended();
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
TRACE_DBG("dev %s, LUN %ld", dev->virt_name, (unsigned long)lun);
|
||||
@@ -2709,14 +2707,12 @@ out_unblock:
|
||||
goto out_resume;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be held and activities suspended */
|
||||
int scst_cm_on_dev_register(struct scst_device *dev)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_assert_activity_suspended();
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
if (!scst_auto_cm_assignment || !dev->handler->auto_cm_assignment_possible)
|
||||
|
||||
+65
-12
@@ -4181,15 +4181,41 @@ static int scst_dif_none_type1(struct scst_cmd *cmd);
|
||||
#define scst_dif_none_type1 scst_dif_none
|
||||
#endif
|
||||
|
||||
/* Called under scst_mutex and suspended activity */
|
||||
int scst_alloc_device(gfp_t gfp_mask, int nodeid,
|
||||
struct scst_device **out_dev)
|
||||
/* Called from thread context and hence may sleep. */
|
||||
static void scst_finally_free_device(struct work_struct *work)
|
||||
{
|
||||
struct scst_device *dev = container_of(work, typeof(*dev),
|
||||
free_work);
|
||||
struct completion *c = dev->dev_freed_cmpl;
|
||||
|
||||
scst_pr_cleanup(dev);
|
||||
|
||||
kfree(dev->virt_name);
|
||||
percpu_ref_exit(&dev->dev_cmd_count);
|
||||
kmem_cache_free(scst_dev_cachep, dev);
|
||||
|
||||
if (c)
|
||||
complete(c);
|
||||
}
|
||||
|
||||
/* RCU callback. Must not sleep. */
|
||||
static void scst_release_device(struct percpu_ref *ref)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
|
||||
dev = container_of(ref, typeof(*dev), dev_cmd_count);
|
||||
schedule_work(&dev->free_work);
|
||||
}
|
||||
|
||||
int scst_alloc_device(gfp_t gfp_mask, int nodeid, struct scst_device **out_dev)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
dev = kmem_cache_alloc_node(scst_dev_cachep, gfp_mask, nodeid);
|
||||
if (dev == NULL) {
|
||||
PRINT_ERROR("%s", "Allocation of scst_device failed");
|
||||
@@ -4199,8 +4225,13 @@ int scst_alloc_device(gfp_t gfp_mask, int nodeid,
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
dev->handler = &scst_null_devtype;
|
||||
#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
|
||||
atomic_set(&dev->dev_cmd_count, 0);
|
||||
INIT_WORK(&dev->free_work, scst_finally_free_device);
|
||||
res = percpu_ref_init(&dev->dev_cmd_count, scst_release_device,
|
||||
PERCPU_REF_INIT_ATOMIC, GFP_KERNEL);
|
||||
if (res < 0)
|
||||
goto free_dev;
|
||||
#ifndef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
|
||||
percpu_ref_switch_to_percpu(&dev->dev_cmd_count);
|
||||
#endif
|
||||
scst_init_mem_lim(&dev->dev_mem_lim);
|
||||
spin_lock_init(&dev->dev_lock);
|
||||
@@ -4234,10 +4265,16 @@ int scst_alloc_device(gfp_t gfp_mask, int nodeid,
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
free_dev:
|
||||
kmem_cache_free(scst_dev_cachep, dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void scst_free_device(struct scst_device *dev)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(c);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
EXTRACHECKS_BUG_ON(dev->dev_scsi_atomic_cmd_active != 0);
|
||||
@@ -4257,11 +4294,11 @@ void scst_free_device(struct scst_device *dev)
|
||||
|
||||
scst_deinit_threads(&dev->dev_cmd_threads);
|
||||
|
||||
scst_pr_cleanup(dev);
|
||||
|
||||
kfree(dev->virt_name);
|
||||
kmem_cache_free(scst_dev_cachep, dev);
|
||||
dev->dev_freed_cmpl = &c;
|
||||
percpu_ref_kill(&dev->dev_cmd_count);
|
||||
|
||||
wait_for_completion(&c);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
@@ -6995,11 +7032,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 +7055,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 +7086,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 +7102,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 +7154,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();
|
||||
|
||||
@@ -1347,10 +1347,6 @@ int scst_register_virtual_device_node(struct scst_dev_type *dev_handler,
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = scst_suspend_activity(SCST_SUSPEND_TIMEOUT_USER);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = mutex_lock_interruptible(&scst_mutex);
|
||||
if (res != 0)
|
||||
goto out_resume;
|
||||
@@ -1419,7 +1415,6 @@ int scst_register_virtual_device_node(struct scst_dev_type *dev_handler,
|
||||
goto out_unreg;
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_resume_activity();
|
||||
|
||||
res = dev->virt_id;
|
||||
|
||||
@@ -2681,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; \
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -4503,9 +4503,7 @@ static int scst_pre_xmit_response1(struct scst_cmd *cmd)
|
||||
*/
|
||||
smp_mb__before_atomic_dec();
|
||||
atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
|
||||
atomic_dec(&cmd->dev->dev_cmd_count);
|
||||
#endif
|
||||
percpu_ref_put(&cmd->dev->dev_cmd_count);
|
||||
if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
scst_on_hq_cmd_response(cmd);
|
||||
else if (unlikely(!cmd->sent_for_exec)) {
|
||||
@@ -5134,6 +5132,7 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
if (likely(res == 0)) {
|
||||
struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
unsigned long __percpu *a __maybe_unused;
|
||||
bool failure = false;
|
||||
int cnt;
|
||||
|
||||
@@ -5149,8 +5148,10 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
failure = true;
|
||||
}
|
||||
|
||||
percpu_ref_get(&dev->dev_cmd_count);
|
||||
#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
|
||||
cnt = atomic_inc_return(&dev->dev_cmd_count);
|
||||
sBUG_ON(__ref_is_percpu(&dev->dev_cmd_count, &a));
|
||||
cnt = atomic_long_read(&dev->dev_cmd_count.count);
|
||||
if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
|
||||
if (!failure) {
|
||||
TRACE(TRACE_FLOW_CONTROL,
|
||||
@@ -8173,7 +8174,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 +8372,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 +8464,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:
|
||||
|
||||
@@ -7,11 +7,12 @@ package SCST::SCST;
|
||||
# Copyright (c) 2005-2011 Mark R. Buechler
|
||||
# Copyright (c) 2011-2019 Bart Van Assche <bvanassche@acm.org>.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.005;
|
||||
use Fcntl ':mode';
|
||||
use IO::Handle;
|
||||
use IO::File;
|
||||
use strict;
|
||||
use Carp qw(cluck);
|
||||
|
||||
use POSIX;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $Version = 'SCST Configurator v3.3.0-pre1';
|
||||
|
||||
# Configures SCST
|
||||
@@ -242,7 +245,6 @@ Examples:
|
||||
EndUsage
|
||||
}
|
||||
|
||||
use strict;
|
||||
use Cwd qw(abs_path);
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
|
||||
Reference in New Issue
Block a user