A bunch of pending fixes/cleanups:

- Docs about limitation of having initiator and target on the same host updated + cleanups
 - Minor local thread storage improvements
 - TRACE_MGMT_MINOR excluded from the default set of trace flags to not confuse people
 - Dedicated kmem_cache for blockio created



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@662 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-02-04 18:45:32 +00:00
parent e4d19dd1da
commit a34ec0f7ff
11 changed files with 102 additions and 53 deletions

View File

@@ -136,7 +136,7 @@ IMPORTANT: All LUN information (access control) MUST be configured
Also see SCST README file how to tune for the best performance.
CAUTION: Working of target and initiator on the same host isn't
CAUTION: Working of target and initiator on the same host isn't fully
======= supported. See SCST README file for details.

View File

@@ -71,7 +71,7 @@ IMPORTANT: All LUN information (access control) MUST be configured
Also see SCST README file how to tune for the best performance.
CAUTION: Working of target and initiator on the same host isn't
CAUTION: Working of target and initiator on the same host isn't fully
======= supported. See SCST README file for details.

View File

@@ -112,13 +112,19 @@ IMPORTANT: Without loading appropriate device handler, corresponding devices
'echo "- - -" >/sys/class/scsi_host/hostX/scan',
where X - is the host number.
IMPORTANT: Working of target and initiator on the same host isn't
========= supported. This is a limitation of the Linux memory/cache
manager, because in this case an OOM deadlock like: system
IMPORTANT: Working of target and initiator on the same host is
========= supported, except the following 2 cases: swap over target exported
device and using a writable mmap over a file from target
exported device. The latter means you can't mount a file
system over target exported device. In other words, you can
freely use any sg, sd, st, etc. devices imported from target
on the same host, but you can't mount file systems or put
swap on them. This is a limitation of Linux memory/cache
manager, because in this case an OOM deadlock like: system
needs some memory -> it decides to clear some cache -> cache
needs to write on a target exported device -> initiator sends
request to the target -> target needs memory -> problem is
possible.
needs to write on target exported device -> initiator sends
request to the target -> target needs memory -> system needs
even more memory -> deadlock.
IMPORTANT: In the current version simultaneous access to local SCSI devices
========= via standard high-level SCSI drivers (sd, st, sg, etc.) and
@@ -863,7 +869,7 @@ Work if target's backstorage or link is too slow
------------------------------------------------
Under high I/O load, when your target's backstorage gets overloaded, or
working over a slow link between inititor and target, when the link
working over a slow link between initiator and target, when the link
can't serve all the queued commands on time, you can experience I/O
stalls or see in the kernel log abort or reset messages.
@@ -947,7 +953,7 @@ Note, that logged messages about QUEUE_FULL status are quite different
by nature. This is a normal work, just SCSI flow control in action.
Simply don't enable "mgmt_minor" logging level, or, alternatively, if
you are confident in the worst case performance of your back-end storage
or inititor-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
scst_priv.h to 64. Usually initiators don't try to push more commands on
the target.

View File

@@ -59,13 +59,19 @@ IMPORTANT: Without loading appropriate device handler, corresponding devices
'echo "- - -" >/sys/class/scsi_host/hostX/scan',
where X - is the host number.
IMPORTANT: Working of target and initiator on the same host isn't
========= supported. This is a limitation of the Linux memory/cache
manager, because in this case an OOM deadlock like: system
IMPORTANT: Working of target and initiator on the same host is
========= supported, except the following 2 cases: swap over target exported
device and using a writable mmap over a file from target
exported device. The latter means you can't mount a file
system over target exported device. In other words, you can
freely use any sg, sd, st, etc. devices imported from target
on the same host, but you can't mount file systems or put
swap on them. This is a limitation of Linux memory/cache
manager, because in this case an OOM deadlock like: system
needs some memory -> it decides to clear some cache -> cache
needs to write on a target exported device -> initiator sends
request to the target -> target needs memory -> problem is
possible.
needs to write on target exported device -> initiator sends
request to the target -> target needs memory -> system needs
even more memory -> deadlock.
IMPORTANT: In the current version simultaneous access to local SCSI devices
========= via standard high-level SCSI drivers (sd, st, sg, etc.) and
@@ -798,7 +804,7 @@ Work if target's backstorage or link is too slow
------------------------------------------------
Under high I/O load, when your target's backstorage gets overloaded, or
working over a slow link between inititor and target, when the link
working over a slow link between initiator and target, when the link
can't serve all the queued commands on time, you can experience I/O
stalls or see in the kernel log abort or reset messages.
@@ -882,7 +888,7 @@ Note, that logged messages about QUEUE_FULL status are quite different
by nature. This is a normal work, just SCSI flow control in action.
Simply don't enable "mgmt_minor" logging level, or, alternatively, if
you are confident in the worst case performance of your back-end storage
or inititor-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
scst_priv.h to 64. Usually initiators don't try to push more commands on
the target.

View File

@@ -1455,7 +1455,7 @@ struct scst_device {
struct scst_thr_data_hdr {
/* List entry in tgt_dev->thr_data_list */
struct list_head thr_data_list_entry;
pid_t pid; /* PID of the owner thread */
struct task_struct *owner_thr; /* the owner thread */
atomic_t ref;
/* Function that will be called on the tgt_dev destruction */
void (*free_fn) (struct scst_thr_data_hdr *data);
@@ -2658,8 +2658,16 @@ void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev);
/* Deletes all local to threads data from all tgt_dev's of the dev */
void scst_dev_del_all_thr_data(struct scst_device *dev);
/* Finds local to the thread data. Returns NULL, if they not found. */
struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
struct task_struct *tsk);
/* Finds local to the current thread data. Returns NULL, if they not found. */
struct scst_thr_data_hdr *scst_find_thr_data(struct scst_tgt_dev *tgt_dev);
static inline struct scst_thr_data_hdr *scst_find_thr_data(
struct scst_tgt_dev *tgt_dev)
{
return __scst_find_thr_data(tgt_dev, current);
}
static inline void scst_thr_data_get(struct scst_thr_data_hdr *data)
{

View File

@@ -226,6 +226,7 @@ struct scst_vdisk_thr {
};
static struct kmem_cache *vdisk_thr_cachep;
static struct kmem_cache *blockio_work_cachep;
#define DEF_NUM_THREADS 5
static int num_threads = DEF_NUM_THREADS;
@@ -2326,19 +2327,19 @@ out:
return;
}
struct blockio_work {
struct scst_blockio_work {
atomic_t bios_inflight;
struct scst_cmd *cmd;
};
static inline void blockio_check_finish(struct blockio_work *blockio_work)
static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
{
/* Decrement the bios in processing, and if zero signal completion */
if (atomic_dec_and_test(&blockio_work->bios_inflight)) {
blockio_work->cmd->completed = 1;
blockio_work->cmd->scst_cmd_done(blockio_work->cmd,
SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT_ATOMIC);
kfree(blockio_work);
kmem_cache_free(blockio_work_cachep, blockio_work);
}
return;
}
@@ -2349,7 +2350,7 @@ static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
static void blockio_endio(struct bio *bio, int error)
#endif
{
struct blockio_work *blockio_work = bio->bi_private;
struct scst_blockio_work *blockio_work = bio->bi_private;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
if (bio->bi_size)
@@ -2395,7 +2396,7 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
uint8_t *address;
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
int need_new_bio;
struct blockio_work *blockio_work;
struct scst_blockio_work *blockio_work;
int bios = 0;
TRACE_ENTRY();
@@ -2404,7 +2405,7 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
goto out;
/* Allocate and initialize blockio_work struct */
blockio_work = kmalloc(sizeof(*blockio_work), GFP_KERNEL);
blockio_work = kmem_cache_alloc(blockio_work_cachep, GFP_KERNEL);
if (blockio_work == NULL)
goto out_no_mem;
@@ -2506,7 +2507,7 @@ out_no_bio:
hbio = hbio->bi_next;
bio_put(bio);
}
kfree(blockio_work);
kmem_cache_free(blockio_work_cachep, blockio_work);
out_no_mem:
scst_set_busy(cmd);
@@ -3561,6 +3562,12 @@ static int __init init_scst_vdisk_driver(void)
goto out;
}
blockio_work_cachep = KMEM_CACHE(scst_blockio_work, SCST_SLAB_FLAGS);
if (blockio_work_cachep == NULL) {
res = -ENOMEM;
goto out_free_vdisk_cache;
}
if (num_threads < 1) {
PRINT_ERROR("num_threads can not be less than 1, use "
"default %d", DEF_NUM_THREADS);
@@ -3601,6 +3608,9 @@ out_free_vdisk:
exit_scst_vdisk(&vdisk_file_devtype, &vdisk_dev_list);
out_free_slab:
kmem_cache_destroy(blockio_work_cachep);
out_free_vdisk_cache:
kmem_cache_destroy(vdisk_thr_cachep);
goto out;
}
@@ -3611,6 +3621,7 @@ static void __exit exit_scst_vdisk_driver(void)
exit_scst_vdisk(&vdisk_blk_devtype, &vdisk_dev_list);
exit_scst_vdisk(&vdisk_file_devtype, &vdisk_dev_list);
exit_scst_vdisk(&vcdrom_devtype, &vcdrom_dev_list);
kmem_cache_destroy(blockio_work_cachep);
kmem_cache_destroy(vdisk_thr_cachep);
}

View File

@@ -2724,8 +2724,8 @@ void scst_process_reset(struct scst_device *dev,
if (dev->dev_reserved) {
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
dev_tgt_dev_list_entry) {
TRACE(TRACE_MGMT, "Clearing RESERVE'ation for tgt_dev "
"lun %lld",
TRACE(TRACE_MGMT_MINOR, "Clearing RESERVE'ation for "
"tgt_dev lun %lld",
(long long unsigned int)tgt_dev->lun);
clear_bit(SCST_TGT_DEV_RESERVED,
&tgt_dev->tgt_dev_flags);
@@ -2800,7 +2800,7 @@ int scst_set_pending_UA(struct scst_cmd *cmd)
TRACE_ENTRY();
TRACE(TRACE_MGMT, "Setting pending UA cmd %p", cmd);
TRACE(TRACE_MGMT_MINOR, "Setting pending UA cmd %p", cmd);
spin_lock_bh(&cmd->tgt_dev->tgt_dev_lock);
@@ -2935,7 +2935,7 @@ void __scst_dev_check_set_UA(struct scst_device *dev,
{
TRACE_ENTRY();
TRACE(TRACE_MGMT, "Processing UA dev %p", dev);
TRACE(TRACE_MGMT_MINOR, "Processing UA dev %p", dev);
/* Check for reset UA */
if (sense[12] == SCST_SENSE_ASC_UA_RESET)
@@ -3044,7 +3044,7 @@ void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
struct scst_thr_data_hdr *data,
void (*free_fn) (struct scst_thr_data_hdr *data))
{
data->pid = current->pid;
data->owner_thr = current;
atomic_set(&data->ref, 1);
EXTRACHECKS_BUG_ON(free_fn == NULL);
data->free_fn = free_fn;
@@ -3091,14 +3091,14 @@ void scst_dev_del_all_thr_data(struct scst_device *dev)
}
EXPORT_SYMBOL(scst_dev_del_all_thr_data);
struct scst_thr_data_hdr *scst_find_thr_data(struct scst_tgt_dev *tgt_dev)
struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
struct task_struct *tsk)
{
struct scst_thr_data_hdr *res = NULL, *d;
struct task_struct *tsk = current;
spin_lock(&tgt_dev->thr_data_lock);
list_for_each_entry(d, &tgt_dev->thr_data_list, thr_data_list_entry) {
if (d->pid == tsk->pid) {
if (d->owner_thr == tsk) {
res = d;
scst_thr_data_get(res);
break;
@@ -3107,7 +3107,7 @@ struct scst_thr_data_hdr *scst_find_thr_data(struct scst_tgt_dev *tgt_dev)
spin_unlock(&tgt_dev->thr_data_lock);
return res;
}
EXPORT_SYMBOL(scst_find_thr_data);
EXPORT_SYMBOL(__scst_find_thr_data);
/* dev_lock supposed to be held and BH disabled */
void __scst_block_dev(struct scst_device *dev)

View File

@@ -1209,13 +1209,28 @@ void scst_del_dev_threads(struct scst_device *dev, int num)
TRACE_ENTRY();
list_for_each_entry_safe(ct, tmp, &dev->threads_list,
list_for_each_entry_safe_reverse(ct, tmp, &dev->threads_list,
thread_list_entry) {
int rc = kthread_stop(ct->cmd_thread);
int rc;
struct scst_tgt_dev *tgt_dev;
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
dev_tgt_dev_list_entry) {
struct scst_thr_data_hdr *td;
td = __scst_find_thr_data(tgt_dev, ct->cmd_thread);
if (td != NULL) {
scst_thr_data_put(td);
break;
}
}
rc = kthread_stop(ct->cmd_thread);
if (rc < 0)
TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
list_del(&ct->thread_list_entry);
kfree(ct);
if ((num > 0) && (++i >= num))
break;
}

View File

@@ -52,14 +52,11 @@ extern unsigned long scst_trace_flag;
#endif
#ifdef CONFIG_SCST_DEBUG
/*#define SCST_DEFAULT_LOG_FLAGS (TRACE_ALL & ~TRACE_MEMORY & ~TRACE_BUFF \
& ~TRACE_FUNCTION)
#define SCST_DEFAULT_LOG_FLAGS (TRACE_ALL & ~TRACE_MEMORY & ~TRACE_BUFF & \
~TRACE_SCSI & ~TRACE_SCSI_SERIALIZING & ~TRACE_DEBUG)
*/
/* TRACE_MGMT_MINOR disabled to not confuse regular users */
#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_PID | \
TRACE_LINE | TRACE_FUNCTION | TRACE_SPECIAL | TRACE_MGMT | \
TRACE_MGMT_MINOR | TRACE_MGMT_DEBUG | TRACE_RTRY)
/*TRACE_MGMT_MINOR |*/ TRACE_MGMT_DEBUG | TRACE_RTRY)
#define TRACE_RETRY(args...) __TRACE(TRACE_RTRY, args)
#define TRACE_SN(args...) __TRACE(TRACE_SCSI_SERIALIZING, args)
@@ -71,7 +68,8 @@ extern unsigned long scst_trace_flag;
#else /* CONFIG_SCST_DEBUG */
# ifdef CONFIG_SCST_TRACING
#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_SPECIAL)
#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_MGMT | \
TRACE_SPECIAL)
# else
#define SCST_DEFAULT_LOG_FLAGS 0
# endif

View File

@@ -4475,11 +4475,11 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
TRACE_ENTRY();
if (nexus_loss) {
TRACE(TRACE_MGMT, "Nexus loss for sess %p (mcmd %p)", sess,
mcmd);
TRACE(TRACE_MGMT_MINOR, "Nexus loss for sess %p (mcmd %p)",
sess, mcmd);
} else {
TRACE(TRACE_MGMT, "Aborting all from sess %p (mcmd %p)", sess,
mcmd);
TRACE(TRACE_MGMT_MINOR, "Aborting all from sess %p (mcmd %p)",
sess, mcmd);
}
if (mcmd->fn != SCST_UNREG_SESS_TM)
@@ -4557,11 +4557,11 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
TRACE_ENTRY();
if (nexus_loss) {
TRACE(TRACE_MGMT, "I_T Nexus loss (tgt %p, mcmd %p)", tgt,
mcmd);
TRACE(TRACE_MGMT_MINOR, "I_T Nexus loss (tgt %p, mcmd %p)",
tgt, mcmd);
} else {
TRACE(TRACE_MGMT, "Aborting all from tgt %p (mcmd %p)", tgt,
mcmd);
TRACE(TRACE_MGMT_MINOR, "Aborting all from tgt %p (mcmd %p)",
tgt, mcmd);
}
mcmd->needs_unblocking = 1;

View File

@@ -9,6 +9,11 @@ No assumptions are made in the code about the device types on the target, so
any device handlers that you load in SCST should be visible, including tapes
and so forth.
You can freely use any sg, sd, st, etc. devices imported from target,
except the following: you can't mount file systems or put swap on them.
This is a limitation of Linux memory/cache manager. See SCST README file
for details.
To build, simply issue 'make' in the scst-local directory.
Try 'modinfo scst_local' for a listing of module parameters so far.