From: <vl...@us...> - 2007-06-08 14:08:09
|
Revision: 127 http://svn.sourceforge.net/scst/?rev=127&view=rev Author: vlnb Date: 2007-06-08 07:08:06 -0700 (Fri, 08 Jun 2007) Log Message: ----------- Minor threads related fixes Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/scst.c trunk/scst/src/scst_lib.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-06-08 10:54:18 UTC (rev 126) +++ trunk/scst/include/scsi_tgt.h 2007-06-08 14:08:06 UTC (rev 127) @@ -1181,7 +1181,7 @@ /* Pointer to lists of commands with the lock */ struct scst_cmd_lists *p_cmd_lists; - /* Lists of commands with the lock, if dedicated threads are used */ + /* Lists of commands with lock, if dedicated threads are used */ struct scst_cmd_lists cmd_lists; /* How many cmds alive on this dev */ @@ -1257,8 +1257,11 @@ /* List of acg_dev's, one per acg, protected by scst_mutex */ struct list_head dev_acg_dev_list; - /* List of dedicated threads. Doesn't need any protection. */ + /* List of dedicated threads, protected by scst_mutex */ struct list_head threads_list; + + /* Device number */ + int dev_num; }; /* Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-06-08 10:54:18 UTC (rev 126) +++ trunk/scst/src/scst.c 2007-06-08 14:08:06 UTC (rev 127) @@ -898,17 +898,17 @@ int scst_add_dev_threads(struct scst_device *dev, int num) { int i, res = 0; - static atomic_t major = ATOMIC_INIT(0); - int N, n = 0; + int n = 0; + struct scst_cmd_thread_t *thr; char nm[12]; TRACE_ENTRY(); - N = atomic_inc_return(&major); + list_for_each_entry(thr, &dev->threads_list, thread_list_entry) { + n++; + } for (i = 0; i < num; i++) { - struct scst_cmd_thread_t *thr; - thr = kmalloc(sizeof(*thr), GFP_KERNEL); if (!thr) { res = -ENOMEM; @@ -918,7 +918,7 @@ strncpy(nm, dev->handler->name, ARRAY_SIZE(nm)-1); nm[ARRAY_SIZE(nm)-1] = '\0'; thr->cmd_thread = kthread_run(scst_cmd_thread, - &dev->cmd_lists, "%sd%d_%d", nm, N, n++); + &dev->cmd_lists, "%sd%d_%d", nm, dev->dev_num, n++); if (IS_ERR(thr->cmd_thread)) { res = PTR_ERR(thr->cmd_thread); PRINT_ERROR_PR("kthread_create() failed: %d", res); Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-06-08 10:54:18 UTC (rev 126) +++ trunk/scst/src/scst_lib.c 2007-06-08 14:08:06 UTC (rev 127) @@ -150,6 +150,7 @@ { struct scst_device *dev; int res = 0; + static int dev_num; /* protected by scst_mutex */ TRACE_ENTRY(); @@ -172,6 +173,7 @@ init_waitqueue_head(&dev->on_dev_waitQ); dev->dev_double_ua_possible = 1; dev->dev_serialized = 1; + dev->dev_num = dev_num++; *out_dev = dev; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-06-27 16:19:45
|
Revision: 138 http://svn.sourceforge.net/scst/?rev=138&view=rev Author: vlnb Date: 2007-06-27 09:19:38 -0700 (Wed, 27 Jun 2007) Log Message: ----------- Patch from Alessandro Premoli fixes all the warnings of scst on 64-bit platforms Modified Paths: -------------- trunk/scst/README trunk/scst/include/scst_debug.h trunk/scst/src/dev_handlers/scst_dev_handler.h trunk/scst/src/dev_handlers/scst_user.c trunk/scst/src/scst.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_mem.c trunk/scst/src/scst_proc.c trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/README 2007-06-27 16:19:38 UTC (rev 138) @@ -621,4 +621,6 @@ * Michael G. Byrnes <mic...@hp...> for fixes. + * Alessandro Premoli <a.p...@an...> for fixes + Vladislav Bolkhovitin <vs...@vl...>, http://scst.sourceforge.net Modified: trunk/scst/include/scst_debug.h =================================================================== --- trunk/scst/include/scst_debug.h 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/include/scst_debug.h 2007-06-27 16:19:38 UTC (rev 138) @@ -21,6 +21,7 @@ #define __SCST_DEBUG_H #include <linux/autoconf.h> /* for CONFIG_* */ +#include <asm/bug.h> /* for WARN_ON_ONCE */ #if !defined(EXTRACHECKS) && defined(CONFIG_SCSI_TARGET_EXTRACHECKS) #define EXTRACHECKS Modified: trunk/scst/src/dev_handlers/scst_dev_handler.h =================================================================== --- trunk/scst/src/dev_handlers/scst_dev_handler.h 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/dev_handlers/scst_dev_handler.h 2007-06-27 16:19:38 UTC (rev 138) @@ -42,7 +42,7 @@ return res; } -static int scst_dev_handler_proc_log_entry_write(struct file *file, +static ssize_t scst_dev_handler_proc_log_entry_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res = 0; Modified: trunk/scst/src/dev_handlers/scst_user.c =================================================================== --- trunk/scst/src/dev_handlers/scst_user.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/dev_handlers/scst_user.c 2007-06-27 16:19:38 UTC (rev 138) @@ -26,7 +26,7 @@ #include "scst_user.h" #include "scst_dev_handler.h" -#ifndef CONFIG_NOHIGHMEM +#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) #warning HIGHMEM kernel configurations are not supported. Consider \ changing VMSPLIT option or using 64-bit configuration. #endif @@ -2927,7 +2927,7 @@ TRACE_ENTRY(); -#ifndef CONFIG_NOHIGHMEM +#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) PRINT_ERROR_PR("%s", "HIGHMEM kernel configurations are not supported. " "Consider changing VMSPLIT option or using 64-bit " "configuration."); Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/scst.c 2007-06-27 16:19:38 UTC (rev 138) @@ -32,7 +32,7 @@ #include "scst_priv.h" #include "scst_mem.h" -#ifndef CONFIG_NOHIGHMEM +#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) #warning HIGHMEM kernel configurations are supported, but not recommended. \ Consider changing VMSPLIT option or using 64-bit configuration instead. #endif Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/scst_lib.c 2007-06-27 16:19:38 UTC (rev 138) @@ -1622,7 +1622,7 @@ op = *cdb_p; /* get clear opcode */ - TRACE_DBG("opcode=%02x, cdblen=%d bytes, tblsize=%zd, " + TRACE_DBG("opcode=%02x, cdblen=%d bytes, tblsize=%d, " "dev_type=%d", op, SCST_GET_CDB_LEN(op), SCST_CDB_TBL_SIZE, dev_type); @@ -1854,7 +1854,7 @@ cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd); } - TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d", + TRACE_DBG("res %d, bufflen %d, data_len %d, direct %d", res, cmd->bufflen, cmd->data_len, cmd->data_direction); TRACE_EXIT_RES(res); @@ -1915,7 +1915,7 @@ if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED) cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd); - TRACE_DBG("res %d bufflen %zd direct %d", + TRACE_DBG("res %d bufflen %d direct %d", res, cmd->bufflen, cmd->data_direction); TRACE_EXIT(); @@ -1976,7 +1976,7 @@ if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED) cmd->bufflen = info_cdb->transfer_len << get_block_shift(cmd); - TRACE_DBG("res %d bufflen %zd direct %d", + TRACE_DBG("res %d bufflen %d direct %d", res, cmd->bufflen, cmd->data_direction); TRACE_EXIT_RES(res); @@ -2043,7 +2043,7 @@ break; } #endif - TRACE_DBG("res %d bufflen %zd direct %d", + TRACE_DBG("res %d bufflen %d direct %d", res, cmd->bufflen, cmd->data_direction); TRACE_EXIT(); Modified: trunk/scst/src/scst_mem.c =================================================================== --- trunk/scst/src/scst_mem.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/scst_mem.c 2007-06-27 16:19:38 UTC (rev 138) @@ -556,7 +556,7 @@ out: TRACE_MEM("Alloced sg %p (count %d)", res, *count); - TRACE_EXIT_HRES((int)res); + TRACE_EXIT_HRES(res); return res; out_free: Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/scst_proc.c 2007-06-27 16:19:38 UTC (rev 138) @@ -351,7 +351,7 @@ return res; } -static int scst_proc_scsi_tgt_gen_write_log(struct file *file, const char __user *buf, +static ssize_t scst_proc_scsi_tgt_gen_write_log(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res; @@ -736,7 +736,7 @@ TRACE_EXIT(); } -static int scst_proc_threads_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_threads_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res = length; @@ -883,7 +883,7 @@ return; } -static int scst_proc_scsi_tgt_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_scsi_tgt_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { struct scst_tgt *vtt = (struct scst_tgt *)PDE(file->f_dentry->d_inode)->data; @@ -1023,7 +1023,7 @@ return; } -static int scst_proc_scsi_dev_handler_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_scsi_dev_handler_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { struct scst_dev_type *dev_type = (struct scst_dev_type *)PDE(file->f_dentry->d_inode)->data; @@ -1083,7 +1083,7 @@ return res; } -static int scst_proc_scsi_tgt_gen_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res = length, rc = 0, action; @@ -1210,7 +1210,7 @@ { int res = 0; char *p = buf, *e, *ee; - unsigned int host, channel = 0, id = 0, lun = 0; + unsigned long host, channel = 0, id = 0, lun = 0; struct scst_device *d, *dev = NULL; struct scst_dev_type *dt, *handler = NULL; @@ -1247,7 +1247,7 @@ } *ee = '\0'; - TRACE_DBG("Dev %d:%d:%d:%d, handler %s", host, channel, id, lun, e); + TRACE_DBG("Dev %ld:%ld:%ld:%ld, handler %s", host, channel, id, lun, e); list_for_each_entry(d, &scst_dev_list, dev_list_entry) { if ((d->virt_id == 0) && @@ -1257,14 +1257,14 @@ d->scsi_dev->lun == lun) { dev = d; - TRACE_DBG("Dev %p (%d:%d:%d:%d) found", + TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found", dev, host, channel, id, lun); break; } } if (dev == NULL) { - PRINT_ERROR_PR("Device %d:%d:%d:%d not found", + PRINT_ERROR_PR("Device %ld:%ld:%ld:%ld not found", host, channel, id, lun); res = -EINVAL; goto out; @@ -1305,7 +1305,7 @@ goto out; } -static int scst_proc_groups_devices_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_groups_devices_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res = length, action, virt = 0, rc, read_only = 0; @@ -1499,7 +1499,7 @@ return res; } -static int scst_proc_groups_names_write(struct file *file, const char __user *buf, +static ssize_t scst_proc_groups_names_write(struct file *file, const char __user *buf, size_t length, loff_t *off) { int res = length, action; Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-06-27 10:41:44 UTC (rev 137) +++ trunk/scst/src/scst_targ.c 2007-06-27 16:19:38 UTC (rev 138) @@ -402,7 +402,7 @@ if (scst_cmd_is_expected_set(cmd)) { if (cmd->expected_transfer_len < cmd->bufflen) { TRACE(TRACE_SCSI, "cmd->expected_transfer_len(%d) < " - "cmd->bufflen(%zd), using expected_transfer_len " + "cmd->bufflen(%d), using expected_transfer_len " "instead", cmd->expected_transfer_len, cmd->bufflen); cmd->bufflen = cmd->expected_transfer_len; @@ -433,7 +433,7 @@ { PRINT_ERROR_PR("Dev handler %s parse() returned " "invalid cmd data_direction %d, " - "bufflen %zd or state %d (opcode 0x%x)", + "bufflen %d or state %d (opcode 0x%x)", dev->handler->name, cmd->data_direction, cmd->bufflen, state, cmd->cdb[0]); @@ -680,7 +680,7 @@ out_no_space: TRACE(TRACE_OUT_OF_MEM, "Unable to allocate or build requested buffer " - "(size %zd), sending BUSY or QUEUE FULL status", cmd->bufflen); + "(size %d), sending BUSY or QUEUE FULL status", cmd->bufflen); scst_low_cur_max_cmd_mem(); scst_set_busy(cmd); cmd->state = SCST_CMD_STATE_DEV_DONE; @@ -1765,7 +1765,7 @@ /* Optimized for lockless fast path */ - TRACE_SN("Slot %d, *cur_sn_slot %d", slot - tgt_dev->sn_slots, + TRACE_SN("Slot %zd, *cur_sn_slot %d", slot - tgt_dev->sn_slots, atomic_read(slot)); if (!atomic_dec_and_test(slot)) @@ -2521,7 +2521,7 @@ ARRAY_SIZE(tgt_dev->sn_slots)) tgt_dev->cur_sn_slot = tgt_dev->sn_slots; } while(atomic_read(tgt_dev->cur_sn_slot) != 0); - TRACE_SN("New cur SN slot %d", + TRACE_SN("New cur SN slot %zd", tgt_dev->cur_sn_slot-tgt_dev->sn_slots); } else tgt_dev->num_free_sn_slots++; @@ -2550,7 +2550,7 @@ TRACE_SN("cmd(%p)->sn: %ld (tgt_dev %p, *cur_sn_slot %d, " "num_free_sn_slots %d, prev_cmd_ordered %ld, " - "cur_sn_slot %d)", cmd, cmd->sn, tgt_dev, + "cur_sn_slot %zd)", cmd, cmd->sn, tgt_dev, atomic_read(tgt_dev->cur_sn_slot), tgt_dev->num_free_sn_slots, tgt_dev->prev_cmd_ordered, tgt_dev->cur_sn_slot-tgt_dev->sn_slots); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-05 14:37:40
|
Revision: 142 http://svn.sourceforge.net/scst/?rev=142&view=rev Author: vlnb Date: 2007-07-05 07:37:36 -0700 (Thu, 05 Jul 2007) Log Message: ----------- - Kernel patches were renamed (in this commit only deleted) - VDISK_ONLY was removed, SCSI_EXEC_REQ_FIFO_DEFINED, defined by corresponding kernel patch used instead - Minor fixes - Docs updates All users will need to revert old SCST kernel patch and apply the corresponding new one. Modified Paths: -------------- trunk/scst/README trunk/scst/src/Makefile trunk/scst/src/dev_handlers/scst_user.c trunk/scst/src/scst.c trunk/scst/src/scst_debug.c trunk/scst/src/scst_priv.h Added Paths: ----------- trunk/scst/kernel/old_unsupported/ Removed Paths: ------------- trunk/scst/kernel/26_scst-2.6.14-.patch trunk/scst/kernel/26_scst-2.6.15+.patch trunk/scst/kernel/26_scst-2.6.16.patch trunk/scst/kernel/26_scst-2.6.18.patch trunk/scst/kernel/26_scst-2.6.21.patch Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/README 2007-07-05 14:37:36 UTC (rev 142) @@ -22,7 +22,7 @@ devices as virtual remotely available SCSI disks or CDROMs with benefits of the Linux page cache - * BLOCKIO mode, which performsd irect block IO with a block device, + * BLOCKIO mode, which performs direct block IO with a block device, bypassing page-cache for all operations. This mode works ideally with high-end storage HBAs and for applications that either do not need caching between application and disk or need the large block @@ -53,11 +53,11 @@ Then, since in the mainstream kernels scsi_do_req()/scsi_execute_async() work in LIFO order, instead of expected and required FIFO, SCST needs a new functions scsi_do_req_fifo()/scsi_execute_async_fifo() to be added -in the kernel. Patch 26_scst-2.6.X.patch from "kernel" directory does -that. If it doesn't apply to your kernel, apply it manually, it only -adds one of those functions and nothing more. You may not patch the -kernel if STRICT_SERIALIZING or VDISK_ONLY are defined during the -compilation (see their description below). +in the kernel. Patch scst_exec_req_fifo.patch from "kernel" directory +does that. If it doesn't apply to your kernel, apply it manually, it +only adds one of those functions and nothing more. You may not patch the +kernel if you don't need pass-through support or STRICT_SERIALIZING is +defined during the compilation (see description below). To compile SCST type 'make'. It will build SCST itself and its device handlers. To install them type 'make install'. The driver modules will @@ -161,11 +161,6 @@ There are the following compilation options, that could be commented in/out in Makefile: - - VDISK_ONLY - if defined, the pass-through device handlers - (scst_disk, scst_tape) will not work, but SCST will not require the - kernel patching. Defined by default to ease new people try SCST on - their kernels. - - DEBUG - turns on some debugging code, including some logging. Makes the driver considerably bigger and slower, producing large amount of log data. @@ -196,17 +191,34 @@ patching is necessary. - SCST_HIGHMEM - if defined on HIGHMEM systems with 2.6 kernels, it - allows SCST to use HIGHMEM. This is very experimental feature and it - is unclear, if it brings something valuable, except some performance - hit, so in the current version it is disabled. Note, that + allows SCST to use HIGHMEM. This is very experimental feature, which + is currently broken and unsupported, since it is unclear, if it + brings something valuable, except some performance hit. Note, that SCST_HIGHMEM isn't required for HIGHMEM systems and SCST will work - fine on them with SCST_HIGHMEM off. Untested. + fine on them with SCST_HIGHMEM off. - - SCST_STRICT_SECURITY - if defined, makes SCST clean allocated data + - SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data buffers. Undefining it (default) considerably improves performance and eases CPU load, but could create a security hole (information leakage), so enable it, if you have strict security requirements. +HIGHMEM kernel configurations are fully supported, but not recommended +for performance reasons, except for scst_user, where they are not +supported, because this module deals with user supplied memory on a +zero-copy manner. Consider change VMSPLIT option or use 64-bit system +configuration instead. + +For changing VMSPLIT option (CONFIG_VMSPLIT to be precise) you should in +"make menuconfig" command set the following variables: + + - General setup->Configure standard kernel features (for small systems): ON + + - Processor type and features->High Memory Support: OFF + + - Processor type and features->Memory split: according to amount of + memory you have. If it is less than 800MB, you may not touch this + option at all. + Module parameters ----------------- @@ -491,7 +503,7 @@ same as BLOCKIO, but also supports files, so for some loads it could be significantly faster, than regular FILEIO access, provided by scst_vdisk. All the words about BLOCKIO from above apply to O_DIRECT as -well. While running fileio_tgt if you don't uderstand some its options, +well. While running fileio_tgt if you don't understand some its options, use defaults for them, those values are the fastest. Performance @@ -606,7 +618,7 @@ * Nathaniel Clark <na...@mi...> for fixes and comments. - * Calvin Morrow <cal...@co...> for testing and usful + * Calvin Morrow <cal...@co...> for testing and useful suggestions. * Hu Gang <hu...@so...> for the original version of the Deleted: trunk/scst/kernel/26_scst-2.6.14-.patch =================================================================== --- trunk/scst/kernel/26_scst-2.6.14-.patch 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/kernel/26_scst-2.6.14-.patch 2007-07-05 14:37:36 UTC (rev 142) @@ -1,77 +0,0 @@ ---- linux-2.6.12-rc6/drivers/scsi/scsi_lib.c_scst 2005-06-15 16:15:01.000000000 +0400 -+++ linux-2.6.12-rc6/drivers/scsi/scsi_lib.c 2005-06-23 20:28:20.802971272 +0400 -@@ -235,6 +235,61 @@ void scsi_do_req(struct scsi_request *sr - } - EXPORT_SYMBOL(scsi_do_req); - -+/* -+ * Function: scsi_do_req_fifo -+ * -+ * Purpose: Queue a SCSI request -+ * -+ * Arguments: sreq - command descriptor. -+ * cmnd - actual SCSI command to be performed. -+ * buffer - data buffer. -+ * bufflen - size of data buffer. -+ * done - completion function to be run. -+ * timeout - how long to let it run before timeout. -+ * retries - number of retries we allow. -+ * -+ * Lock status: No locks held upon entry. -+ * -+ * Returns: Nothing. -+ * -+ * Notes: This function is used for queueing requests in FIFO order. -+ * It is a copy of scsi_do_req() with only changed the last -+ * parameter of scsi_insert_special_req(). Not sure, if it -+ * breaks quiesce, but, anyway, I don't see another way to -+ * queue requests in FIFO order, which is necessary for SCST. -+ */ -+void scsi_do_req_fifo(struct scsi_request *sreq, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done)(struct scsi_cmnd *), -+ int timeout, int retries) -+{ -+ /* -+ * If the upper level driver is reusing these things, then -+ * we should release the low-level block now. Another one will -+ * be allocated later when this request is getting queued. -+ */ -+ __scsi_release_request(sreq); -+ -+ /* -+ * Our own function scsi_done (which marks the host as not busy, -+ * disables the timeout counter, etc) will be called by us or by the -+ * scsi_hosts[host].queuecommand() function needs to also call -+ * the completion function for the high level driver. -+ */ -+ memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd)); -+ sreq->sr_bufflen = bufflen; -+ sreq->sr_buffer = buffer; -+ sreq->sr_allowed = retries; -+ sreq->sr_done = done; -+ sreq->sr_timeout_per_command = timeout; -+ -+ if (sreq->sr_cmd_len == 0) -+ sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]); -+ -+ scsi_insert_special_req(sreq, 0); -+} -+EXPORT_SYMBOL(scsi_do_req_fifo); -+ - static void scsi_wait_done(struct scsi_cmnd *cmd) - { - struct request *req = cmd->request; ---- linux-2.6.12-rc6/include/scsi/scsi_request.h_scst 2005-06-23 20:08:59.475519880 +0400 -+++ linux-2.6.12-rc6/include/scsi/scsi_request.h 2005-06-23 20:08:26.881474928 +0400 -@@ -54,6 +54,10 @@ extern void scsi_do_req(struct scsi_requ - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -+extern void scsi_do_req_fifo(struct scsi_request *, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done) (struct scsi_cmnd *), -+ int timeout, int retries); - - struct scsi_mode_data { - __u32 length; Deleted: trunk/scst/kernel/26_scst-2.6.15+.patch =================================================================== --- trunk/scst/kernel/26_scst-2.6.15+.patch 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/kernel/26_scst-2.6.15+.patch 2007-07-05 14:37:36 UTC (rev 142) @@ -1,75 +0,0 @@ ---- linux-2.6.15.6/drivers/scsi/scsi_lib.c_scst 2006-03-05 22:07:54.000000000 +0300 -+++ linux-2.6.15.6/drivers/scsi/scsi_lib.c 2006-03-27 17:56:59.000000000 +0400 -@@ -254,6 +254,61 @@ - } - EXPORT_SYMBOL(scsi_do_req); - -+/* -+ * Function: scsi_do_req_fifo -+ * -+ * Purpose: Queue a SCSI request -+ * -+ * Arguments: sreq - command descriptor. -+ * cmnd - actual SCSI command to be performed. -+ * buffer - data buffer. -+ * bufflen - size of data buffer. -+ * done - completion function to be run. -+ * timeout - how long to let it run before timeout. -+ * retries - number of retries we allow. -+ * -+ * Lock status: No locks held upon entry. -+ * -+ * Returns: Nothing. -+ * -+ * Notes: This function is used for queueing requests in FIFO order. -+ * It is a copy of scsi_do_req() with only changed the last -+ * parameter of scsi_insert_special_req(). Not sure, if it -+ * breaks quiesce, but, anyway, I don't see another way to -+ * queue requests in FIFO order, which is necessary for SCST. -+ */ -+void scsi_do_req_fifo(struct scsi_request *sreq, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done)(struct scsi_cmnd *), -+ int timeout, int retries) -+{ -+ /* -+ * If the upper level driver is reusing these things, then -+ * we should release the low-level block now. Another one will -+ * be allocated later when this request is getting queued. -+ */ -+ __scsi_release_request(sreq); -+ -+ /* -+ * Our own function scsi_done (which marks the host as not busy, -+ * disables the timeout counter, etc) will be called by us or by the -+ * scsi_hosts[host].queuecommand() function needs to also call -+ * the completion function for the high level driver. -+ */ -+ memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd)); -+ sreq->sr_bufflen = bufflen; -+ sreq->sr_buffer = buffer; -+ sreq->sr_allowed = retries; -+ sreq->sr_done = done; -+ sreq->sr_timeout_per_command = timeout; -+ -+ if (sreq->sr_cmd_len == 0) -+ sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]); -+ -+ scsi_insert_special_req(sreq, 0); -+} -+EXPORT_SYMBOL(scsi_do_req_fifo); -+ - /** - * scsi_execute - insert request and wait for the result - * @sdev: scsi device ---- linux-2.6.15.6/include/scsi/scsi_request.h_scst 2006-03-27 17:54:21.000000000 +0400 -+++ linux-2.6.15.6/include/scsi/scsi_request.h 2006-03-27 17:56:00.000000000 +0400 -@@ -51,4 +51,8 @@ - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -+extern void scsi_do_req_fifo(struct scsi_request *, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done) (struct scsi_cmnd *), -+ int timeout, int retries); - #endif /* _SCSI_SCSI_REQUEST_H */ Deleted: trunk/scst/kernel/26_scst-2.6.16.patch =================================================================== --- trunk/scst/kernel/26_scst-2.6.16.patch 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/kernel/26_scst-2.6.16.patch 2007-07-05 14:37:36 UTC (rev 142) @@ -1,77 +0,0 @@ ---- linux-2.6.16/drivers/scsi/scsi_lib.c.orig 2006-03-20 00:53:29.000000000 -0500 -+++ linux-2.6.16/drivers/scsi/scsi_lib.c 2006-04-07 10:04:42.077637750 -0400 -@@ -227,6 +227,63 @@ void scsi_do_req(struct scsi_request *sr - } - EXPORT_SYMBOL(scsi_do_req); - -+/* -+ * Function: scsi_do_req_fifo -+ * -+ * Purpose: Queue a SCSI request -+ * -+ * Arguments: sreq - command descriptor. -+ * cmnd - actual SCSI command to be performed. -+ * buffer - data buffer. -+ * bufflen - size of data buffer. -+ * done - completion function to be run. -+ * timeout - how long to let it run before timeout. -+ * retries - number of retries we allow. -+ * -+ * Lock status: No locks held upon entry. -+ * -+ * Returns: Nothing. -+ * -+ * Notes: This function is used for queueing requests in FIFO order. -+ * It is a copy of scsi_do_req() with only changed the last -+ * parameter of scsi_insert_special_req(). Not sure, if it -+ * breaks quiesce, but, anyway, I don't see another way to -+ * queue requests in FIFO order, which is necessary for SCST. -+ */ -+void scsi_do_req_fifo(struct scsi_request *sreq, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done)(struct scsi_cmnd *), -+ int timeout, int retries) -+{ -+ /* -+ * If the upper level driver is reusing these things, then -+ * we should release the low-level block now. Another one will -+ * be allocated later when this request is getting queued. -+ */ -+ __scsi_release_request(sreq); -+ -+ /* -+ * Our own function scsi_done (which marks the host as not busy, -+ * disables the timeout counter, etc) will be called by us or by the -+ * scsi_hosts[host].queuecommand() function needs to also call -+ * the completion function for the high level driver. -+ */ -+ memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd)); -+ sreq->sr_bufflen = bufflen; -+ sreq->sr_buffer = buffer; -+ sreq->sr_allowed = retries; -+ sreq->sr_done = done; -+ sreq->sr_timeout_per_command = timeout; -+ -+ if (sreq->sr_cmd_len == 0) -+ sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]); -+ -+ sreq->sr_request->flags &= ~REQ_DONTPREP; -+ blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request, -+ 1, sreq); -+} -+EXPORT_SYMBOL(scsi_do_req_fifo); -+ - /** - * scsi_execute - insert request and wait for the result - * @sdev: scsi device ---- linux-2.6.16/include/scsi/scsi_request.h.orig 2006-04-07 10:06:02.506664250 -0400 -+++ linux-2.6.16/include/scsi/scsi_request.h 2006-04-07 10:06:19.039697500 -0400 -@@ -51,4 +51,8 @@ extern void scsi_do_req(struct scsi_requ - void *buffer, unsigned bufflen, - void (*done) (struct scsi_cmnd *), - int timeout, int retries); -+extern void scsi_do_req_fifo(struct scsi_request *, const void *cmnd, -+ void *buffer, unsigned bufflen, -+ void (*done) (struct scsi_cmnd *), -+ int timeout, int retries); - #endif /* _SCSI_SCSI_REQUEST_H */ Deleted: trunk/scst/kernel/26_scst-2.6.18.patch =================================================================== --- trunk/scst/kernel/26_scst-2.6.18.patch 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/kernel/26_scst-2.6.18.patch 2007-07-05 14:37:36 UTC (rev 142) @@ -1,106 +0,0 @@ ---- linux-2.6.18.1-scst-dbg/drivers/scsi/scsi_lib.c_scst 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18.1-scst-dbg/drivers/scsi/scsi_lib.c 2006-10-25 20:52:58.000000000 +0400 -@@ -367,7 +367,7 @@ - } - - /** -- * scsi_execute_async - insert request -+ * __scsi_execute_async - insert request - * @sdev: scsi device - * @cmd: scsi command - * @cmd_len: length of scsi cdb -@@ -378,11 +378,14 @@ - * @timeout: request timeout in seconds - * @retries: number of times to retry request - * @flags: or into request flags -+ * @at_head: insert request at head or tail of queue - **/ --int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, -+static inline int __scsi_execute_async(struct scsi_device *sdev, -+ const unsigned char *cmd, - int cmd_len, int data_direction, void *buffer, unsigned bufflen, - int use_sg, int timeout, int retries, void *privdata, -- void (*done)(void *, char *, int, int), gfp_t gfp) -+ void (*done)(void *, char *, int, int), gfp_t gfp, -+ int at_head) - { - struct request *req; - struct scsi_io_context *sioc; -@@ -418,7 +421,7 @@ - sioc->data = privdata; - sioc->done = done; - -- blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); -+ blk_execute_rq_nowait(req->q, NULL, req, at_head, scsi_end_async); - return 0; - - free_req: -@@ -427,8 +430,53 @@ - kfree(sioc); - return DRIVER_ERROR << 24; - } -+ -+/** -+ * scsi_execute_async - insert request -+ * @sdev: scsi device -+ * @cmd: scsi command -+ * @cmd_len: length of scsi cdb -+ * @data_direction: data direction -+ * @buffer: data buffer (this can be a kernel buffer or scatterlist) -+ * @bufflen: len of buffer -+ * @use_sg: if buffer is a scatterlist this is the number of elements -+ * @timeout: request timeout in seconds -+ * @retries: number of times to retry request -+ * @flags: or into request flags -+ **/ -+int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, -+ int cmd_len, int data_direction, void *buffer, unsigned bufflen, -+ int use_sg, int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), gfp_t gfp) -+{ -+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, -+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 1); -+} - EXPORT_SYMBOL_GPL(scsi_execute_async); - -+/** -+ * scsi_execute_async_fifi - insert request at tail, in FIFO order -+ * @sdev: scsi device -+ * @cmd: scsi command -+ * @cmd_len: length of scsi cdb -+ * @data_direction: data direction -+ * @buffer: data buffer (this can be a kernel buffer or scatterlist) -+ * @bufflen: len of buffer -+ * @use_sg: if buffer is a scatterlist this is the number of elements -+ * @timeout: request timeout in seconds -+ * @retries: number of times to retry request -+ * @flags: or into request flags -+ **/ -+int scsi_execute_async_fifo(struct scsi_device *sdev, const unsigned char *cmd, -+ int cmd_len, int data_direction, void *buffer, unsigned bufflen, -+ int use_sg, int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), gfp_t gfp) -+{ -+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, -+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 0); -+} -+EXPORT_SYMBOL_GPL(scsi_execute_async_fifo); -+ - /* - * Function: scsi_init_cmd_errh() - * ---- linux-2.6.18.1-scst-dbg/include/scsi/scsi_device.h_scst 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18.1-scst-dbg/include/scsi/scsi_device.h 2006-10-25 20:09:23.000000000 +0400 -@@ -297,6 +297,12 @@ - int timeout, int retries, void *privdata, - void (*done)(void *, char *, int, int), - gfp_t gfp); -+extern int scsi_execute_async_fifo(struct scsi_device *sdev, -+ const unsigned char *cmd, int cmd_len, int data_direction, -+ void *buffer, unsigned bufflen, int use_sg, -+ int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), -+ gfp_t gfp); - - static inline void scsi_device_reprobe(struct scsi_device *sdev) - { Deleted: trunk/scst/kernel/26_scst-2.6.21.patch =================================================================== --- trunk/scst/kernel/26_scst-2.6.21.patch 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/kernel/26_scst-2.6.21.patch 2007-07-05 14:37:36 UTC (rev 142) @@ -1,106 +0,0 @@ ---- linux-2.6.21.1-scst-dbg/drivers/scsi/scsi_lib.c.orig 2007-04-28 01:49:26.000000000 +0400 -+++ linux-2.6.21.1-scst-dbg/drivers/scsi/scsi_lib.c 2007-05-02 13:37:38.000000000 +0400 -@@ -366,7 +366,7 @@ - } - - /** -- * scsi_execute_async - insert request -+ * __scsi_execute_async - insert request - * @sdev: scsi device - * @cmd: scsi command - * @cmd_len: length of scsi cdb -@@ -377,11 +377,14 @@ - * @timeout: request timeout in seconds - * @retries: number of times to retry request - * @flags: or into request flags -+ * @at_head: insert request at head or tail of queue - **/ --int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, -+static inline int __scsi_execute_async(struct scsi_device *sdev, -+ const unsigned char *cmd, - int cmd_len, int data_direction, void *buffer, unsigned bufflen, - int use_sg, int timeout, int retries, void *privdata, -- void (*done)(void *, char *, int, int), gfp_t gfp) -+ void (*done)(void *, char *, int, int), gfp_t gfp, -+ int at_head) - { - struct request *req; - struct scsi_io_context *sioc; -@@ -418,7 +421,7 @@ - sioc->data = privdata; - sioc->done = done; - -- blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); -+ blk_execute_rq_nowait(req->q, NULL, req, at_head, scsi_end_async); - return 0; - - free_req: -@@ -427,8 +430,53 @@ - kmem_cache_free(scsi_io_context_cache, sioc); - return DRIVER_ERROR << 24; - } -+ -+/** -+ * scsi_execute_async - insert request -+ * @sdev: scsi device -+ * @cmd: scsi command -+ * @cmd_len: length of scsi cdb -+ * @data_direction: data direction -+ * @buffer: data buffer (this can be a kernel buffer or scatterlist) -+ * @bufflen: len of buffer -+ * @use_sg: if buffer is a scatterlist this is the number of elements -+ * @timeout: request timeout in seconds -+ * @retries: number of times to retry request -+ * @flags: or into request flags -+ **/ -+int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, -+ int cmd_len, int data_direction, void *buffer, unsigned bufflen, -+ int use_sg, int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), gfp_t gfp) -+{ -+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, -+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 1); -+} - EXPORT_SYMBOL_GPL(scsi_execute_async); - -+/** -+ * scsi_execute_async_fifi - insert request at tail, in FIFO order -+ * @sdev: scsi device -+ * @cmd: scsi command -+ * @cmd_len: length of scsi cdb -+ * @data_direction: data direction -+ * @buffer: data buffer (this can be a kernel buffer or scatterlist) -+ * @bufflen: len of buffer -+ * @use_sg: if buffer is a scatterlist this is the number of elements -+ * @timeout: request timeout in seconds -+ * @retries: number of times to retry request -+ * @flags: or into request flags -+ **/ -+int scsi_execute_async_fifo(struct scsi_device *sdev, const unsigned char *cmd, -+ int cmd_len, int data_direction, void *buffer, unsigned bufflen, -+ int use_sg, int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), gfp_t gfp) -+{ -+ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, -+ bufflen, use_sg, timeout, retries, privdata, done, gfp, 0); -+} -+EXPORT_SYMBOL_GPL(scsi_execute_async_fifo); -+ - /* - * Function: scsi_init_cmd_errh() - * ---- linux-2.6.21.1-scst-dbg/include/scsi/scsi_device.h.orig 2007-04-28 01:49:26.000000000 +0400 -+++ linux-2.6.21.1-scst-dbg/include/scsi/scsi_device.h 2007-05-02 13:37:38.000000000 +0400 -@@ -298,6 +298,12 @@ - int timeout, int retries, void *privdata, - void (*done)(void *, char *, int, int), - gfp_t gfp); -+extern int scsi_execute_async_fifo(struct scsi_device *sdev, -+ const unsigned char *cmd, int cmd_len, int data_direction, -+ void *buffer, unsigned bufflen, int use_sg, -+ int timeout, int retries, void *privdata, -+ void (*done)(void *, char *, int, int), -+ gfp_t gfp); - - static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev) - { Modified: trunk/scst/src/Makefile =================================================================== --- trunk/scst/src/Makefile 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/src/Makefile 2007-07-05 14:37:36 UTC (rev 142) @@ -98,7 +98,6 @@ #EXTRA_CFLAGS += -DSTRICT_SERIALIZING EXTRA_CFLAGS += -DEXTRACHECKS -#EXTRA_CFLAGS += -DVDISK_ONLY #EXTRA_CFLAGS += -fno-inline Modified: trunk/scst/src/dev_handlers/scst_user.c =================================================================== --- trunk/scst/src/dev_handlers/scst_user.c 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/src/dev_handlers/scst_user.c 2007-07-05 14:37:36 UTC (rev 142) @@ -26,9 +26,11 @@ #include "scst_user.h" #include "scst_dev_handler.h" -#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) -#warning HIGHMEM kernel configurations are not supported. Consider \ - changing VMSPLIT option or using 64-bit configuration. +#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) +#warning HIGHMEM kernel configurations are not supported by this module, \ + because nowadays it doesn't worth the effort. Consider change \ + VMSPLIT option or use 64-bit configuration instead. See README file \ + for details. #endif #if defined(DEBUG) && defined(CONFIG_DEBUG_SLAB) @@ -2933,10 +2935,10 @@ TRACE_ENTRY(); -#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) +#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) PRINT_ERROR_PR("%s", "HIGHMEM kernel configurations are not supported. " - "Consider changing VMSPLIT option or using 64-bit " - "configuration."); + "Consider change VMSPLIT option or use 64-bit " + "configuration instead. See README file for details."); res = -EINVAL; goto out; #endif Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/src/scst.c 2007-07-05 14:37:36 UTC (rev 142) @@ -32,15 +32,27 @@ #include "scst_priv.h" #include "scst_mem.h" -#if !defined(CONFIG_NOHIGHMEM) && !defined(CONFIG_64BIT) -#warning HIGHMEM kernel configurations are supported, but not recommended. \ - Consider changing VMSPLIT option or using 64-bit configuration instead. +#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) +#warning HIGHMEM kernel configurations are fully supported, but not \ + recommended for performance reasons. Consider change VMSPLIT \ + option or use 64-bit configuration instead. See README file for \ + details. #endif -/* - * All targets, devices and dev_types management is done under - * this mutex. - */ +#ifdef SCST_HIGHMEM +#error SCST_HIGHMEM configuration isn't supported and broken, because there \ + is no real point to support it, at least it definitely doesn't worth \ + the effort. Better use no-HIGHMEM kernel with VMSPLIT option \ + or in 64-bit configuration instead. See README file for details. +#endif + +#if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING) +#warning Patch scst_exec_req_fifo.patch was not applied on your kernel and \ + STRICT_SERIALIZING isn't defined. Pass-through dev handlers will \ + not be supported. +#endif + +/* All targets, devices and dev_types management is done under this mutex */ DECLARE_MUTEX(scst_mutex); LIST_HEAD(scst_template_list); @@ -732,10 +744,11 @@ if (res != 0) goto out_err; -#ifdef VDISK_ONLY +#if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING) if (dev_type->exec == NULL) { PRINT_ERROR_PR("Pass-through dev handlers (handler \"%s\") not " - "supported. Recompile SCST with undefined VDISK_ONLY", + "supported. Consider applying on your kernel patch " + "scst_exec_req_fifo.patch or define STRICT_SERIALIZING", dev_type->name); res = -EINVAL; goto out_err; Modified: trunk/scst/src/scst_debug.c =================================================================== --- trunk/scst/src/scst_debug.c 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/src/scst_debug.c 2007-07-05 14:37:36 UTC (rev 142) @@ -18,8 +18,8 @@ * GNU General Public License for more details. */ +#include "scsi_tgt.h" #include "scst_debug.h" -#include "scsi_tgt.h" #if defined(DEBUG) || defined(TRACING) Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-07-05 14:20:17 UTC (rev 141) +++ trunk/scst/src/scst_priv.h 2007-07-05 14:37:36 UTC (rev 142) @@ -313,7 +313,7 @@ { #ifdef STRICT_SERIALIZING scsi_do_req(sreq, cmnd, buffer, bufflen, done, timeout, retries); - #elif defined(VDISK_ONLY) + #elif !defined(SCSI_EXEC_REQ_FIFO_DEFINED) sBUG(); #else scsi_do_req_fifo(sreq, cmnd, buffer, bufflen, done, timeout, retries); @@ -328,7 +328,7 @@ #ifdef STRICT_SERIALIZING return scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, bufflen, use_sg, timeout, retries, privdata, done, gfp); - #elif defined(VDISK_ONLY) + #elif !defined(SCSI_EXEC_REQ_FIFO_DEFINED) sBUG(); return -1; #else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-10 16:48:37
|
Revision: 146 http://svn.sourceforge.net/scst/?rev=146&view=rev Author: vlnb Date: 2007-07-10 09:47:43 -0700 (Tue, 10 Jul 2007) Log Message: ----------- lun_t changed to 64 bits. Don't know why it was 32 bits Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/include/scst_debug.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_proc.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-10 16:39:38 UTC (rev 145) +++ trunk/scst/include/scsi_tgt.h 2007-07-10 16:47:43 UTC (rev 146) @@ -361,7 +361,7 @@ struct scst_acg_dev; struct scst_acn; -typedef uint32_t lun_t; +typedef uint64_t lun_t; typedef enum dma_data_direction scst_data_direction; @@ -1036,6 +1036,9 @@ struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */ + /* The corresponding mgmt cmd, if any, protected by sess_list_lock */ + struct scst_mgmt_cmd *mgmt_cmnd; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) struct scsi_request *scsi_req; /* SCSI request */ #endif @@ -1113,6 +1116,9 @@ /* Used for storage of target driver private stuff */ void *tgt_priv; + /* Used for storage of dev handler private stuff */ + void *dh_priv; + /* * Used to restore the SG vector if it was modified by * scst_set_resp_data_len() @@ -1121,15 +1127,9 @@ uint8_t sense_buffer[SCST_SENSE_BUFFERSIZE]; /* sense buffer */ - /* The corresponding mgmt cmd, if any, protected by sess_list_lock */ - struct scst_mgmt_cmd *mgmt_cmnd; - /* List entry for dev's blocked_cmd_list */ struct list_head blocked_cmd_list_entry; - /* Used for storage of dev handler private stuff */ - void *dh_priv; - struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */ }; Modified: trunk/scst/include/scst_debug.h =================================================================== --- trunk/scst/include/scst_debug.h 2007-07-10 16:39:38 UTC (rev 145) +++ trunk/scst/include/scst_debug.h 2007-07-10 16:47:43 UTC (rev 146) @@ -67,7 +67,7 @@ #endif #ifndef WARN_ON_ONCE -#define WARN_ON_ONCE(condition) ({ \ +#define WARN_ON_ONCE(condition) ({ \ static int __warned; \ typeof(condition) __ret_warn_once = (condition); \ \ Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-10 16:39:38 UTC (rev 145) +++ trunk/scst/src/scst_lib.c 2007-07-10 16:47:43 UTC (rev 146) @@ -1874,7 +1874,7 @@ * based on info_cdb, therefore change them only if necessary */ - TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)", + TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %Ld(%d)", info_cdb->op_name, info_cdb->direction, info_cdb->flags, @@ -1935,7 +1935,7 @@ * based on info_cdb, therefore change them only if necessary */ - TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)", + TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %Ld(%d)", info_cdb->op_name, info_cdb->direction, info_cdb->flags, @@ -2208,7 +2208,7 @@ dev_tgt_dev_list_entry) { TRACE(TRACE_MGMT, "Clearing RESERVE'ation for tgt_dev " - "lun %d", tgt_dev->lun); + "lun %Ld", tgt_dev->lun); clear_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags); } @@ -2416,7 +2416,7 @@ TRACE_ENTRY(); list_for_each_entry_safe(UA_entry, t, &tgt_dev->UA_list, UA_list_entry) { - TRACE_MGMT_DBG("Clearing UA for tgt_dev lun %d", + TRACE_MGMT_DBG("Clearing UA for tgt_dev lun %Ld", tgt_dev->lun); list_del(&UA_entry->UA_list_entry); kfree(UA_entry); Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-07-10 16:39:38 UTC (rev 145) +++ trunk/scst/src/scst_proc.c 2007-07-10 16:47:43 UTC (rev 146) @@ -1826,7 +1826,7 @@ acg_dev->lun, acg_dev->rd_only_flag ? "RO" : ""); } else { - seq_printf(seq, "%-60s%4d%12s\n", + seq_printf(seq, "%-60s%4Ld%12s\n", acg_dev->dev->virt_name, acg_dev->lun, acg_dev->rd_only_flag ? "RO" : ""); } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-10 16:39:38 UTC (rev 145) +++ trunk/scst/src/scst_targ.c 2007-07-10 16:47:43 UTC (rev 146) @@ -3307,7 +3307,7 @@ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev; struct scst_device *dev = tgt_dev->dev; - TRACE(TRACE_MGMT, "Aborting task set (lun=%d, mcmd=%p)", + TRACE(TRACE_MGMT, "Aborting task set (lun=%Ld, mcmd=%p)", tgt_dev->lun, mcmd); spin_lock_bh(&dev->dev_lock); @@ -3493,7 +3493,7 @@ TRACE_ENTRY(); - TRACE(TRACE_MGMT, "Resetting lun %d (mcmd %p)", tgt_dev->lun, mcmd); + TRACE(TRACE_MGMT, "Resetting lun %Ld (mcmd %p)", tgt_dev->lun, mcmd); spin_lock_bh(&dev->dev_lock); __scst_block_dev(dev); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-13 09:34:27
|
Revision: 148 http://svn.sourceforge.net/scst/?rev=148&view=rev Author: vlnb Date: 2007-07-13 02:34:25 -0700 (Fri, 13 Jul 2007) Log Message: ----------- Few minor races fixed Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_proc.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-11 09:30:10 UTC (rev 147) +++ trunk/scst/include/scsi_tgt.h 2007-07-13 09:34:25 UTC (rev 148) @@ -421,16 +421,6 @@ unsigned no_proc_entry:1; /* - * True, if the target requires that *ALL* affecting by a task - * management command outstanding SCSI commands finished before - * sending the TM command reply. Otherwise, the TM reply will be - * send immediately after it is insured, that the affecting SCSI - * commands will reach xmit_response() with ABORTED flag set (see - * also scst_cmd_aborted()). - */ - unsigned tm_sync_reply:1; - - /* * This function is equivalent to the SCSI * queuecommand. The target should transmit the response * buffer and the status in the scst_cmd struct. @@ -853,8 +843,8 @@ /* Used for storage of target driver private stuff */ void *tgt_priv; - /* Alive commands for this session, protected by sess_list_lock */ - int sess_cmd_count; + /* Alive commands for this session. ToDo: make it part of common IO flow control */ + atomic_t sess_cmd_count; spinlock_t sess_list_lock; /* protects search_cmd_list, etc */ Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-11 09:30:10 UTC (rev 147) +++ trunk/scst/src/scst_lib.c 2007-07-13 09:34:25 UTC (rev 148) @@ -86,7 +86,7 @@ void scst_set_busy(struct scst_cmd *cmd) { - int c = cmd->sess->sess_cmd_count; + int c = atomic_read(&cmd->sess->sess_cmd_count); TRACE_ENTRY(); @@ -1371,7 +1371,7 @@ TRACE_ENTRY(); spin_lock_irqsave(&mcmd->sess->sess_list_lock, flags); - mcmd->sess->sess_cmd_count--; + atomic_dec(&mcmd->sess->sess_cmd_count); spin_unlock_irqrestore(&mcmd->sess->sess_list_lock, flags); scst_sess_put(mcmd->sess); Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-07-11 09:30:10 UTC (rev 147) +++ trunk/scst/src/scst_proc.c 2007-07-13 09:34:25 UTC (rev 148) @@ -1703,7 +1703,7 @@ sess->tgt->tgtt->name, sess->initiator_name, acg->acg_name, - sess->sess_cmd_count); + atomic_read(&sess->sess_cmd_count)); } } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-11 09:30:10 UTC (rev 147) +++ trunk/scst/src/scst_targ.c 2007-07-13 09:34:25 UTC (rev 148) @@ -181,9 +181,10 @@ } #endif + atomic_inc(&sess->sess_cmd_count); + spin_lock_irqsave(&sess->sess_list_lock, flags); - sess->sess_cmd_count++; list_add_tail(&cmd->search_cmd_list_entry, &sess->search_cmd_list); if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) { @@ -2312,6 +2313,17 @@ goto out; } + /* + * If we don't remove cmd from the search list here, before + * submitting it for transmittion, we will have a race, when for + * some reason cmd's release is delayed after transmittion and + * initiator sends cmd with the same tag => it is possible that + * a wrong cmd will be found by find() functions. + */ + spin_lock_irq(&cmd->sess->sess_list_lock); + list_del(&cmd->search_cmd_list_entry); + spin_unlock_irq(&cmd->sess->sess_list_lock); + set_bit(SCST_CMD_XMITTING, &cmd->cmd_flags); smp_mb__after_set_bit(); @@ -2449,10 +2461,7 @@ spin_unlock_bh(&scst_cmd_mem_lock); } - spin_lock_irq(&cmd->sess->sess_list_lock); - cmd->sess->sess_cmd_count--; - list_del(&cmd->search_cmd_list_entry); - spin_unlock_irq(&cmd->sess->sess_list_lock); + atomic_dec(&cmd->sess->sess_cmd_count); if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { TRACE_MGMT_DBG("Aborted cmd %p finished (cmd_ref %d, " @@ -3143,44 +3152,32 @@ } if (mcmd) { - int defer; - if (cmd->tgtt->tm_sync_reply) - defer = 1; - else { - if (scst_is_strict_mgmt_fn(mcmd->fn)) - defer = test_bit(SCST_CMD_EXECUTING, - &cmd->cmd_flags); - else - defer = test_bit(SCST_CMD_XMITTING, - &cmd->cmd_flags); - } - - if (defer) { - unsigned long flags; - /* - * Delay the response until the command's finish in - * order to guarantee that "no further responses from - * the task are sent to the SCSI initiator port" after - * response from the TM function is sent (SAM) - */ - TRACE(TRACE_MGMT, "cmd %p (tag %d) being executed/" - "xmitted (state %d), deferring ABORT...", cmd, - cmd->tag, cmd->state); + unsigned long flags; + /* + * Delay the response until the command's finish in + * order to guarantee that "no further responses from + * the task are sent to the SCSI initiator port" after + * response from the TM function is sent (SAM). Plus, + * we must wait here to be sure that we won't receive + * double commands with the same tag. + */ + TRACE(TRACE_MGMT, "cmd %p (tag %d) being executed/" + "xmitted (state %d), deferring ABORT...", cmd, + cmd->tag, cmd->state); #ifdef EXTRACHECKS - if (cmd->mgmt_cmnd) { - printk(KERN_ALERT "cmd %p (tag %d, state %d) " - "has non-NULL mgmt_cmnd %p!!! Current " - "mcmd %p\n", cmd, cmd->tag, cmd->state, - cmd->mgmt_cmnd, mcmd); - } -#endif - sBUG_ON(cmd->mgmt_cmnd); - spin_lock_irqsave(&scst_mcmd_lock, flags); - mcmd->cmd_wait_count++; - spin_unlock_irqrestore(&scst_mcmd_lock, flags); - /* cmd can't die here or sess_list_lock already taken */ - cmd->mgmt_cmnd = mcmd; + if (cmd->mgmt_cmnd) { + printk(KERN_ALERT "cmd %p (tag %d, state %d) " + "has non-NULL mgmt_cmnd %p!!! Current " + "mcmd %p\n", cmd, cmd->tag, cmd->state, + cmd->mgmt_cmnd, mcmd); } +#endif + sBUG_ON(cmd->mgmt_cmnd); + spin_lock_irqsave(&scst_mcmd_lock, flags); + mcmd->cmd_wait_count++; + spin_unlock_irqrestore(&scst_mcmd_lock, flags); + /* cmd can't die here or sess_list_lock already taken */ + cmd->mgmt_cmnd = mcmd; } tm_dbg_release_cmd(cmd); @@ -3407,7 +3404,7 @@ TRACE_ENTRY(); TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)", - mcmd, mcmd->sess->sess_cmd_count); + mcmd, atomic_read(&mcmd->sess->sess_cmd_count)); down(&scst_mutex); @@ -3927,7 +3924,7 @@ local_irq_save(flags); spin_lock(&sess->sess_list_lock); - sess->sess_cmd_count++; + atomic_inc(&sess->sess_cmd_count); #ifdef EXTRACHECKS if (unlikely(sess->shutting_down)) { @@ -4172,7 +4169,7 @@ cmd_list_entry) { TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd); list_del(&cmd->cmd_list_entry); - sess->sess_cmd_count--; + atomic_dec(&sess->sess_cmd_count); list_del(&cmd->search_cmd_list_entry); spin_unlock_irq(&sess->sess_list_lock); scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-13 15:02:22
|
Revision: 149 http://svn.sourceforge.net/scst/?rev=149&view=rev Author: vlnb Date: 2007-07-13 08:02:20 -0700 (Fri, 13 Jul 2007) Log Message: ----------- Patch from Nathan Bullock. We are using OFED target machines to export a large number of disks, many of which are just NULLIO disks, but we have noticed that VPD numbers have a significant tendency to conflict. For example if we name one disk abc12 and another abc21 they will end up with the same VPD. We are using a quick, slightly hackish way to solve this, by just creating a random hash for each ascii value and then rotating that hash based on the position of the character in the name. If you would like here is our changes. Modified Paths: -------------- trunk/scst/README trunk/scst/src/dev_handlers/scst_vdisk.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-07-13 09:34:25 UTC (rev 148) +++ trunk/scst/README 2007-07-13 15:02:20 UTC (rev 149) @@ -635,4 +635,6 @@ * Alessandro Premoli <a.p...@an...> for fixes + * Nathan Bullock <nbu...@yo...> for fixes. + Vladislav Bolkhovitin <vs...@vl...>, http://scst.sourceforge.net Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-13 09:34:25 UTC (rev 148) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-13 15:02:20 UTC (rev 149) @@ -95,6 +95,73 @@ #define VDISK_PROC_HELP "help" +static unsigned int random_values[256] = { + 9862592UL, 3744545211UL, 2348289082UL, 4036111983UL, + 435574201UL, 3110343764UL, 2383055570UL, 1826499182UL, + 4076766377UL, 1549935812UL, 3696752161UL, 1200276050UL, + 3878162706UL, 1783530428UL, 2291072214UL, 125807985UL, + 3407668966UL, 547437109UL, 3961389597UL, 969093968UL, + 56006179UL, 2591023451UL, 1849465UL, 1614540336UL, + 3699757935UL, 479961779UL, 3768703953UL, 2529621525UL, + 4157893312UL, 3673555386UL, 4091110867UL, 2193909423UL, + 2800464448UL, 3052113233UL, 450394455UL, 3424338713UL, + 2113709130UL, 4082064373UL, 3708640918UL, 3841182218UL, + 3141803315UL, 1032476030UL, 1166423150UL, 1169646901UL, + 2686611738UL, 575517645UL, 2829331065UL, 1351103339UL, + 2856560215UL, 2402488288UL, 867847666UL, 8524618UL, + 704790297UL, 2228765657UL, 231508411UL, 1425523814UL, + 2146764591UL, 1287631730UL, 4142687914UL, 3879884598UL, + 729945311UL, 310596427UL, 2263511876UL, 1983091134UL, + 3500916580UL, 1642490324UL, 3858376049UL, 695342182UL, + 780528366UL, 1372613640UL, 1100993200UL, 1314818946UL, + 572029783UL, 3775573540UL, 776262915UL, 2684520905UL, + 1007252738UL, 3505856396UL, 1974886670UL, 3115856627UL, + 4194842288UL, 2135793908UL, 3566210707UL, 7929775UL, + 1321130213UL, 2627281746UL, 3587067247UL, 2025159890UL, + 2587032000UL, 3098513342UL, 3289360258UL, 130594898UL, + 2258149812UL, 2275857755UL, 3966929942UL, 1521739999UL, + 4191192765UL, 958953550UL, 4153558347UL, 1011030335UL, + 524382185UL, 4099757640UL, 498828115UL, 2396978754UL, + 328688935UL, 826399828UL, 3174103611UL, 3921966365UL, + 2187456284UL, 2631406787UL, 3930669674UL, 4282803915UL, + 1776755417UL, 374959755UL, 2483763076UL, 844956392UL, + 2209187588UL, 3647277868UL, 291047860UL, 3485867047UL, + 2223103546UL, 2526736133UL, 3153407604UL, 3828961796UL, + 3355731910UL, 2322269798UL, 2752144379UL, 519897942UL, + 3430536488UL, 1801511593UL, 1953975728UL, 3286944283UL, + 1511612621UL, 1050133852UL, 409321604UL, 1037601109UL, + 3352316843UL, 4198371381UL, 617863284UL, 994672213UL, + 1540735436UL, 2337363549UL, 1242368492UL, 665473059UL, + 2330728163UL, 3443103219UL, 2291025133UL, 3420108120UL, + 2663305280UL, 1608969839UL, 2278959931UL, 1389747794UL, + 2226946970UL, 2131266900UL, 3856979144UL, 1894169043UL, + 2692697628UL, 3797290626UL, 3248126844UL, 3922786277UL, + 343705271UL, 3739749888UL, 2191310783UL, 2962488787UL, + 4119364141UL, 1403351302UL, 2984008923UL, 3822407178UL, + 1932139782UL, 2323869332UL, 2793574182UL, 1852626483UL, + 2722460269UL, 1136097522UL, 1005121083UL, 1805201184UL, + 2212824936UL, 2979547931UL, 4133075915UL, 2585731003UL, + 2431626071UL, 134370235UL, 3763236829UL, 1171434827UL, + 2251806994UL, 1289341038UL, 3616320525UL, 392218563UL, + 1544502546UL, 2993937212UL, 1957503701UL, 3579140080UL, + 4270846116UL, 2030149142UL, 1792286022UL, 366604999UL, + 2625579499UL, 790898158UL, 770833822UL, 815540197UL, + 2747711781UL, 3570468835UL, 3976195842UL, 1257621341UL, + 1198342980UL, 1860626190UL, 3247856686UL, 351473955UL, + 993440563UL, 340807146UL, 1041994520UL, 3573925241UL, + 480246395UL, 2104806831UL, 1020782793UL, 3362132583UL, + 2272911358UL, 3440096248UL, 2356596804UL, 259492703UL, + 3899500740UL, 252071876UL, 2177024041UL, 4284810959UL, + 2775999888UL, 2653420445UL, 2876046047UL, 1025771859UL, + 1994475651UL, 3564987377UL, 4112956647UL, 1821511719UL, + 3113447247UL, 455315102UL, 1585273189UL, 2311494568UL, + 774051541UL, 1898115372UL, 2637499516UL, 247231365UL, + 1475014417UL, 803585727UL, 3911097303UL, 1714292230UL, + 476579326UL, 2496900974UL, 3397613314UL, 341202244UL, + 807790202UL, 4221326173UL, 499979741UL, 1301488547UL, + 1056807896UL, 3525009458UL, 1174811641UL, 3049738746UL, +}; + struct scst_vdisk_dev { uint32_t block_size; uint64_t nblocks; @@ -995,7 +1062,12 @@ char dev_id_str[6]; for (dev_id_num = 0, i = 0; i < (int)strlen(virt_dev->name); i++) { - dev_id_num += virt_dev->name[i]; + unsigned int rv = random_values[(int)(virt_dev->name[i])]; + /* + * Device name maximum length = 16, + * do some rotating of the bits. + */ + dev_id_num ^= ((rv << i) | (rv >> (32 - i))); } len = scnprintf(dev_id_str, 6, "%d", dev_id_num); TRACE_DBG("num %d, str <%s>, len %d", This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-18 08:42:21
|
Revision: 150 http://svn.sourceforge.net/scst/?rev=150&view=rev Author: vlnb Date: 2007-07-18 01:41:44 -0700 (Wed, 18 Jul 2007) Log Message: ----------- Patch from Terry Greeniaus: We use the 64-bit tag field in the SRP commands to store information allowing us to track each command. However, SCST only saves/uses 32-bits out of this 64-bit field. This causes our code to fail when we get a response SRP command that doesn't match any tags we used. I have updated SCST to work with our product by changing it to save all 64-bits of the tag. Modified Paths: -------------- trunk/scst/README trunk/scst/include/scsi_tgt.h trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/README 2007-07-18 08:41:44 UTC (rev 150) @@ -637,4 +637,6 @@ * Nathan Bullock <nbu...@yo...> for fixes. + * Terry Greeniaus <tgr...@yo...> for fixes. + Vladislav Bolkhovitin <vs...@vl...>, http://scst.sourceforge.net Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/include/scsi_tgt.h 2007-07-18 08:41:44 UTC (rev 150) @@ -1049,7 +1049,7 @@ * Used to found the cmd by scst_find_cmd_by_tag(). Set by the * target driver on the cmd's initialization time */ - uint32_t tag; + uint64_t tag; /* CDB and its len */ uint8_t cdb[SCST_MAX_CDB_SIZE]; @@ -1149,7 +1149,7 @@ lun_t lun; /* LUN for this mgmt cmd */ /* or */ - uint32_t tag; /* tag of the corresponding cmd */ + uint64_t tag; /* tag of the corresponding cmd */ /* corresponding cmd (to be aborted, found by tag) */ struct scst_cmd *cmd_to_abort; @@ -1623,7 +1623,7 @@ * Must not been called in parallel with scst_unregister_session() for the * same sess. Returns 0 for success, error code otherwise. */ -int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint32_t tag, +int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint64_t tag, int atomic, void *tgt_priv); /* @@ -1667,7 +1667,7 @@ * that previously set by scst_cmd_set_tag(). * Returns the command on success or NULL otherwise */ -struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint32_t tag); +struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag); /* * Finds a command based on user supplied data and comparision @@ -1879,12 +1879,12 @@ /* * Get/Set functions for cmd's target SN */ -static inline uint32_t scst_cmd_get_tag(struct scst_cmd *cmd) +static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd) { return cmd->tag; } -static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint32_t tag) +static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag) { cmd->tag = tag; } Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-18 08:41:44 UTC (rev 150) @@ -657,7 +657,7 @@ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { TRACE_MGMT_DBG("Flag ABORTED set for " - "cmd %p (tag %d), skipping", cmd, cmd->tag); + "cmd %p (tag %lld), skipping", cmd, cmd->tag); goto done_uncompl; } Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/src/scst_lib.c 2007-07-18 08:41:44 UTC (rev 150) @@ -126,7 +126,7 @@ l += cmd->sg[i].length; if (l >= resp_data_len) { int left = resp_data_len - (l - cmd->sg[i].length); - TRACE(TRACE_SG|TRACE_MEMORY, "cmd %p (tag %d), " + TRACE(TRACE_SG|TRACE_MEMORY, "cmd %p (tag %lld), " "resp_data_len %d, i %d, cmd->sg[i].length %d, " "left %d", cmd, cmd->tag, resp_data_len, i, cmd->sg[i].length, left); @@ -1267,7 +1267,7 @@ #endif if (unlikely(cmd->out_of_sn)) { - TRACE_SN("Out of SN cmd %p (tag %d, sn %ld), " + TRACE_SN("Out of SN cmd %p (tag %lld, sn %ld), " "destroy=%d", cmd, cmd->tag, cmd->sn, destroy); destroy = test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED, &cmd->cmd_flags); @@ -2536,7 +2536,7 @@ * !! sn_slot and sn_cmd_list_entry, could be !! * !! already destroyed !! */ - TRACE_SN("cmd %p (tag %d) with skipped sn %ld found", + TRACE_SN("cmd %p (tag %lld) with skipped sn %ld found", cmd, cmd->tag, cmd->sn); tgt_dev->def_cmd_count--; list_del(&cmd->sn_cmd_list_entry); @@ -2647,7 +2647,7 @@ if (dev->block_count > 0) { scst_dec_on_dev_cmd(cmd, 0); TRACE_MGMT_DBG("Delaying cmd %p due to blocking or serializing" - "(tag %d, dev %p)", cmd, cmd->tag, dev); + "(tag %lld, dev %p)", cmd, cmd->tag, dev); list_add_tail(&cmd->blocked_cmd_list_entry, &dev->blocked_cmd_list); res = 1; @@ -2667,7 +2667,7 @@ if (dev->block_count > 0) { scst_dec_on_dev_cmd(cmd, 0); TRACE_MGMT_DBG("Delaying cmd %p due to blocking or " - "serializing (tag %d, dev %p)", cmd, + "serializing (tag %lld, dev %p)", cmd, cmd->tag, dev); list_add_tail(&cmd->blocked_cmd_list_entry, &dev->blocked_cmd_list); @@ -2684,7 +2684,7 @@ spin_lock_bh(&dev->dev_lock); barrier(); /* to reread block_count */ if (dev->block_count == 0) { - TRACE_MGMT_DBG("cmd %p (tag %d), blocking further " + TRACE_MGMT_DBG("cmd %p (tag %lld), blocking further " "cmds due to serializing (dev %p)", cmd, cmd->tag, dev); __scst_block_dev(dev); @@ -2960,7 +2960,7 @@ case TM_DBG_STATE_ABORT: if (tm_dbg_delayed_cmds_count == 0) { unsigned long d = 58*HZ + (scst_random() % (4*HZ)); - TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %d) " + TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %lld) " "for %ld.%ld seconds (%ld HZ), " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, d/HZ, (d%HZ)*100/HZ, d, tm_dbg_on_state_passes); @@ -2970,7 +2970,7 @@ #endif } else { TRACE_MGMT_DBG("Delaying another timed cmd %p " - "(tag %d), delayed_cmds_count=%d, " + "(tag %lld), delayed_cmds_count=%d, " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes); @@ -2982,7 +2982,7 @@ case TM_DBG_STATE_RESET: case TM_DBG_STATE_OFFLINE: TRACE_MGMT_DBG("STATE RESET/OFFLINE: delaying cmd %p " - "(tag %d), delayed_cmds_count=%d, " + "(tag %lld), delayed_cmds_count=%d, " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes); tm_dbg_flags.tm_dbg_blocked = 1; @@ -3008,7 +3008,7 @@ spin_lock_irq(&scst_tm_dbg_lock); list_for_each_entry_safe_reverse(cmd, tc, &tm_dbg_delayed_cmd_list, cmd_list_entry) { - TRACE_MGMT_DBG("Releasing timed cmd %p (tag %d), " + TRACE_MGMT_DBG("Releasing timed cmd %p (tag %lld), " "delayed_cmds_count=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count); spin_lock(&cmd->cmd_lists->cmd_list_lock); @@ -3070,7 +3070,7 @@ if (cmd->tm_dbg_delayed) { spin_lock_irqsave(&scst_tm_dbg_lock, flags); - TRACE_MGMT_DBG("Processing delayed cmd %p (tag %d), " + TRACE_MGMT_DBG("Processing delayed cmd %p (tag %lld), " "delayed_cmds_count=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count); @@ -3108,7 +3108,7 @@ cmd_list_entry) { if (c == cmd) { TRACE_MGMT_DBG("Abort request for " - "delayed cmd %p (tag=%d), moving it to " + "delayed cmd %p (tag=%lld), moving it to " "active cmd list (delayed_cmds_count=%d)", c, c->tag, tm_dbg_delayed_cmds_count); spin_lock(&cmd->cmd_lists->cmd_list_lock); Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/src/scst_priv.h 2007-07-18 08:41:44 UTC (rev 150) @@ -345,7 +345,7 @@ lun_t scst_unpack_lun(const uint8_t *lun, int len); struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, - uint32_t tag); + uint64_t tag); struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(int gfp_mask); void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd); @@ -460,7 +460,7 @@ { int cmd_blocking = cmd->blocking; if (cmd_blocking) { - TRACE_MGMT_DBG("cmd %p (tag %d): unblocking dev %p", cmd, + TRACE_MGMT_DBG("cmd %p (tag %lld): unblocking dev %p", cmd, cmd->tag, cmd->dev); cmd->blocking = 0; } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-13 15:02:20 UTC (rev 149) +++ trunk/scst/src/scst_targ.c 2007-07-18 08:41:44 UTC (rev 150) @@ -165,7 +165,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd); - TRACE(TRACE_SCSI, "tag=%d, lun=%Ld, CDB len=%d", cmd->tag, + TRACE(TRACE_SCSI, "tag=%lld, lun=%Ld, CDB len=%d", cmd->tag, (uint64_t)cmd->lun, cmd->cdb_len); TRACE_BUFF_FLAG(TRACE_SCSI|TRACE_RECV_BOT, "Recieving CDB", cmd->cdb, cmd->cdb_len); @@ -700,7 +700,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d", pref_context); - TRACE_DBG("tag=%d, status=%#x", scst_cmd_get_tag(cmd), status); + TRACE_DBG("tag=%lld, status=%#x", scst_cmd_get_tag(cmd), status); #ifdef EXTRACHECKS if (in_irq() && ((pref_context == SCST_CONTEXT_DIRECT) || @@ -950,7 +950,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d", pref_context); - TRACE(TRACE_SCSI, "tag=%d status=%#x", scst_cmd_get_tag(cmd), status); + TRACE(TRACE_SCSI, "tag=%lld status=%#x", scst_cmd_get_tag(cmd), status); #ifdef EXTRACHECKS if (in_irq() && ((pref_context == SCST_CONTEXT_DIRECT) || @@ -1443,7 +1443,7 @@ scst_block_dev(dev, 1); cmd->blocking = 1; - TRACE_MGMT_DBG("Blocking cmd %p (tag %d)", cmd, cmd->tag); + TRACE_MGMT_DBG("Blocking cmd %p (tag %lld)", cmd, cmd->tag); spin_lock_bh(&dev->dev_lock); @@ -1865,7 +1865,7 @@ int cmd_blocking = scst_dec_on_dev_cmd(cmd, 1); if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { /* Necessary to allow aborting out of sn cmds */ - TRACE_MGMT_DBG("Aborting out of sn cmd %p (tag %d)", + TRACE_MGMT_DBG("Aborting out of sn cmd %p (tag %lld)", cmd, cmd->tag); tgt_dev->def_cmd_count--; cmd->state = SCST_CMD_STATE_DEV_DONE; @@ -1995,7 +1995,7 @@ "Double UA detected"); /* Do retry */ TRACE(TRACE_MGMT, "Retrying cmd %p " - "(tag %d)", cmd, cmd->tag); + "(tag %lld)", cmd, cmd->tag); cmd->status = 0; cmd->msg_status = 0; cmd->host_status = DID_OK; @@ -2330,13 +2330,13 @@ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { if (test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags)) { TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p " - "(tag %d), returning TASK ABORTED", cmd, cmd->tag); + "(tag %lld), returning TASK ABORTED", cmd, cmd->tag); scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED); } } if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) { - TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %d), skipping", + TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %lld), skipping", cmd, cmd->tag); cmd->state = SCST_CMD_STATE_FINISHED; res = SCST_CMD_STATE_RES_CONT_SAME; @@ -2350,7 +2350,7 @@ res = SCST_CMD_STATE_RES_NEED_THREAD; goto out; } - TRACE_MGMT_DBG("Delaying cmd %p (tag %d) for 1 second", + TRACE_MGMT_DBG("Delaying cmd %p (tag %lld) for 1 second", cmd, cmd->tag); schedule_timeout_uninterruptible(HZ); } @@ -2703,7 +2703,7 @@ goto restart; } } else { - TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %d)", + TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %lld)", cmd, cmd->tag); cmd->state = SCST_CMD_STATE_XMIT_RESP; } @@ -2823,7 +2823,7 @@ case SCST_CMD_STATE_SEND_TO_MIDLEV: if (tm_dbg_check_cmd(cmd) != 0) { res = SCST_CMD_STATE_RES_CONT_NEXT; - TRACE_MGMT_DBG("Skipping cmd %p (tag %d), " + TRACE_MGMT_DBG("Skipping cmd %p (tag %lld), " "because of TM DBG delay", cmd, cmd->tag); break; @@ -3051,7 +3051,7 @@ spin_lock_irq(&scst_mcmd_lock); - TRACE_MGMT_DBG("cmd %p completed (tag %d, mcmd %p, " + TRACE_MGMT_DBG("cmd %p completed (tag %lld, mcmd %p, " "mcmd->cmd_wait_count %d)", cmd, cmd->tag, mcmd, mcmd->cmd_wait_count); @@ -3129,7 +3129,7 @@ { TRACE_ENTRY(); - TRACE(TRACE_MGMT, "Aborting cmd %p (tag %d)", cmd, cmd->tag); + TRACE(TRACE_MGMT, "Aborting cmd %p (tag %lld)", cmd, cmd->tag); if (other_ini) { set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); @@ -3161,12 +3161,12 @@ * we must wait here to be sure that we won't receive * double commands with the same tag. */ - TRACE(TRACE_MGMT, "cmd %p (tag %d) being executed/" + TRACE(TRACE_MGMT, "cmd %p (tag %lld) being executed/" "xmitted (state %d), deferring ABORT...", cmd, cmd->tag, cmd->state); #ifdef EXTRACHECKS if (cmd->mgmt_cmnd) { - printk(KERN_ALERT "cmd %p (tag %d, state %d) " + printk(KERN_ALERT "cmd %p (tag %lld, state %d) " "has non-NULL mgmt_cmnd %p!!! Current " "mcmd %p\n", cmd, cmd->tag, cmd->state, cmd->mgmt_cmnd, mcmd); @@ -3357,7 +3357,7 @@ cmd = __scst_find_cmd_by_tag(sess, mcmd->tag); if (cmd == NULL) { TRACE(TRACE_MGMT, "ABORT TASK failed: command for " - "tag %d not found", mcmd->tag); + "tag %lld not found", mcmd->tag); mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST; mcmd->state = SCST_MGMT_CMD_STATE_DONE; spin_unlock_irq(&sess->sess_list_lock); @@ -3365,7 +3365,7 @@ } scst_cmd_get(cmd); spin_unlock_irq(&sess->sess_list_lock); - TRACE(TRACE_MGMT, "Cmd %p for tag %d (sn %ld) found, " + TRACE(TRACE_MGMT, "Cmd %p for tag %lld (sn %ld) found, " "aborting it", cmd, mcmd->tag, cmd->sn); mcmd->cmd_to_abort = cmd; scst_abort_cmd(cmd, mcmd, 0, 1); @@ -4021,7 +4021,7 @@ * Must not been called in parallel with scst_unregister_session() for the * same sess */ -int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint32_t tag, +int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, uint64_t tag, int atomic, void *tgt_priv) { int res = -EFAULT; @@ -4041,7 +4041,7 @@ mcmd->tag = tag; - TRACE(TRACE_MGMT, "sess=%p, tag=%d", sess, mcmd->tag); + TRACE(TRACE_MGMT, "sess=%p, tag=%lld", sess, mcmd->tag); if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0) goto out_free; @@ -4411,7 +4411,7 @@ } /* Called under sess->sess_list_lock */ -struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, uint32_t tag) +struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag) { struct scst_cmd *cmd = NULL; @@ -4419,7 +4419,7 @@ /* ToDo: hash list */ - TRACE_DBG("%s (sess=%p, tag=%d)", "Searching in search cmd list", + TRACE_DBG("%s (sess=%p, tag=%lld)", "Searching in search cmd list", sess, tag); list_for_each_entry(cmd, &sess->search_cmd_list, search_cmd_list_entry) { @@ -4464,7 +4464,7 @@ } struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, - uint32_t tag) + uint64_t tag) { unsigned long flags; struct scst_cmd *cmd; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-30 11:23:08
|
Revision: 153 http://scst.svn.sourceforge.net/scst/?rev=153&view=rev Author: vlnb Date: 2007-07-30 04:21:04 -0700 (Mon, 30 Jul 2007) Log Message: ----------- - Semaphores converted to mutexes - pre_exec() callback added - *_DBG_SPECIAL() macroses added Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/include/scst_debug.h trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_mem.c trunk/scst/src/scst_mem.h trunk/scst/src/scst_priv.h trunk/scst/src/scst_proc.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/include/scsi_tgt.h 2007-07-30 11:21:04 UTC (rev 153) @@ -522,6 +522,22 @@ void (*preprocessing_done) (struct scst_cmd *cmd); /* + * This function informs the driver that the said command is about + * to be executed. + * + * Returns one of the SCST_PREPROCESS_* constants. + * + * This command is expected to be NON-BLOCKING. + * + * Pay attention to "atomic" attribute of the cmd, which can be get + * by scst_cmd_atomic(): it is true if the function called in the + * atomic (non-sleeping) context. + * + * OPTIONAL + */ + int (*pre_exec) (struct scst_cmd *cmd); + + /* * This function informs the driver that a * received task management function has been completed. This * function is necessary because low-level protocols have some Modified: trunk/scst/include/scst_debug.h =================================================================== --- trunk/scst/include/scst_debug.h 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/include/scst_debug.h 2007-07-30 11:21:04 UTC (rev 153) @@ -220,6 +220,19 @@ } \ } while(0) +#define TRACE_DBG_SPECIAL(format, args...) \ +do { \ + if (trace_flag & (TRACE_DEBUG|TRACE_SPECIAL)) \ + { \ + char *__tflag = LOG_FLAG; \ + if (debug_print_prefix(trace_flag, __FUNCTION__, __LINE__) > 0) \ + { \ + __tflag = NO_FLAG; \ + } \ + PRINT(NO_FLAG, "%s" format, __tflag, args); \ + } \ +} while(0) + #define TRACE_MGMT_DBG(format, args...) \ do { \ if (trace_flag & TRACE_MGMT_DEBUG) \ @@ -233,6 +246,19 @@ } \ } while(0) +#define TRACE_MGMT_DBG_SPECIAL(format, args...) \ +do { \ + if (trace_flag & (TRACE_MGMT_DEBUG|TRACE_SPECIAL)) \ + { \ + char *__tflag = LOG_FLAG; \ + if (debug_print_prefix(trace_flag, __FUNCTION__, __LINE__) > 0) \ + { \ + __tflag = NO_FLAG; \ + } \ + PRINT(NO_FLAG, "%s" format, __tflag, args); \ + } \ +} while(0) + #define PRINT_ERROR_PR(format, args...) \ do { \ if (ERROR_FLAG != LOG_FLAG) \ @@ -341,7 +367,9 @@ #define TRACE_MEM(format, args...) {} #define TRACE_DBG(format, args...) {} +#define TRACE_DBG_SPECIAL(format, args...) {} #define TRACE_MGMT_DBG(format, args...) {} +#define TRACE_MGMT_DBG_SPECIAL(format, args...) {} #define TRACE_ENTRY() {} #define TRACE_EXIT() {} #define TRACE_EXIT_RES(res) {} Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-30 11:21:04 UTC (rev 153) @@ -293,7 +293,7 @@ write_proc: vcdrom_write_proc, \ } -static DECLARE_MUTEX(scst_vdisk_mutex); +static DEFINE_MUTEX(scst_vdisk_mutex); static LIST_HEAD(vdisk_dev_list); static LIST_HEAD(vcdrom_dev_list); @@ -2356,7 +2356,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_vdisk_mutex) != 0) { + if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) { res = -EINTR; goto out; } @@ -2400,7 +2400,7 @@ } seq_printf(seq, "%s\n", virt_dev->file_name); } - up(&scst_vdisk_mutex); + mutex_unlock(&scst_vdisk_mutex); out: TRACE_EXIT_RES(res); return res; @@ -2426,7 +2426,7 @@ if (buffer[0] == '\0') goto out; - if (down_interruptible(&scst_vdisk_mutex) != 0) { + if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) { res = -EINTR; goto out; } @@ -2632,7 +2632,7 @@ res = length; out_up: - up(&scst_vdisk_mutex); + mutex_unlock(&scst_vdisk_mutex); out: TRACE_EXIT_RES(res); @@ -2932,7 +2932,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_vdisk_mutex) != 0) { + if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) { res = -EINTR; goto out; } @@ -2946,7 +2946,7 @@ virt_dev->file_name); } - up(&scst_vdisk_mutex); + mutex_unlock(&scst_vdisk_mutex); out: TRACE_EXIT_RES(res); @@ -2965,7 +2965,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_vdisk_mutex) != 0) { + if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) { res = -EINTR; goto out; } @@ -3022,7 +3022,7 @@ res = length; out_up: - up(&scst_vdisk_mutex); + mutex_unlock(&scst_vdisk_mutex); out: TRACE_EXIT_RES(res); @@ -3122,7 +3122,7 @@ { TRACE_ENTRY(); - down(&scst_vdisk_mutex); + mutex_lock(&scst_vdisk_mutex); while (1) { struct scst_vdisk_dev *virt_dev; @@ -3141,7 +3141,7 @@ kfree(virt_dev->file_name); kfree(virt_dev); } - up(&scst_vdisk_mutex); + mutex_unlock(&scst_vdisk_mutex); if (!devtype->no_proc) { vdisk_proc_help_destroy(devtype); Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst.c 2007-07-30 11:21:04 UTC (rev 153) @@ -53,7 +53,7 @@ #endif /* All targets, devices and dev_types management is done under this mutex */ -DECLARE_MUTEX(scst_mutex); +DEFINE_MUTEX(scst_mutex); LIST_HEAD(scst_template_list); LIST_HEAD(scst_dev_list); @@ -113,7 +113,7 @@ DECLARE_WAIT_QUEUE_HEAD(scst_dev_cmd_waitQ); -DECLARE_MUTEX(scst_suspend_mutex); +DEFINE_MUTEX(scst_suspend_mutex); LIST_HEAD(scst_cmd_lists_list); /* protected by scst_suspend_mutex */ static int scst_threads; @@ -141,7 +141,7 @@ { int res = 0; struct scst_tgt_template *t; - static DECLARE_MUTEX(m); + static DEFINE_MUTEX(m); TRACE_ENTRY(); @@ -185,20 +185,20 @@ if (vtt->preprocessing_done == NULL) vtt->preprocessing_done_atomic = 1; - if (down_interruptible(&m) != 0) + if (mutex_lock_interruptible(&m) != 0) goto out_err; - if (down_interruptible(&scst_mutex) != 0) + if (mutex_lock_interruptible(&scst_mutex) != 0) goto out_m_up; list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { if (strcmp(t->name, vtt->name) == 0) { PRINT_ERROR_PR("Target driver %s already registered", vtt->name); - up(&scst_mutex); + mutex_unlock(&scst_mutex); goto out_cleanup; } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); TRACE_DBG("%s", "Calling target driver's detect()"); res = vtt->detect(vtt); @@ -209,22 +209,22 @@ goto out_cleanup; } - down(&scst_mutex); + mutex_lock(&scst_mutex); list_add_tail(&vtt->scst_template_list_entry, &scst_template_list); - up(&scst_mutex); + mutex_unlock(&scst_mutex); res = 0; PRINT_INFO_PR("Target template %s registered successfully", vtt->name); - up(&m); + mutex_unlock(&m); out: TRACE_EXIT_RES(res); return res; out_m_up: - up(&m); + mutex_unlock(&m); out_cleanup: scst_cleanup_proc_target_dir_entries(vtt); @@ -242,7 +242,7 @@ TRACE_ENTRY(); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { if (strcmp(t->name, vtt->name) == 0) { @@ -257,9 +257,9 @@ restart: list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) { - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_unregister(tgt); - down(&scst_mutex); + mutex_lock(&scst_mutex); goto restart; } list_del(&vtt->scst_template_list_entry); @@ -267,7 +267,7 @@ PRINT_INFO_PR("Target template %s unregistered successfully", vtt->name); out_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_cleanup_proc_target_dir_entries(vtt); @@ -300,7 +300,7 @@ tgt->retry_timer.function = scst_tgt_retry_timer_fn; scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); if (target_name != NULL) { int len = strlen(target_name) + 1 + @@ -321,7 +321,7 @@ else list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list); - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); PRINT_INFO_PR("Target %s for template %s registered successfully", @@ -336,7 +336,7 @@ kfree(tgt->default_group_name); out_free_err: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); kfree(tgt); @@ -350,9 +350,9 @@ static inline int test_sess_list(struct scst_tgt *tgt) { int res; - down(&scst_mutex); + mutex_lock(&scst_mutex); res = list_empty(&tgt->sess_list); - up(&scst_mutex); + mutex_unlock(&scst_mutex); return res; } @@ -367,18 +367,18 @@ tgt->tgtt->release(tgt); TRACE_DBG("%s", "Target driver's release() returned"); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { sBUG_ON(!sess->shutting_down); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); TRACE_DBG("%s", "Waiting for sessions shutdown"); wait_event(tgt->unreg_waitQ, test_sess_list(tgt)); TRACE_DBG("%s", "wait_event() returned"); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_del(&tgt->tgt_list_entry); @@ -387,7 +387,7 @@ if (tgt->default_group_name) kfree(tgt->default_group_name); - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); del_timer_sync(&tgt->retry_timer); @@ -405,7 +405,7 @@ { TRACE_ENTRY(); - down(&scst_suspend_mutex); + mutex_lock(&scst_suspend_mutex); TRACE_MGMT_DBG("suspend_count %d", suspend_count); suspend_count++; @@ -430,7 +430,7 @@ TRACE_MGMT_DBG("%s", "wait_event() returned"); out_up: - up(&scst_suspend_mutex); + mutex_unlock(&scst_suspend_mutex); TRACE_EXIT(); return; @@ -442,7 +442,7 @@ TRACE_ENTRY(); - down(&scst_suspend_mutex); + mutex_lock(&scst_suspend_mutex); TRACE_MGMT_DBG("suspend_count %d", suspend_count); suspend_count--; @@ -470,7 +470,7 @@ wake_up_all(&scst_mgmt_cmd_list_waitQ); out_up: - up(&scst_suspend_mutex); + mutex_unlock(&scst_suspend_mutex); TRACE_EXIT(); return; @@ -485,7 +485,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); res = scst_alloc_device(GFP_KERNEL, &dev); if (res != 0) @@ -514,7 +514,7 @@ } out_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); if (res == 0) { @@ -550,7 +550,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(d, &scst_dev_list, dev_list_entry) { if (d->scsi_dev == scsidp) { @@ -582,7 +582,7 @@ scsidp->channel, scsidp->id, scsidp->lun, scsidp->type); out_unblock: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); TRACE_EXIT(); @@ -637,7 +637,7 @@ goto out; scst_suspend_activity(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out_resume; } @@ -662,7 +662,7 @@ } out_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); out_resume: scst_resume_activity(); @@ -694,7 +694,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(d, &scst_dev_list, dev_list_entry) { if (d->virt_id == id) { @@ -724,7 +724,7 @@ scst_free_device(dev); out_unblock: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); TRACE_EXIT(); @@ -756,7 +756,7 @@ #endif scst_suspend_activity(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out_err; } @@ -787,7 +787,7 @@ scst_assign_dev_handler(dev, dev_type); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); if (res == 0) { @@ -800,7 +800,7 @@ return res; out_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); out_err: scst_resume_activity(); @@ -818,7 +818,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { if (strcmp(dt->name, dev_type->name) == 0) { @@ -841,7 +841,7 @@ list_del(&dev_type->dev_type_list_entry); - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); scst_cleanup_proc_dev_handler_dir_entries(dev_type); @@ -854,7 +854,7 @@ return; out_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); goto out; } @@ -967,10 +967,10 @@ if (res != 0) goto out; - down(&scst_suspend_mutex); + mutex_lock(&scst_suspend_mutex); list_add_tail(&dev->cmd_lists.lists_list_entry, &scst_cmd_lists_list); - up(&scst_suspend_mutex); + mutex_unlock(&scst_suspend_mutex); dev->p_cmd_lists = &dev->cmd_lists; @@ -1014,9 +1014,9 @@ scst_del_dev_threads(dev, -1); if (dev->p_cmd_lists == &dev->cmd_lists) { - down(&scst_suspend_mutex); + mutex_lock(&scst_suspend_mutex); list_del(&dev->cmd_lists.lists_list_entry); - up(&scst_suspend_mutex); + mutex_unlock(&scst_suspend_mutex); } out: @@ -1127,16 +1127,16 @@ int i; /* Just to lower the race window, when user can get just changed value */ - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); i = scst_threads_info.nr_cmd_threads; - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); return i; } static void scst_threads_info_init(void) { memset(&scst_threads_info, 0, sizeof(scst_threads_info)); - init_MUTEX(&scst_threads_info.cmd_threads_mutex); + mutex_init(&scst_threads_info.cmd_threads_mutex); INIT_LIST_HEAD(&scst_threads_info.cmd_threads_list); } @@ -1222,9 +1222,9 @@ TRACE_ENTRY(); - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); res = __scst_add_cmd_threads(num); - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); TRACE_EXIT_RES(res); return res; @@ -1234,9 +1234,9 @@ { TRACE_ENTRY(); - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); __scst_del_cmd_threads(num); - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); TRACE_EXIT(); return; @@ -1246,7 +1246,7 @@ { TRACE_ENTRY(); - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); __scst_del_cmd_threads(scst_threads_info.nr_cmd_threads); if (scst_threads_info.mgmt_cmd_thread) kthread_stop(scst_threads_info.mgmt_cmd_thread); @@ -1254,7 +1254,7 @@ kthread_stop(scst_threads_info.mgmt_thread); if (scst_threads_info.init_cmd_thread) kthread_stop(scst_threads_info.init_cmd_thread); - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); TRACE_EXIT(); return; @@ -1266,7 +1266,7 @@ TRACE_ENTRY(); - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); res = __scst_add_cmd_threads(num); if (res < 0) goto out; @@ -1299,7 +1299,7 @@ } out: - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); TRACE_EXIT_RES(res); return res; } Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_lib.c 2007-07-30 11:21:04 UTC (rev 153) @@ -1085,7 +1085,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); TRACE_DBG("Removing sess %p from the list", sess); list_del(&sess->sess_list_entry); @@ -1096,7 +1096,7 @@ wake_up_all(&sess->tgt->unreg_waitQ); - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); kfree(sess->initiator_name); @@ -2599,14 +2599,14 @@ * suspending the activity isn't necessary. */ - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { scst_del_all_thr_data(tgt_dev); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); TRACE_EXIT(); return; Modified: trunk/scst/src/scst_mem.c =================================================================== --- trunk/scst/src/scst_mem.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_mem.c 2007-07-30 11:21:04 UTC (rev 153) @@ -65,7 +65,7 @@ atomic_t sgv_other_total_alloc; -DECLARE_MUTEX(scst_sgv_pool_mutex); +DEFINE_MUTEX(scst_sgv_pool_mutex); LIST_HEAD(scst_sgv_pool_list); static int scst_check_clustering(struct scatterlist *sg, int cur, int hint) @@ -643,9 +643,9 @@ } } - down(&scst_sgv_pool_mutex); + mutex_lock(&scst_sgv_pool_mutex); list_add_tail(&pool->sgv_pool_list_entry, &scst_sgv_pool_list); - up(&scst_sgv_pool_mutex); + mutex_unlock(&scst_sgv_pool_mutex); res = 0; @@ -676,9 +676,9 @@ pool->caches[i] = NULL; } - down(&scst_sgv_pool_mutex); + mutex_lock(&scst_sgv_pool_mutex); list_del(&pool->sgv_pool_list_entry); - up(&scst_sgv_pool_mutex); + mutex_unlock(&scst_sgv_pool_mutex); TRACE_EXIT(); } Modified: trunk/scst/src/scst_mem.h =================================================================== --- trunk/scst/src/scst_mem.h 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_mem.h 2007-07-30 11:21:04 UTC (rev 153) @@ -86,7 +86,7 @@ }; extern atomic_t sgv_other_total_alloc; -extern struct semaphore scst_sgv_pool_mutex; +extern struct mutex scst_sgv_pool_mutex; extern struct list_head scst_sgv_pool_list; int sgv_pool_init(struct sgv_pool *pool, const char *name, Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_priv.h 2007-07-30 11:21:04 UTC (rev 153) @@ -154,14 +154,14 @@ extern struct scst_sgv_pools scst_sgv; extern unsigned long scst_flags; -extern struct semaphore scst_mutex; +extern struct mutex scst_mutex; extern atomic_t scst_cmd_count; extern struct list_head scst_template_list; /* protected by scst_mutex */ extern struct list_head scst_dev_list; /* protected by scst_mutex */ extern struct list_head scst_dev_type_list; /* protected by scst_mutex */ extern wait_queue_head_t scst_dev_cmd_waitQ; -extern struct semaphore scst_suspend_mutex; +extern struct mutex scst_suspend_mutex; extern struct list_head scst_cmd_lists_list; /* protected by scst_suspend_mutex */ extern struct list_head scst_acg_list; @@ -206,7 +206,7 @@ }; struct scst_threads_info_t { - struct semaphore cmd_threads_mutex; + struct mutex cmd_threads_mutex; u32 nr_cmd_threads; struct list_head cmd_threads_list; struct task_struct *init_cmd_thread; Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_proc.c 2007-07-30 11:21:04 UTC (rev 153) @@ -163,7 +163,7 @@ "Optical card reader/writer device" }; -static DECLARE_MUTEX(scst_proc_mutex); +static DEFINE_MUTEX(scst_proc_mutex); #include <linux/ctype.h> @@ -195,7 +195,7 @@ #if defined(DEBUG) || defined(TRACING) -static DECLARE_MUTEX(scst_log_mutex); +static DEFINE_MUTEX(scst_log_mutex); int scst_proc_log_entry_write(struct file *file, const char *buf, unsigned long length, unsigned long *log_level, @@ -358,7 +358,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_log_mutex) != 0) { + if (mutex_lock_interruptible(&scst_log_mutex) != 0) { res = -EINTR; goto out; } @@ -366,7 +366,7 @@ res = scst_proc_log_entry_write(file, buf, length, &trace_flag, SCST_DEFAULT_LOG_FLAGS, scst_proc_local_trace_tbl); - up(&scst_log_mutex); + mutex_unlock(&scst_log_mutex); out: TRACE_EXIT_RES(res); @@ -769,12 +769,12 @@ goto out_free; } - if (down_interruptible(&scst_proc_mutex) != 0) { + if (mutex_lock_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out_free; } - down(&scst_threads_info.cmd_threads_mutex); + mutex_lock(&scst_threads_info.cmd_threads_mutex); oldtn = scst_threads_info.nr_cmd_threads; newtn = simple_strtoul(buffer, NULL, 0); @@ -792,9 +792,9 @@ PRINT_INFO_PR("Changed cmd threads num: old %d, new %d", oldtn, newtn); out_up_thr_free: - up(&scst_threads_info.cmd_threads_mutex); + mutex_unlock(&scst_threads_info.cmd_threads_mutex); - up(&scst_proc_mutex); + mutex_unlock(&scst_proc_mutex); out_free: free_page((unsigned long)buffer); @@ -925,14 +925,14 @@ TRACE_BUFFER("Buffer", buffer, length); - if (down_interruptible(&scst_proc_mutex) != 0) { + if (mutex_lock_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out_free; } res = vtt->tgtt->write_proc(buffer, &start, 0, length, &eof, vtt); - up(&scst_proc_mutex); + mutex_unlock(&scst_proc_mutex); out_free: free_page((unsigned long)buffer); @@ -1066,14 +1066,14 @@ TRACE_BUFFER("Buffer", buffer, length); - if (down_interruptible(&scst_proc_mutex) != 0) { + if (mutex_lock_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out_free; } res = dev_type->write_proc(buffer, &start, 0, length, &eof, dev_type); - up(&scst_proc_mutex); + mutex_unlock(&scst_proc_mutex); out_free: free_page((unsigned long)buffer); @@ -1142,7 +1142,7 @@ scst_suspend_activity(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out_free_resume; } @@ -1192,7 +1192,7 @@ res = rc; out_up_free: - up(&scst_mutex); + mutex_unlock(&scst_mutex); out_free_resume: scst_resume_activity(); @@ -1366,7 +1366,7 @@ scst_suspend_activity(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out_free_resume; } @@ -1486,7 +1486,7 @@ } out_free_up: - up(&scst_mutex); + mutex_unlock(&scst_mutex); out_free_resume: scst_resume_activity(); @@ -1569,7 +1569,7 @@ break; } - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out_free; } @@ -1591,7 +1591,7 @@ break; } - up(&scst_mutex); + mutex_unlock(&scst_mutex); out_free: free_page((unsigned long)buffer); @@ -1689,7 +1689,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out; } @@ -1707,7 +1707,7 @@ } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); out: TRACE_EXIT_RES(res); @@ -1747,11 +1747,11 @@ seq_printf(seq, "%-30s %-11s %-11s", "Name", "Hit", "Total"); - down(&scst_sgv_pool_mutex); + mutex_lock(&scst_sgv_pool_mutex); list_for_each_entry(pool, &scst_sgv_pool_list, sgv_pool_list_entry) { scst_do_sgv_read(seq, pool); } - up(&scst_sgv_pool_mutex); + mutex_unlock(&scst_sgv_pool_mutex); seq_printf(seq, "\n%-42s %-11d\n", "other", atomic_read(&sgv_other_total_alloc)); @@ -1772,7 +1772,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out; } @@ -1781,7 +1781,7 @@ seq_printf(seq, "%s\n", name->name); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); out: TRACE_EXIT_RES(res); @@ -1801,7 +1801,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out; } @@ -1831,7 +1831,7 @@ acg_dev->rd_only_flag ? "RO" : ""); } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); out: TRACE_EXIT_RES(res); @@ -1886,14 +1886,14 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_log_mutex) != 0) { + if (mutex_lock_interruptible(&scst_log_mutex) != 0) { res = -EINTR; goto out; } res = scst_proc_log_entry_read(seq, trace_flag, scst_proc_local_trace_tbl); - up(&scst_log_mutex); + mutex_unlock(&scst_log_mutex); out: TRACE_EXIT_RES(res); @@ -1915,7 +1915,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_mutex) != 0) { + if (mutex_lock_interruptible(&scst_mutex) != 0) { res = -EINTR; goto out; } @@ -1937,7 +1937,7 @@ seq_printf(seq, "%-60s%s\n", dev->virt_name, dev->handler->name); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); out: TRACE_EXIT_RES(res); @@ -1971,7 +1971,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_proc_mutex) != 0) { + if (mutex_lock_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out; } @@ -1979,7 +1979,7 @@ if (vtt->tgtt->read_proc) res = vtt->tgtt->read_proc(seq, vtt); - up(&scst_proc_mutex); + mutex_unlock(&scst_proc_mutex); out: TRACE_EXIT_RES(res); return res; @@ -1997,7 +1997,7 @@ TRACE_ENTRY(); - if (down_interruptible(&scst_proc_mutex) != 0) { + if (mutex_lock_interruptible(&scst_proc_mutex) != 0) { res = -EINTR; goto out; } @@ -2005,7 +2005,7 @@ if (dev_type->read_proc) res = dev_type->read_proc(seq, dev_type); - up(&scst_proc_mutex); + mutex_unlock(&scst_proc_mutex); out: TRACE_EXIT_RES(res); Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-23 11:51:05 UTC (rev 152) +++ trunk/scst/src/scst_targ.c 2007-07-30 11:21:04 UTC (rev 153) @@ -1001,6 +1001,43 @@ return; } +static int scst_tgt_pre_exec(struct scst_cmd *cmd, int *action) +{ + int res = 0, rc; + + TRACE_ENTRY(); + + TRACE_DBG("Calling pre_exec(%p)", cmd); + rc = cmd->tgtt->pre_exec(cmd); + TRACE_DBG("pre_exec() returned %d", rc); + + if (unlikely(rc != SCST_PREPROCESS_STATUS_SUCCESS)) { + switch(rc) { + case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET: + cmd->state = SCST_CMD_STATE_DEV_DONE; + *action = SCST_CMD_STATE_RES_CONT_SAME; + res = -1; + break; + case SCST_PREPROCESS_STATUS_ERROR_FATAL: + set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags); + /* go through */ + case SCST_PREPROCESS_STATUS_ERROR: + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_hardw_error)); + cmd->state = SCST_CMD_STATE_DEV_DONE; + *action = SCST_CMD_STATE_RES_CONT_SAME; + res = -1; + break; + default: + sBUG(); + break; + } + } + + TRACE_EXIT_RES(res); + return res; +} + static void scst_inc_check_expected_sn(struct scst_cmd *cmd) { struct scst_cmd *c; @@ -1812,6 +1849,12 @@ res = SCST_CMD_STATE_RES_CONT_NEXT; + if (cmd->tgtt->pre_exec != NULL) { + rc = scst_tgt_pre_exec(cmd, &res); + if (unlikely(rc != 0)) + goto out; + } + if (unlikely(scst_inc_on_dev_cmd(cmd) != 0)) goto out; @@ -3229,7 +3272,7 @@ TRACE_ENTRY(); if (!scst_mutex_held) - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { struct scst_cmd *cmd, *tcmd; @@ -3264,7 +3307,7 @@ } if (!scst_mutex_held) - up(&scst_mutex); + mutex_unlock(&scst_mutex); TRACE_EXIT(); return; @@ -3406,7 +3449,7 @@ TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)", mcmd, atomic_read(&mcmd->sess->sess_cmd_count)); - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { int found = 0; @@ -3472,7 +3515,7 @@ dev->scsi_dev->was_reset = 0; } - up(&scst_mutex); + mutex_unlock(&scst_mutex); tm_dbg_task_mgmt("TARGET RESET", 0); res = scst_set_mcmd_next_state(mcmd); @@ -3537,7 +3580,7 @@ mcmd); } - down(&scst_mutex); + mutex_lock(&scst_mutex); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = &sess->sess_tgt_dev_list_hash[i]; @@ -3559,7 +3602,7 @@ mcmd->status = rc; } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); res = scst_set_mcmd_next_state(mcmd); @@ -3588,7 +3631,7 @@ mcmd); } - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { spin_lock_bh(&dev->dev_lock); @@ -3616,7 +3659,7 @@ } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); res = scst_set_mcmd_next_state(mcmd); @@ -3728,11 +3771,11 @@ case SCST_TARGET_RESET: case SCST_ABORT_ALL_TASKS: case SCST_NEXUS_LOSS: - down(&scst_mutex); + mutex_lock(&scst_mutex); list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { scst_unblock_dev(dev); } - up(&scst_mutex); + mutex_unlock(&scst_mutex); break; case SCST_NEXUS_LOSS_SESS: @@ -3740,7 +3783,7 @@ { int i; - down(&scst_mutex); + mutex_lock(&scst_mutex); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = &mcmd->sess->sess_tgt_dev_list_hash[i]; @@ -3749,7 +3792,7 @@ scst_unblock_dev(tgt_dev->dev); } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); break; } @@ -4116,7 +4159,7 @@ TRACE_ENTRY(); scst_suspend_activity(); - down(&scst_mutex); + mutex_lock(&scst_mutex); if (sess->initiator_name) acg = scst_find_acg(sess->initiator_name); @@ -4137,7 +4180,7 @@ res = scst_sess_alloc_tgt_devs(sess); - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_resume_activity(); if (sess->init_result_fn) { @@ -4259,7 +4302,7 @@ TRACE_ENTRY(); - down(&scst_mutex); + mutex_lock(&scst_mutex); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = &sess->sess_tgt_dev_list_hash[i]; @@ -4275,7 +4318,7 @@ } } } - up(&scst_mutex); + mutex_unlock(&scst_mutex); scst_sess_put(sess); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-07-31 14:22:50
|
Revision: 154 http://scst.svn.sourceforge.net/scst/?rev=154&view=rev Author: vlnb Date: 2007-07-31 07:21:46 -0700 (Tue, 31 Jul 2007) Log Message: ----------- - Device blocking cleanups and fixes - tags logging made unsigned Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-30 11:21:04 UTC (rev 153) +++ trunk/scst/include/scsi_tgt.h 2007-07-31 14:21:46 UTC (rev 154) @@ -951,9 +951,15 @@ /* Set if cmd is being retried */ unsigned int retry:1; - /* Set if the device should be unblock after cmd's finish */ - unsigned int blocking:1; + /* Set if the device was blocked by scst_inc_on_dev_cmd() (for debug) */ + unsigned int inc_blocking:1; + /* Set if the device should be unblocked after cmd's finish */ + unsigned int needs_unblocking:1; + + /* Set if scst_dec_on_dev_cmd() call is needed on the cmd's finish */ + unsigned int dec_on_dev_needed:1; + /* * Set if the target driver wants to alloc data buffers on its own. * In this case alloc_data_buf() must be provided in the target driver Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-30 11:21:04 UTC (rev 153) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-31 14:21:46 UTC (rev 154) @@ -657,7 +657,7 @@ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { TRACE_MGMT_DBG("Flag ABORTED set for " - "cmd %p (tag %lld), skipping", cmd, cmd->tag); + "cmd %p (tag %llu), skipping", cmd, cmd->tag); goto done_uncompl; } Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-30 11:21:04 UTC (rev 153) +++ trunk/scst/src/scst_lib.c 2007-07-31 14:21:46 UTC (rev 154) @@ -126,7 +126,7 @@ l += cmd->sg[i].length; if (l >= resp_data_len) { int left = resp_data_len - (l - cmd->sg[i].length); - TRACE(TRACE_SG|TRACE_MEMORY, "cmd %p (tag %lld), " + TRACE(TRACE_SG|TRACE_MEMORY, "cmd %p (tag %llu), " "resp_data_len %d, i %d, cmd->sg[i].length %d, " "left %d", cmd, cmd->tag, resp_data_len, i, cmd->sg[i].length, left); @@ -1199,12 +1199,15 @@ TRACE_ENTRY(); + TRACE_DBG("Freeing cmd %p (tag %Lu)", cmd, cmd->tag); + if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { TRACE_MGMT_DBG("Freeing aborted cmd %p (scst_cmd_count %d)", cmd, atomic_read(&scst_cmd_count)); } - sBUG_ON(cmd->blocking); + sBUG_ON(cmd->inc_blocking || cmd->needs_unblocking || + cmd->dec_on_dev_needed); #if defined(EXTRACHECKS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) if (cmd->scsi_req) { @@ -1267,7 +1270,7 @@ #endif if (unlikely(cmd->out_of_sn)) { - TRACE_SN("Out of SN cmd %p (tag %lld, sn %ld), " + TRACE_SN("Out of SN cmd %p (tag %llu, sn %ld), " "destroy=%d", cmd, cmd->tag, cmd->sn, destroy); destroy = test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED, &cmd->cmd_flags); @@ -2536,7 +2539,7 @@ * !! sn_slot and sn_cmd_list_entry, could be !! * !! already destroyed !! */ - TRACE_SN("cmd %p (tag %lld) with skipped sn %ld found", + TRACE_SN("cmd %p (tag %llu) with skipped sn %ld found", cmd, cmd->tag, cmd->sn); tgt_dev->def_cmd_count--; list_del(&cmd->sn_cmd_list_entry); @@ -2628,7 +2631,59 @@ return res; } +/* dev_lock supposed to be held and BH disabled */ +void __scst_block_dev(struct scst_device *dev) +{ + dev->block_count++; + smp_mb(); + TRACE_MGMT_DBG("Device BLOCK(new %d), dev %p", dev->block_count, dev); +} + /* No locks */ +void scst_block_dev(struct scst_device *dev, int outstanding) +{ + spin_lock_bh(&dev->dev_lock); + __scst_block_dev(dev); + spin_unlock_bh(&dev->dev_lock); + + TRACE_MGMT_DBG("Waiting during blocking outstanding %d (on_dev_count " + "%d)", outstanding, atomic_read(&dev->on_dev_count)); + wait_event(dev->on_dev_waitQ, + atomic_read(&dev->on_dev_count) <= outstanding); + TRACE_MGMT_DBG("%s", "wait_event() returned"); +} + +/* No locks */ +void scst_block_dev_cmd(struct scst_cmd *cmd, int outstanding) +{ + sBUG_ON(cmd->needs_unblocking); + + cmd->needs_unblocking = 1; + TRACE_MGMT_DBG("Needs unblocking cmd %p (tag %llu)", cmd, cmd->tag); + + scst_block_dev(cmd->dev, outstanding); +} + +/* No locks */ +void scst_unblock_dev(struct scst_device *dev) +{ + spin_lock_bh(&dev->dev_lock); + TRACE_MGMT_DBG("Device UNBLOCK(new %d), dev %p", + dev->block_count-1, dev); + if (--dev->block_count == 0) + scst_unblock_cmds(dev); + spin_unlock_bh(&dev->dev_lock); + sBUG_ON(dev->block_count < 0); +} + +/* No locks */ +void scst_unblock_dev_cmd(struct scst_cmd *cmd) +{ + scst_unblock_dev(cmd->dev); + cmd->needs_unblocking = 0; +} + +/* No locks */ int scst_inc_on_dev_cmd(struct scst_cmd *cmd) { int res = 0; @@ -2636,24 +2691,26 @@ TRACE_ENTRY(); - sBUG_ON(cmd->blocking); + sBUG_ON(cmd->inc_blocking || cmd->dec_on_dev_needed); atomic_inc(&dev->on_dev_count); + cmd->dec_on_dev_needed = 1; + TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count)); #ifdef STRICT_SERIALIZING spin_lock_bh(&dev->dev_lock); if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) goto out_unlock; if (dev->block_count > 0) { - scst_dec_on_dev_cmd(cmd, 0); - TRACE_MGMT_DBG("Delaying cmd %p due to blocking or serializing" - "(tag %lld, dev %p)", cmd, cmd->tag, dev); + scst_dec_on_dev_cmd(cmd); + TRACE_MGMT_DBG("Delaying cmd %p due to blocking or strict " + "serializing (tag %llu, dev %p)", cmd, cmd->tag, dev); list_add_tail(&cmd->blocked_cmd_list_entry, &dev->blocked_cmd_list); res = 1; } else { __scst_block_dev(dev); - cmd->blocking = 1; + cmd->inc_blocking = 1; } spin_unlock_bh(&dev->dev_lock); goto out; @@ -2665,9 +2722,9 @@ goto out_unlock; barrier(); /* to reread block_count */ if (dev->block_count > 0) { - scst_dec_on_dev_cmd(cmd, 0); + scst_dec_on_dev_cmd(cmd); TRACE_MGMT_DBG("Delaying cmd %p due to blocking or " - "serializing (tag %lld, dev %p)", cmd, + "serializing (tag %llu, dev %p)", cmd, cmd->tag, dev); list_add_tail(&cmd->blocked_cmd_list_entry, &dev->blocked_cmd_list); @@ -2684,11 +2741,11 @@ spin_lock_bh(&dev->dev_lock); barrier(); /* to reread block_count */ if (dev->block_count == 0) { - TRACE_MGMT_DBG("cmd %p (tag %lld), blocking further " + TRACE_MGMT_DBG("cmd %p (tag %llu), blocking further " "cmds due to serializing (dev %p)", cmd, cmd->tag, dev); __scst_block_dev(dev); - cmd->blocking = 1; + cmd->inc_blocking = 1; } else { spin_unlock_bh(&dev->dev_lock); TRACE_MGMT_DBG("Somebody blocked the device, " @@ -2960,7 +3017,7 @@ case TM_DBG_STATE_ABORT: if (tm_dbg_delayed_cmds_count == 0) { unsigned long d = 58*HZ + (scst_random() % (4*HZ)); - TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %lld) " + TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %llu) " "for %ld.%ld seconds (%ld HZ), " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, d/HZ, (d%HZ)*100/HZ, d, tm_dbg_on_state_passes); @@ -2970,7 +3027,7 @@ #endif } else { TRACE_MGMT_DBG("Delaying another timed cmd %p " - "(tag %lld), delayed_cmds_count=%d, " + "(tag %llu), delayed_cmds_count=%d, " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes); @@ -2982,7 +3039,7 @@ case TM_DBG_STATE_RESET: case TM_DBG_STATE_OFFLINE: TRACE_MGMT_DBG("STATE RESET/OFFLINE: delaying cmd %p " - "(tag %lld), delayed_cmds_count=%d, " + "(tag %llu), delayed_cmds_count=%d, " "tm_dbg_on_state_passes=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes); tm_dbg_flags.tm_dbg_blocked = 1; @@ -3008,7 +3065,7 @@ spin_lock_irq(&scst_tm_dbg_lock); list_for_each_entry_safe_reverse(cmd, tc, &tm_dbg_delayed_cmd_list, cmd_list_entry) { - TRACE_MGMT_DBG("Releasing timed cmd %p (tag %lld), " + TRACE_MGMT_DBG("Releasing timed cmd %p (tag %llu), " "delayed_cmds_count=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count); spin_lock(&cmd->cmd_lists->cmd_list_lock); @@ -3070,7 +3127,7 @@ if (cmd->tm_dbg_delayed) { spin_lock_irqsave(&scst_tm_dbg_lock, flags); - TRACE_MGMT_DBG("Processing delayed cmd %p (tag %lld), " + TRACE_MGMT_DBG("Processing delayed cmd %p (tag %llu), " "delayed_cmds_count=%d", cmd, cmd->tag, tm_dbg_delayed_cmds_count); @@ -3108,7 +3165,7 @@ cmd_list_entry) { if (c == cmd) { TRACE_MGMT_DBG("Abort request for " - "delayed cmd %p (tag=%lld), moving it to " + "delayed cmd %p (tag=%llu), moving it to " "active cmd list (delayed_cmds_count=%d)", c, c->tag, tm_dbg_delayed_cmds_count); spin_lock(&cmd->cmd_lists->cmd_list_lock); Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-07-30 11:21:04 UTC (rev 153) +++ trunk/scst/src/scst_priv.h 2007-07-31 14:21:46 UTC (rev 154) @@ -414,61 +414,43 @@ extern int scst_inc_on_dev_cmd(struct scst_cmd *cmd); extern void scst_unblock_cmds(struct scst_device *dev); -static inline void __scst_block_dev(struct scst_device *dev) -{ - dev->block_count++; - smp_mb(); - TRACE_MGMT_DBG("Device BLOCK(%d), dev %p", dev->block_count, dev); -} +extern void __scst_block_dev(struct scst_device *dev); +extern void scst_block_dev(struct scst_device *dev, int outstanding); +extern void scst_block_dev_cmd(struct scst_cmd *cmd, int outstanding); +extern void scst_unblock_dev(struct scst_device *dev); +extern void scst_unblock_dev_cmd(struct scst_cmd *cmd); -static inline void scst_block_dev(struct scst_device *dev, - int outstanding) -{ - spin_lock_bh(&dev->dev_lock); - __scst_block_dev(dev); - spin_unlock_bh(&dev->dev_lock); - - TRACE_MGMT_DBG("Waiting during blocking outstanding %d (on_dev_count " - "%d)", outstanding, atomic_read(&dev->on_dev_count)); - wait_event(dev->on_dev_waitQ, - atomic_read(&dev->on_dev_count) <= outstanding); - TRACE_MGMT_DBG("%s", "wait_event() returned"); -} - -static inline void scst_unblock_dev(struct scst_device *dev) -{ - spin_lock_bh(&dev->dev_lock); - TRACE_MGMT_DBG("Device UNBLOCK(%d), dev %p", - dev->block_count-1, dev); - if (--dev->block_count == 0) - scst_unblock_cmds(dev); - spin_unlock_bh(&dev->dev_lock); -} - static inline void __scst_dec_on_dev_cmd(struct scst_device *dev, - int cmd_blocking) + int unblock_dev) { - if (cmd_blocking) + if (unblock_dev) scst_unblock_dev(dev); atomic_dec(&dev->on_dev_count); smp_mb__after_atomic_dec(); + TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count)); + sBUG_ON(atomic_read(&dev->on_dev_count) < 0); if (unlikely(dev->block_count != 0)) wake_up_all(&dev->on_dev_waitQ); } -static inline int scst_dec_on_dev_cmd(struct scst_cmd *cmd, int defer) +static inline int scst_pre_dec_on_dev_cmd(struct scst_cmd *cmd) { - int cmd_blocking = cmd->blocking; + int cmd_blocking = cmd->inc_blocking; if (cmd_blocking) { - TRACE_MGMT_DBG("cmd %p (tag %lld): unblocking dev %p", cmd, + TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %p", cmd, cmd->tag, cmd->dev); - cmd->blocking = 0; + cmd->inc_blocking = 0; } - if (!defer) - __scst_dec_on_dev_cmd(cmd->dev, cmd_blocking); + cmd->dec_on_dev_needed = 0; return cmd_blocking; } +static inline void scst_dec_on_dev_cmd(struct scst_cmd *cmd) +{ + int cmd_blocking = scst_pre_dec_on_dev_cmd(cmd); + __scst_dec_on_dev_cmd(cmd->dev, cmd_blocking); +} + static inline void __scst_get(int barrier) { atomic_inc(&scst_cmd_count); Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-30 11:21:04 UTC (rev 153) +++ trunk/scst/src/scst_targ.c 2007-07-31 14:21:46 UTC (rev 154) @@ -165,7 +165,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd); - TRACE(TRACE_SCSI, "tag=%lld, lun=%Ld, CDB len=%d", cmd->tag, + TRACE(TRACE_SCSI, "tag=%llu, lun=%Ld, CDB len=%d", cmd->tag, (uint64_t)cmd->lun, cmd->cdb_len); TRACE_BUFF_FLAG(TRACE_SCSI|TRACE_RECV_BOT, "Recieving CDB", cmd->cdb, cmd->cdb_len); @@ -700,7 +700,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d", pref_context); - TRACE_DBG("tag=%lld, status=%#x", scst_cmd_get_tag(cmd), status); + TRACE_DBG("tag=%llu, status=%#x", scst_cmd_get_tag(cmd), status); #ifdef EXTRACHECKS if (in_irq() && ((pref_context == SCST_CONTEXT_DIRECT) || @@ -950,7 +950,7 @@ TRACE_ENTRY(); TRACE_DBG("Preferred context: %d", pref_context); - TRACE(TRACE_SCSI, "tag=%lld status=%#x", scst_cmd_get_tag(cmd), status); + TRACE(TRACE_SCSI, "tag=%llu status=%#x", scst_cmd_get_tag(cmd), status); #ifdef EXTRACHECKS if (in_irq() && ((pref_context == SCST_CONTEXT_DIRECT) || @@ -1095,7 +1095,9 @@ cmd->completed = 1; - scst_dec_on_dev_cmd(cmd, 0); + if (likely(cmd->host_status != DID_RESET) && + likely(!SCST_SENSE_VALID(cmd->sense_buffer))) + scst_dec_on_dev_cmd(cmd); type = cmd->dev->handler->type; if ((cmd->cdb[0] == MODE_SENSE || cmd->cdb[0] == MODE_SENSE_10) && @@ -1218,7 +1220,8 @@ { TRACE_ENTRY(); - scst_dec_on_dev_cmd(cmd, 0); + if (likely(!SCST_SENSE_VALID(cmd->sense_buffer))) + scst_dec_on_dev_cmd(cmd); if (cmd->inc_expected_sn_on_done) scst_inc_check_expected_sn(cmd); @@ -1383,8 +1386,7 @@ goto out; } - scst_block_dev(cmd->dev, 1); - /* Device will be unblocked in scst_done_cmd_check() */ + scst_block_dev_cmd(cmd, 1); if (test_bit(SCST_TGT_DEV_UA_PENDING, &cmd->tgt_dev->tgt_dev_flags)) { int rc = scst_set_pending_UA(cmd); @@ -1439,9 +1441,9 @@ } dev = cmd->dev; - scst_block_dev(dev, 1); - /* Device will be unblocked in scst_done_cmd_check() */ + scst_block_dev_cmd(cmd, 1); + spin_lock_bh(&dev->dev_lock); if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { @@ -1478,9 +1480,7 @@ dev = cmd->dev; - scst_block_dev(dev, 1); - cmd->blocking = 1; - TRACE_MGMT_DBG("Blocking cmd %p (tag %lld)", cmd, cmd->tag); + scst_block_dev_cmd(cmd, 1); spin_lock_bh(&dev->dev_lock); @@ -1867,7 +1867,7 @@ TRACE_DBG("%s", "scst_do_send_to_midlev() requested " "thread context, rescheduling"); res = SCST_CMD_STATE_RES_NEED_THREAD; - scst_dec_on_dev_cmd(cmd, 0); + scst_dec_on_dev_cmd(cmd); goto out_dec_cmd_count; } else { sBUG_ON(rc != SCST_EXEC_COMPLETED); @@ -1887,7 +1887,7 @@ scst_cmd_put(cmd); goto exec; } else { - scst_dec_on_dev_cmd(cmd, 0); + scst_dec_on_dev_cmd(cmd); scst_cmd_put(cmd); goto out_unplug; } @@ -1905,10 +1905,10 @@ if ((cmd->sn != expected_sn) || test_bit(SCST_TGT_DEV_HQ_ACTIVE, &tgt_dev->tgt_dev_flags)) { /* We are under IRQ lock, but dev->dev_lock is BH one */ - int cmd_blocking = scst_dec_on_dev_cmd(cmd, 1); + int cmd_blocking = scst_pre_dec_on_dev_cmd(cmd); if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { /* Necessary to allow aborting out of sn cmds */ - TRACE_MGMT_DBG("Aborting out of sn cmd %p (tag %lld)", + TRACE_MGMT_DBG("Aborting out of sn cmd %p (tag %llu)", cmd, cmd->tag); tgt_dev->def_cmd_count--; cmd->state = SCST_CMD_STATE_DEV_DONE; @@ -1954,7 +1954,7 @@ &tgt_dev->hq_cmd_list); spin_unlock_irq(&tgt_dev->sn_lock); } - scst_dec_on_dev_cmd(cmd, 0); + scst_dec_on_dev_cmd(cmd); if (count != 0) goto out_unplug; else @@ -2025,20 +2025,19 @@ spin_unlock_bh(&dev->dev_lock); } - if (sense_valid) { + if (unlikely(sense_valid)) { TRACE_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense_buffer, - sizeof(cmd->sense_buffer)); + sizeof(cmd->sense_buffer)); /* Check Unit Attention Sense Key */ if (cmd->sense_buffer[2] == UNIT_ATTENTION) { if (cmd->sense_buffer[12] == SCST_SENSE_ASC_UA_RESET) { - if (dbl_ua_possible) - { + if (dbl_ua_possible) { if (ua_sent) { TRACE(TRACE_MGMT, "%s", "Double UA detected"); /* Do retry */ TRACE(TRACE_MGMT, "Retrying cmd %p " - "(tag %lld)", cmd, cmd->tag); + "(tag %llu)", cmd, cmd->tag); cmd->status = 0; cmd->msg_status = 0; cmd->host_status = DID_OK; @@ -2223,7 +2222,6 @@ } cmd->dev->dev_reserved = 0; } - scst_unblock_dev(cmd->dev); } if (unlikely((cmd->cdb[0] == MODE_SELECT) || @@ -2248,7 +2246,6 @@ sizeof(scst_temp_UA), 1); spin_unlock_bh(&scst_temp_UA_lock); } - scst_unblock_dev(cmd->dev); } out: @@ -2258,7 +2255,7 @@ static int scst_dev_done(struct scst_cmd *cmd) { - int res = SCST_CMD_STATE_RES_CONT_SAME; + int res = SCST_CMD_STATE_RES_CONT_SAME, rc; int state; int atomic = scst_cmd_atomic(cmd); @@ -2273,7 +2270,15 @@ goto out; } - if (scst_done_cmd_check(cmd, &res)) + rc = scst_done_cmd_check(cmd, &res); + + if (cmd->needs_unblocking) + scst_unblock_dev_cmd(cmd); + + if (unlikely(cmd->dec_on_dev_needed)) + scst_dec_on_dev_cmd(cmd); + + if (rc) goto out; state = SCST_CMD_STATE_XMIT_RESP; @@ -2373,13 +2378,13 @@ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { if (test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags)) { TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p " - "(tag %lld), returning TASK ABORTED", cmd, cmd->tag); + "(tag %llu), returning TASK ABORTED", cmd, cmd->tag); scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED); } } if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) { - TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %lld), skipping", + TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), skipping", cmd, cmd->tag); cmd->state = SCST_CMD_STATE_FINISHED; res = SCST_CMD_STATE_RES_CONT_SAME; @@ -2393,7 +2398,7 @@ res = SCST_CMD_STATE_RES_NEED_THREAD; goto out; } - TRACE_MGMT_DBG("Delaying cmd %p (tag %lld) for 1 second", + TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second", cmd, cmd->tag); schedule_timeout_uninterruptible(HZ); } @@ -2746,7 +2751,7 @@ goto restart; } } else { - TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %lld)", + TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %llu)", cmd, cmd->tag); cmd->state = SCST_CMD_STATE_XMIT_RESP; } @@ -2866,7 +2871,7 @@ case SCST_CMD_STATE_SEND_TO_MIDLEV: if (tm_dbg_check_cmd(cmd) != 0) { res = SCST_CMD_STATE_RES_CONT_NEXT; - TRACE_MGMT_DBG("Skipping cmd %p (tag %lld), " + TRACE_MGMT_DBG("Skipping cmd %p (tag %llu), " "because of TM DBG delay", cmd, cmd->tag); break; @@ -3094,7 +3099,7 @@ spin_lock_irq(&scst_mcmd_lock); - TRACE_MGMT_DBG("cmd %p completed (tag %lld, mcmd %p, " + TRACE_MGMT_DBG("cmd %p completed (tag %llu, mcmd %p, " "mcmd->cmd_wait_count %d)", cmd, cmd->tag, mcmd, mcmd->cmd_wait_count); @@ -3172,7 +3177,7 @@ { TRACE_ENTRY(); - TRACE(TRACE_MGMT, "Aborting cmd %p (tag %lld)", cmd, cmd->tag); + TRACE(TRACE_MGMT, "Aborting cmd %p (tag %llu)", cmd, cmd->tag); if (other_ini) { set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); @@ -3204,12 +3209,12 @@ * we must wait here to be sure that we won't receive * double commands with the same tag. */ - TRACE(TRACE_MGMT, "cmd %p (tag %lld) being executed/" + TRACE(TRACE_MGMT, "cmd %p (tag %llu) being executed/" "xmitted (state %d), deferring ABORT...", cmd, cmd->tag, cmd->state); #ifdef EXTRACHECKS if (cmd->mgmt_cmnd) { - printk(KERN_ALERT "cmd %p (tag %lld, state %d) " + printk(KERN_ALERT "cmd %p (tag %llu, state %d) " "has non-NULL mgmt_cmnd %p!!! Current " "mcmd %p\n", cmd, cmd->tag, cmd->state, cmd->mgmt_cmnd, mcmd); @@ -3400,7 +3405,7 @@ cmd = __scst_find_cmd_by_tag(sess, mcmd->tag); if (cmd == NULL) { TRACE(TRACE_MGMT, "ABORT TASK failed: command for " - "tag %lld not found", mcmd->tag); + "tag %llu not found", mcmd->tag); mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST; mcmd->state = SCST_MGMT_CMD_STATE_DONE; spin_unlock_irq(&sess->sess_list_lock); @@ -3408,7 +3413,7 @@ } scst_cmd_get(cmd); spin_unlock_irq(&sess->sess_list_lock); - TRACE(TRACE_MGMT, "Cmd %p for tag %lld (sn %ld) found, " + TRACE(TRACE_MGMT, "Cmd %p for tag %llu (sn %ld) found, " "aborting it", cmd, mcmd->tag, cmd->sn); mcmd->cmd_to_abort = cmd; scst_abort_cmd(cmd, mcmd, 0, 1); @@ -4084,7 +4089,7 @@ mcmd->tag = tag; - TRACE(TRACE_MGMT, "sess=%p, tag=%lld", sess, mcmd->tag); + TRACE(TRACE_MGMT, "sess=%p, tag=%llu", sess, mcmd->tag); if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0) goto out_free; @@ -4462,7 +4467,7 @@ /* ToDo: hash list */ - TRACE_DBG("%s (sess=%p, tag=%lld)", "Searching in search cmd list", + TRACE_DBG("%s (sess=%p, tag=%llu)", "Searching in search cmd list", sess, tag); list_for_each_entry(cmd, &sess->search_cmd_list, search_cmd_list_entry) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-08-03 09:57:45
|
Revision: 155 http://scst.svn.sourceforge.net/scst/?rev=155&view=rev Author: vlnb Date: 2007-08-03 02:57:15 -0700 (Fri, 03 Aug 2007) Log Message: ----------- - In scst_user fixed potential deadlock - scst_check_local_events() added - Minor cleanups and fixes Modified Paths: -------------- trunk/scst/ToDo trunk/scst/include/scsi_tgt.h trunk/scst/src/Makefile trunk/scst/src/dev_handlers/scst_disk.c trunk/scst/src/dev_handlers/scst_modisk.c trunk/scst/src/dev_handlers/scst_tape.c trunk/scst/src/dev_handlers/scst_user.c trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_mem.c trunk/scst/src/scst_proc.c trunk/scst/src/scst_targ.c Modified: trunk/scst/ToDo =================================================================== --- trunk/scst/ToDo 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/ToDo 2007-08-03 09:57:15 UTC (rev 155) @@ -8,7 +8,7 @@ the page cache (in order to avoid data copy between it and internal buffers). Requires modifications of the kernel. - - O_DIRECT mode doesn't work (oops'es somewhere in the kernel) + - O_DIRECT mode doesn't work for FILEIO (oops'es somewhere in the kernel) - Close integration with Linux initiator SCSI mil-level, including queue types (simple, ordered, etc.) and local initiators (sd, st, sg, @@ -17,11 +17,11 @@ - Improve task management and Unit Attention conditions handling using ACA in order to make them always reliable. Honoring NACA, QErr, TST, UA_INTLCK_CTRL bits. Requires deep modifications of the kernel. + + - Better handle of devices DMA restrictions. - Move linear searches to hash-table based. - - Redone some semaphores with completion interface. - - HIGHMEM cleanup. Looks like HIGHMEM usage doesn't worth the effort and performance hit, at least until VDISK handler doesn't use the page cache directly, so disable it for now, although the code looks ready. Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/include/scsi_tgt.h 2007-08-03 09:57:15 UTC (rev 155) @@ -678,6 +678,9 @@ * by scst_cmd_atomic(): it is true if the function called in the * atomic (non-sleeping) context. * + * !! If this function is implemented, scst_check_local_events() shall !! + * !! be called inside it just before the actual command's execution. !! + * * OPTIONAL, if not set, the commands will be sent directly to SCSI * device. */ @@ -2117,6 +2120,17 @@ */ void scst_process_active_cmd(struct scst_cmd *cmd, int context); +/* + * Checks if command can be executed (reservations, etc.) or there are local + * events, like pending UAs. Returns < 0 if command must be aborted, > 0 if + * there is an event and command should be immediately completed, or 0 + * otherwise. + * + * !! Dev handlers implementing exec() callback must call this function there !! + * !! just before the actual command's execution !! + */ +int scst_check_local_events(struct scst_cmd *cmd); + /* * Returns target driver's root entry in SCST's /proc hierarchy. * The driver can create own files/directoryes here, which should Modified: trunk/scst/src/Makefile =================================================================== --- trunk/scst/src/Makefile 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/Makefile 2007-08-03 09:57:15 UTC (rev 155) @@ -117,7 +117,7 @@ # If defined, allows SCST to use HIGHMEM. It's unclear, if it brings # something valuable, except performance hit in some cases, -# so let it be off. Untested. +# so let it be off. Untested and unsupported. #EXTRA_CFLAGS += -DSCST_HIGHMEM clean: Modified: trunk/scst/src/dev_handlers/scst_disk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_disk.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/dev_handlers/scst_disk.c 2007-08-03 09:57:15 UTC (rev 155) @@ -344,11 +344,19 @@ ********************************************************************/ int disk_exec(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED; + int res = SCST_EXEC_NOT_COMPLETED, rc; int opcode = cmd->cdb[0]; TRACE_ENTRY(); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_uncompl; + } + switch (opcode) { case WRITE_6: case WRITE_10: @@ -358,18 +366,24 @@ case READ_10: case READ_12: case READ_16: - res = SCST_EXEC_COMPLETED; - cmd->status = 0; - cmd->msg_status = 0; - cmd->host_status = DID_OK; - cmd->driver_status = 0; - cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - break; + goto out_compl; } +out: TRACE_EXIT_RES(res); return res; + +out_compl: + cmd->completed = 1; + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + +out_uncompl: + res = SCST_EXEC_COMPLETED; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + goto out; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_modisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_modisk.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/dev_handlers/scst_modisk.c 2007-08-03 09:57:15 UTC (rev 155) @@ -358,11 +358,19 @@ ********************************************************************/ int modisk_exec(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED; + int res = SCST_EXEC_NOT_COMPLETED, rc; int opcode = cmd->cdb[0]; TRACE_ENTRY(); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_uncompl; + } + switch (opcode) { case WRITE_6: case WRITE_10: @@ -372,18 +380,24 @@ case READ_10: case READ_12: case READ_16: - res = SCST_EXEC_COMPLETED; - cmd->status = 0; - cmd->msg_status = 0; - cmd->host_status = DID_OK; - cmd->driver_status = 0; - cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - break; + goto out_compl; } +out: TRACE_EXIT_RES(res); return res; + +out_compl: + cmd->completed = 1; + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + +out_uncompl: + res = SCST_EXEC_COMPLETED; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + goto out; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_tape.c =================================================================== --- trunk/scst/src/dev_handlers/scst_tape.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/dev_handlers/scst_tape.c 2007-08-03 09:57:15 UTC (rev 155) @@ -389,26 +389,40 @@ ********************************************************************/ int tape_exec(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED; + int res = SCST_EXEC_NOT_COMPLETED, rc; int opcode = cmd->cdb[0]; TRACE_ENTRY(); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_uncompl; + } + switch (opcode) { case WRITE_6: case READ_6: - res = SCST_EXEC_COMPLETED; - cmd->status = 0; - cmd->msg_status = 0; - cmd->host_status = DID_OK; - cmd->driver_status = 0; - cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - break; + goto out_compl; } +out: TRACE_EXIT_RES(res); return res; + +out_compl: + cmd->completed = 1; + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + +out_uncompl: + res = SCST_EXEC_COMPLETED; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + goto out; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_user.c =================================================================== --- trunk/scst/src/dev_handlers/scst_user.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/dev_handlers/scst_user.c 2007-08-03 09:57:15 UTC (rev 155) @@ -191,7 +191,7 @@ static struct kmem_cache *user_cmd_cachep; -static DEFINE_MUTEX(dev_user_mutex); +static DEFINE_MUTEX(dev_priv_mutex); static struct file_operations dev_user_fops = { .poll = dev_user_poll, @@ -204,6 +204,7 @@ static struct class *dev_user_sysfs_class; +static spinlock_t dev_list_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(dev_list); static spinlock_t cleanup_lock = SPIN_LOCK_UNLOCKED; @@ -1383,15 +1384,15 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; res = dev_user_check_reg(dev); if (res != 0) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } down_read(&dev->dev_rwsem); - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); reply = kzalloc(sizeof(*reply), GFP_KERNEL); if (reply == NULL) { @@ -1452,16 +1453,28 @@ TRACE_DBG("Found ready ucmd %p", u); list_del(&u->ready_cmd_list_entry); EXTRACHECKS_BUG_ON(u->state & UCMD_STATE_JAMMED_MASK); - if ((u->cmd != NULL) && - unlikely(test_bit(SCST_CMD_ABORTED, - &u->cmd->cmd_flags))) { - switch(u->state) { - case UCMD_STATE_PARSING: - case UCMD_STATE_BUF_ALLOCING: - case UCMD_STATE_EXECING: - TRACE_MGMT_DBG("Aborting ucmd %p", u); - dev_user_unjam_cmd(u, 0, NULL); - goto again; + if (u->cmd != NULL) { + if (u->state == UCMD_STATE_EXECING) { + int rc = scst_check_local_events(u->cmd); + if (unlikely(rc != 0)) { + if (rc > 0) { + u->cmd->completed = 1; + u->cmd->scst_cmd_done( + u->cmd, SCST_CMD_STATE_DEFAULT); + } else + dev_user_unjam_cmd(u, 0, NULL); + goto again; + } + } else if (unlikely(test_bit(SCST_CMD_ABORTED, + &u->cmd->cmd_flags))) { + switch(u->state) { + case UCMD_STATE_PARSING: + case UCMD_STATE_BUF_ALLOCING: + case UCMD_STATE_EXECING: + TRACE_MGMT_DBG("Aborting ucmd %p", u); + dev_user_unjam_cmd(u, 0, NULL); + goto again; + } } } u->state |= UCMD_STATE_SENT_MASK; @@ -1604,15 +1617,15 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; res = dev_user_check_reg(dev); if (res != 0) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } down_read(&dev->dev_rwsem); - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); res = copy_from_user(&ureply, (void*)arg, sizeof(ureply)); if (res < 0) @@ -1742,15 +1755,15 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; res = dev_user_check_reg(dev); if (res != 0) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } down_read(&dev->dev_rwsem); - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); spin_lock_irq(&dev->cmd_lists.cmd_list_lock); @@ -1828,7 +1841,8 @@ scst_set_cmd_error(ucmd->cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); TRACE_MGMT_DBG("EXEC: unjamming ucmd %p", ucmd); - ucmd->cmd->completed = 1; + if (!test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) + ucmd->cmd->completed = 1; ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT); if (flags != NULL) spin_lock_irqsave(&dev->cmd_lists.cmd_list_lock, *flags); @@ -2136,14 +2150,14 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + spin_lock(&dev_list_lock); list_for_each_entry(d, &dev_list, dev_list_entry) { if (strcmp(d->name, sdev->virt_name) == 0) { dev = d; break; } } - mutex_unlock(&dev_user_mutex); + spin_unlock(&dev_list_lock); if (dev == NULL) { PRINT_ERROR_PR("Device %s not found", sdev->virt_name); res = -EINVAL; @@ -2539,17 +2553,6 @@ strncpy(dev->name, dev_desc->name, sizeof(dev->name)-1); dev->name[sizeof(dev->name)-1] = '\0'; - mutex_lock(&dev_user_mutex); - - list_for_each_entry(d, &dev_list, dev_list_entry) { - if (strcmp(d->name, dev->name) == 0) { - PRINT_ERROR_PR("Device %s already exist", - dev->name); - res = -EEXIST; - goto out_free_unlock; - } - } - /* * We don't use clustered pool, since it implies pages reordering, * which isn't possible with user space supplied buffers. Although @@ -2558,7 +2561,7 @@ */ dev->pool = sgv_pool_create(dev->name, 0); if (dev->pool == NULL) - goto out_free_unlock; + goto out_put; sgv_pool_set_allocator(dev->pool, dev_user_alloc_pages, dev_user_free_sg_entries); @@ -2588,16 +2591,28 @@ TRACE_MEM("dev %p, name %s", dev, dev->name); + spin_lock(&dev_list_lock); + + list_for_each_entry(d, &dev_list, dev_list_entry) { + if (strcmp(d->name, dev->name) == 0) { + PRINT_ERROR_PR("Device %s already exist", + dev->name); + res = -EEXIST; + spin_unlock(&dev_list_lock); + goto out_free; + } + } + list_add_tail(&dev->dev_list_entry, &dev_list); - mutex_unlock(&dev_user_mutex); + spin_unlock(&dev_list_lock); if (res != 0) - goto out_free_pool; + goto out_del_free; res = scst_register_virtual_dev_driver(&dev->devtype); if (res < 0) - goto out_free_pool; + goto out_del_free; dev->virt_id = scst_register_virtual_device(&dev->devtype, dev->name); if (dev->virt_id < 0) { @@ -2605,15 +2620,15 @@ goto out_unreg_handler; } - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); if (file->private_data != NULL) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); PRINT_ERROR_PR("%s", "Device already registered"); res = -EINVAL; goto out_unreg_drv; } file->private_data = dev; - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); out: TRACE_EXIT_RES(res); @@ -2625,18 +2640,16 @@ out_unreg_handler: scst_unregister_virtual_dev_driver(&dev->devtype); -out_free_pool: - mutex_lock(&dev_user_mutex); +out_del_free: + spin_lock(&dev_list_lock); list_del(&dev->dev_list_entry); - mutex_unlock(&dev_user_mutex); + spin_unlock(&dev_list_lock); + +out_free: sgv_pool_destroy(dev->pool); kfree(dev); goto out_put; -out_free_unlock: - kfree(dev); - mutex_unlock(&dev_user_mutex); - out_put: module_put(THIS_MODULE); goto out; @@ -2696,15 +2709,15 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; res = dev_user_check_reg(dev); if (res != 0) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } down_read(&dev->dev_rwsem); - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); scst_suspend_activity(); res = __dev_user_set_opt(dev, opt); @@ -2725,15 +2738,15 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; res = dev_user_check_reg(dev); if (res != 0) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } down_read(&dev->dev_rwsem); - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); opt.parse_type = dev->parse_type; opt.on_free_cmd_type = dev->on_free_cmd_type; @@ -2777,16 +2790,20 @@ TRACE_ENTRY(); - mutex_lock(&dev_user_mutex); + mutex_lock(&dev_priv_mutex); dev = (struct scst_user_dev*)file->private_data; if (dev == NULL) { - mutex_unlock(&dev_user_mutex); + mutex_unlock(&dev_priv_mutex); goto out; } file->private_data = NULL; + + spin_lock(&dev_list_lock); list_del(&dev->dev_list_entry); - mutex_unlock(&dev_user_mutex); + spin_unlock(&dev_list_lock); + mutex_unlock(&dev_priv_mutex); + down_write(&dev->dev_rwsem); TRACE_DBG("Releasing dev %p", dev); Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-08-03 09:57:15 UTC (rev 155) @@ -636,6 +636,7 @@ static int vdisk_do_job(struct scst_cmd *cmd) { + int rc; uint64_t lba_start = 0; loff_t data_len = 0; uint8_t *cdb = cmd->cdb; @@ -650,17 +651,19 @@ TRACE_ENTRY(); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto done; + else + goto done_uncompl; + } + cmd->status = 0; cmd->msg_status = 0; cmd->host_status = DID_OK; cmd->driver_status = 0; - if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { - TRACE_MGMT_DBG("Flag ABORTED set for " - "cmd %p (tag %llu), skipping", cmd, cmd->tag); - goto done_uncompl; - } - d = scst_find_thr_data(cmd->tgt_dev); if (unlikely(d == NULL)) { thr = vdisk_init_thr_data(cmd->tgt_dev); Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/scst.c 2007-08-03 09:57:15 UTC (rev 155) @@ -1656,6 +1656,8 @@ EXPORT_SYMBOL(scst_alloc); EXPORT_SYMBOL(scst_free); +EXPORT_SYMBOL(scst_check_local_events); + /* Tgt_dev's threads local storage */ EXPORT_SYMBOL(scst_add_thr_data); EXPORT_SYMBOL(scst_del_all_thr_data); Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/scst_lib.c 2007-08-03 09:57:15 UTC (rev 155) @@ -2699,7 +2699,7 @@ #ifdef STRICT_SERIALIZING spin_lock_bh(&dev->dev_lock); - if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) + if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) goto out_unlock; if (dev->block_count > 0) { scst_dec_on_dev_cmd(cmd); @@ -2718,7 +2718,7 @@ repeat: if (unlikely(dev->block_count > 0)) { spin_lock_bh(&dev->dev_lock); - if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) + if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) goto out_unlock; barrier(); /* to reread block_count */ if (dev->block_count > 0) { @@ -3184,6 +3184,9 @@ { unsigned long flags; + if (!tm_dbg_flags.tm_dbg_active) + goto out; + spin_lock_irqsave(&scst_tm_dbg_lock, flags); if ((tm_dbg_state != TM_DBG_STATE_OFFLINE) || force) { TRACE_MGMT_DBG("%s: freeing %d delayed cmds", fn, @@ -3196,6 +3199,9 @@ TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn); } spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); + +out: + return; } int tm_dbg_is_release(void) Modified: trunk/scst/src/scst_mem.c =================================================================== --- trunk/scst/src/scst_mem.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/scst_mem.c 2007-08-03 09:57:15 UTC (rev 155) @@ -210,8 +210,9 @@ for (pg = 0; pg < pages; pg++) { void *rc; #ifdef DEBUG_OOM - if ((scst_random() % 10000) == 55) - void *rc = NULL; + if (((gfp_mask & __GFP_NOFAIL) == 0) && + ((scst_random() % 10000) == 55)) + rc = NULL; else #endif rc = alloc_fns->alloc_pages_fn(&sg[sg_count], gfp_mask, Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/scst_proc.c 2007-08-03 09:57:15 UTC (rev 155) @@ -1694,12 +1694,12 @@ goto out; } - seq_printf(seq, "%-20s%-35s%-35s%-15s\n", "Target name", "Initiator name", + seq_printf(seq, "%-20s %-35s %-35s %-15s\n", "Target name", "Initiator name", "Group name", "Command Count"); list_for_each_entry(acg, &scst_acg_list, scst_acg_list_entry) { list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) { - seq_printf(seq, "%-20s%-35s%-35s%-15d\n", + seq_printf(seq, "%-20s %-35s %-35s %-15d\n", sess->tgt->tgtt->name, sess->initiator_name, acg->acg_name, Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-07-31 14:21:46 UTC (rev 154) +++ trunk/scst/src/scst_targ.c 2007-08-03 09:57:15 UTC (rev 155) @@ -26,6 +26,7 @@ #include <asm/unistd.h> #include <asm/string.h> #include <linux/kthread.h> +#include <linux/delay.h> #include "scsi_tgt.h" #include "scst_priv.h" @@ -142,6 +143,11 @@ sBUG_ON(context != SCST_CONTEXT_DIRECT); scst_set_busy(cmd); cmd->state = SCST_CMD_STATE_XMIT_RESP; + /* Keep initiator away from too many BUSY commands */ + if (!in_interrupt() && !in_atomic()) + ssleep(2); + else + WARN_ON_ONCE(1); } else { unsigned long flags; spin_lock_irqsave(&scst_init_lock, flags); @@ -1270,7 +1276,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd) { - int res = SCST_EXEC_COMPLETED; + int res = SCST_EXEC_COMPLETED, rc; int dev_cnt = 0; int buffer_size; int i; @@ -1280,6 +1286,14 @@ TRACE_ENTRY(); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_done; + else + goto out_uncompl; + } + cmd->status = 0; cmd->msg_status = 0; cmd->host_status = DID_OK; @@ -1355,6 +1369,7 @@ out_done: cmd->completed = 1; +out_uncompl: /* Report the result */ scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); @@ -1388,16 +1403,7 @@ scst_block_dev_cmd(cmd, 1); - if (test_bit(SCST_TGT_DEV_UA_PENDING, &cmd->tgt_dev->tgt_dev_flags)) { - int rc = scst_set_pending_UA(cmd); - if (rc == 0) { - res = SCST_EXEC_COMPLETED; - cmd->completed = 1; - /* Report the result */ - scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); - goto out; - } - } + /* Check for local events will be done when cmd will be executed */ out: TRACE_EXIT_RES(res); @@ -1419,7 +1425,7 @@ static int scst_reserve_local(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED; + int res = SCST_EXEC_NOT_COMPLETED, rc; struct scst_device *dev; struct scst_tgt_dev *tgt_dev_tmp; @@ -1444,6 +1450,14 @@ scst_block_dev_cmd(cmd, 1); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_uncompl; + } + spin_lock_bh(&dev->dev_lock); if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { @@ -1468,20 +1482,42 @@ out: TRACE_EXIT_RES(res); return res; + +out_compl: + cmd->completed = 1; + +out_uncompl: + res = SCST_EXEC_COMPLETED; + /* Report the result */ + scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); + goto out; } static int scst_release_local(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED; + int res = SCST_EXEC_NOT_COMPLETED, rc; struct scst_tgt_dev *tgt_dev_tmp; struct scst_device *dev; TRACE_ENTRY(); + if (scst_cmd_atomic(cmd)) { + res = SCST_EXEC_NEED_THREAD; + goto out; + } + dev = cmd->dev; scst_block_dev_cmd(cmd, 1); + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_uncompl; + } + spin_lock_bh(&dev->dev_lock); /* @@ -1498,8 +1534,7 @@ } else { list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { clear_bit(SCST_TGT_DEV_RESERVED, &tgt_dev_tmp->tgt_dev_flags); } @@ -1508,27 +1543,35 @@ spin_unlock_bh(&dev->dev_lock); - if (res == SCST_EXEC_COMPLETED) { - cmd->completed = 1; - /* Report the result */ - scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); - } + if (res == SCST_EXEC_COMPLETED) + goto out_compl; +out: TRACE_EXIT_RES(res); return res; + +out_compl: + cmd->completed = 1; + +out_uncompl: + res = SCST_EXEC_COMPLETED; + /* Report the result */ + scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); + goto out; } -/* - * The result of cmd execution, if any, should be reported - * via scst_cmd_done_local() - */ -static int scst_pre_exec(struct scst_cmd *cmd) +int scst_check_local_events(struct scst_cmd *cmd) { - int res = SCST_EXEC_NOT_COMPLETED, rc; + int res, rc; struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; TRACE_ENTRY(); + if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { + TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); + goto out_uncomplete; + } + /* Reserve check before Unit Attention */ if (unlikely(test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags))) { if ((cmd->cdb[0] != INQUIRY) && (cmd->cdb[0] != REPORT_LUNS) && @@ -1538,8 +1581,7 @@ (cmd->cdb[0] != LOG_SENSE) && (cmd->cdb[0] != REQUEST_SENSE)) { scst_report_reserved(cmd); - res = SCST_EXEC_COMPLETED; - goto out; + goto out_complete; } } @@ -1565,7 +1607,7 @@ spin_unlock_bh(&dev->dev_lock); if (done) - goto out_done; + goto out_complete; } } @@ -1575,10 +1617,36 @@ { rc = scst_set_pending_UA(cmd); if (rc == 0) - goto out_done; + goto out_complete; } } + res = 0; + +out: + TRACE_EXIT_RES(res); + return res; + +out_complete: + res = 1; + goto out; + +out_uncomplete: + res = -1; + goto out; +} + +/* + * The result of cmd execution, if any, should be reported + * via scst_cmd_done_local() + */ +static int scst_pre_exec(struct scst_cmd *cmd) +{ + int res = SCST_EXEC_NOT_COMPLETED; + struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; + + TRACE_ENTRY(); + /* Check READ_ONLY device status */ if (tgt_dev->acg_dev->rd_only_flag && (cmd->cdb[0] == WRITE_6 || /* ToDo: full list of the modify cmds */ @@ -1595,6 +1663,7 @@ SCST_LOAD_SENSE(scst_sense_data_protect)); goto out_done; } + out: TRACE_EXIT_RES(res); return res; @@ -1667,11 +1736,6 @@ set_bit(SCST_CMD_EXECUTING, &cmd->cmd_flags); smp_mb__after_set_bit(); - if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { - TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd); - goto out_aborted; - } - rc = scst_pre_exec(cmd); /* !! At this point cmd, sess & tgt_dev can be already freed !! */ if (rc != SCST_EXEC_NOT_COMPLETED) { @@ -1721,6 +1785,14 @@ goto out_error; } + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) + goto out_compl; + else + goto out_aborted; + } + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) if (unlikely(scst_alloc_request(cmd) != 0)) { if (scst_cmd_atomic(cmd)) { @@ -1772,8 +1844,9 @@ out_error: scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + +out_compl: cmd->completed = 1; - cmd->state = SCST_CMD_STATE_DEV_DONE; rc = SCST_EXEC_COMPLETED; scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); goto out; @@ -1781,10 +1854,7 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) out_busy: scst_set_busy(cmd); - cmd->completed = 1; - cmd->state = SCST_CMD_STATE_DEV_DONE; - rc = SCST_EXEC_COMPLETED; - scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); + goto out_compl; goto out; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-08-08 09:53:11
|
Revision: 157 http://scst.svn.sourceforge.net/scst/?rev=157&view=rev Author: vlnb Date: 2007-08-08 02:52:23 -0700 (Wed, 08 Aug 2007) Log Message: ----------- - Docs updated - Minor fix Modified Paths: -------------- trunk/scst/README trunk/scst/ToDo trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-08-07 17:12:21 UTC (rev 156) +++ trunk/scst/README 2007-08-08 09:52:23 UTC (rev 157) @@ -361,8 +361,9 @@ - READ_ONLY - read only - - O_DIRECT - both read and write caching disabled (doesn't work - currently). + - O_DIRECT - both read and write caching disabled. This mode + isn't currently fully implemented, you should use user space + fileio_tgt program in O_DIRECT mode instead (see below). - NULLIO - in this mode no real IO will be done, but success will be returned. Intended to be used for performance measurements at the same @@ -499,28 +500,21 @@ User space program fileio_tgt uses interface of scst_user dev handler and allows to see how it work in various modes. Fileio_tgt provides mostly the same functionality as scst_vdisk handler with the only -exception that it supports O_DIRECT mode. This mode is basically the -same as BLOCKIO, but also supports files, so for some loads it could be -significantly faster, than regular FILEIO access, provided by -scst_vdisk. All the words about BLOCKIO from above apply to O_DIRECT as -well. While running fileio_tgt if you don't understand some its options, -use defaults for them, those values are the fastest. +exceptions that it has implemented O_DIRECT mode and doesn't support +BLOCKIO one. O_DIRECT mode is basically the same as BLOCKIO, but also +supports files, so for some loads it could be significantly faster, than +regular FILEIO access. All the words about BLOCKIO from above apply to +O_DIRECT as well. While running fileio_tgt if you don't understand some +its options, use defaults for them, those values are the fastest. Performance ----------- Before doing any performance measurements note that: -I. Currently maximum performance is possible only with real SCSI devices -or VDISK BLOCKIO mode with several simultaneously executed commands -(SCSI tagged queuing) or performance handlers. If you have enough CPU -power, VDISK FILEIO handler also could provide the same results, when -aggregate throughput is close to the aggregate throughput locally on the -target from the same disks. Also note, that currently IO subsystem in -Linux implemented on such way, so a VDISK FILEIO device over a single -file occupied entire formatted with some file system device (eg -/dev/hdc) could perform considerably better, than a VDISK FILEIO device -over /dev/hdc itself without the file system involved. +I. Performance results are very much dependent from your type of load, +so it is crucial that you choose access mode (FILEIO, BLOCKIO, +O_DIRECT, pass-through), which suits your needs the best. II. In order to get the maximum performance you should: @@ -529,9 +523,9 @@ - Disable in Makefile STRICT_SERIALIZING, EXTRACHECKS, TRACING, DEBUG*, SCST_STRICT_SECURITY, SCST_HIGHMEM -2. For Qlogic target driver: +2. For target drivers: - - Disable in Makefile EXTRACHECKS, TRACING, DEBUG_TGT, DEBUG_WORK_IN_THREAD + - Disable in Makefiles EXTRACHECKS, TRACING, DEBUG* 3. For device handlers, including VDISK: @@ -554,13 +548,40 @@ - The default kernel read-ahead and queuing settings are optimized for locally attached disks, therefore they are not optimal if they - attached remotely (our case), which sometimes could lead to - unexpectedly low throughput. You should increase read-ahead size - (/sys/block/device/queue/read_ahead_kb) to at least 256Kb or even - more on all initiators and the target. Also experiment with other - parameters in /sys/block/device directory, they also affect the - performance. If you find the best values, please share them with us. + attached remotely (SCSI target case), which sometimes could lead to + unexpectedly low throughput. You should increase read-ahead size to at + least 512KB or even more on all initiators and the target. + + You should also limit on all initiators maximum amount of sectors per + SCSI command. To do it on Linux initiators, run: + + echo “64” > /sys/block/sdX/queue/max_sectors_kb + where specify instead of X your imported from target device letter, + like 'b', i.e. sdb. + + To increase read-ahead size on Linux, run: + + blockdev --setra N /dev/sdX + + where N is a read-ahead number in 512-byte sectors and X is a device + letter like above. + + Note: you need to set read-ahead setting for device sdX again after + you changed the maximum amount of sectors per SCSI command for that + device. + + - You may need to increase amount of requests that OS on initiator + sends to the target device. To do it on Linux initiators, run + + echo “512” > /sys/block/sdX/queue/nr_requests + + where X is a device letter like above. + + You may also experiment with other parameters in /sys/block/sdX + directory, they also affect performance. If you find the best values, + please share them with us. + - Use on the target deadline IO scheduler with read_expire and write_expire increased on all exported devices to 5000 and 20000 correspondingly. @@ -571,41 +592,30 @@ 5. For hardware. - Make sure that your target hardware (e.g. target FC card) and underlaying - SCSI hardware (e.g. SCSI card to which your disks connected) stay on - different PCI buses. They will have to work in parallel, so it - will be better if they don't race for the bus. The problem is not - only in the bandwidth, which they have to share, but also in the - interaction between the cards during that competition. We have told - that in some cases it could lead to 5-10 times less performance, than + IO hardware (e.g. IO card, like SATA, SCSI or RAID to which your + disks connected) stay on different PCI buses. They have to work in + parallel, so it will be better if they don't compete for the bus. The + problem is not only in the bandwidth, which they have to share, but + also in the interaction between cards during that competition. In + some cases it could lead up to 5-10 times less performance, than expected. IMPORTANT: If you use on initiator some versions of Windows (at least W2K) ========= you can't get good write performance for VDISK FILEIO devices with default 512 bytes block sizes. You could get about 10% of the - expected one. This is because of "unusual" write access - pattern, with which Windows'es write data and which is - (simplifying) incompatible with how Linux page cache works, - so for each write the corresponding block must be read first. - With 4096 bytes block sizes for VDISK devices the write - performance will be as expected. Actually, any system on - initiator, not only Windows, will benefit from block size + expected one. This is because of partition alignment, which + is (simplifying) incompatible with how Linux page cache + works, so for each write the corresponding block must be read + first. Use 4096 bytes block sizes for VDISK devices and you + will have the expected write performance. Actually, any OS on + initiators, not only Windows, will benefit from block size max(PAGE_SIZE, BLOCK_SIZE_ON_UNDERLYING_FS), where PAGE_SIZE - is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size on - the underlying FS, on which the device file located, or 0, if - a device node is used. Both values are on the target. + is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size + on the underlying FS, on which the device file located, or 0, + if a device node is used. Both values are from the target. + See also important notes about setting block sizes >512 bytes + for VDISK FILEIO devices above. -Just for reference: we had with 0.9.2 and "old" Qlogic driver on 2.4.2x -kernel, where we did careful performance study, aggregate throughput -about 390 Mb/sec from 2 qla2300 cards sitting on different 64-bit PCI -buses and working simultaneously for two different initiators with -several simultaneously working load programs on each. From one card - -about 190 Mb/sec. We used tape_perf handler, so there was no influence -from underlying SCSI hardware, i.e. we measured only SCST/FC overhead. -The target computer configuration was not very modern for the moment: -something like 2x1GHz Intel P3 Xeon CPUs. You can estimate the -memory/PCI speed from that. CPU load was ~5%, there were ~30K IRQ/sec -and no additional SCST related context switches. - Credits ------- Modified: trunk/scst/ToDo =================================================================== --- trunk/scst/ToDo 2007-08-07 17:12:21 UTC (rev 156) +++ trunk/scst/ToDo 2007-08-08 09:52:23 UTC (rev 157) @@ -8,7 +8,7 @@ the page cache (in order to avoid data copy between it and internal buffers). Requires modifications of the kernel. - - O_DIRECT mode doesn't work for FILEIO (oops'es somewhere in the kernel) + - Fix in-kernel O_DIRECT mode. - Close integration with Linux initiator SCSI mil-level, including queue types (simple, ordered, etc.) and local initiators (sd, st, sg, Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-08-07 17:12:21 UTC (rev 156) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-08-08 09:52:23 UTC (rev 157) @@ -2549,7 +2549,8 @@ TRACE_DBG("%s", "O_DIRECT"); #else PRINT_INFO_PR("%s flag doesn't currently" - " work, ignoring it", "O_DIRECT"); + " work, ignoring it, use fileio_tgt " + "in O_DIRECT mode instead", "O_DIRECT"); #endif } else if (!strncmp("NULLIO", p, 6)) { p += 6; Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-08-07 17:12:21 UTC (rev 156) +++ trunk/scst/src/scst_targ.c 2007-08-08 09:52:23 UTC (rev 157) @@ -2447,9 +2447,16 @@ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { if (test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags)) { - TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p " - "(tag %llu), returning TASK ABORTED", cmd, cmd->tag); - scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED); + if (cmd->completed) { + /* It's completed and it's OK to return its result */ + clear_bit(SCST_CMD_ABORTED, &cmd->cmd_flags); + clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); + } else { + TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd " + "%p (tag %llu), returning TASK ABORTED", + cmd, cmd->tag); + scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-08-14 16:55:03
|
Revision: 159 http://scst.svn.sourceforge.net/scst/?rev=159&view=rev Author: vlnb Date: 2007-08-14 09:54:54 -0700 (Tue, 14 Aug 2007) Log Message: ----------- - Call of pre_unreg_sess() moved to scst_mgmt_thread, because of scst_mutex deadlock with scst_user's pre_unreg_sess() handler - scst_check_local_events() cleanups - In scst_user notification about aborted commands added, user space interface changed - Other minor fixes and cleanups Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/include/scst_user.h trunk/scst/src/Makefile trunk/scst/src/dev_handlers/scst_disk.c trunk/scst/src/dev_handlers/scst_modisk.c trunk/scst/src/dev_handlers/scst_tape.c trunk/scst/src/dev_handlers/scst_user.c trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/include/scsi_tgt.h 2007-08-14 16:54:54 UTC (rev 159) @@ -285,6 +285,19 @@ /* Set if session is initialized and ready */ #define SCST_SESS_IPH_READY 3 +/************************************************************* + ** Session shutdown phases + *************************************************************/ + +/* Set if session is initialized and ready */ +#define SCST_SESS_SPH_READY 0 + +/* Set if session is on calling pre_unreg_sess() phase */ +#define SCST_SESS_SPH_PRE_UNREG 1 + +/* Set if session is shutting down */ +#define SCST_SESS_SPH_SHUTDOWN 2 + /************************************************************* ** Cmd's async (atomic) flags *************************************************************/ @@ -833,20 +846,27 @@ struct scst_session { - /* Initialization phase, one of SCST_SESS_IPH_* constants */ + /* + * Initialization phase, one of SCST_SESS_IPH_* constants, protected by + * sess_list_lock + */ int init_phase; atomic_t refcnt; /* get/put counter */ - /************************************************************* - ** Session's flags. Serialized by scst_mgmt_lock - *************************************************************/ + /**************************************************************/ - /* Set if the session is shutting down */ - unsigned int shutting_down:1; + /* Alive commands for this session. ToDo: make it part of the common IO flow control */ + atomic_t sess_cmd_count; - /**************************************************************/ + spinlock_t sess_list_lock; /* protects search_cmd_list, etc */ + /* + * List of cmds in this session. Used to find a cmd in the + * session. Protected by sess_list_lock. + */ + struct list_head search_cmd_list; + /* * Hash list of tgt_dev's for this session, protected by scst_mutex * and suspended activity @@ -859,22 +879,11 @@ /* List entry for the sessions list inside ACG */ struct list_head acg_sess_list_entry; + struct scst_tgt *tgt; /* corresponding target */ + /* Used for storage of target driver private stuff */ void *tgt_priv; - /* Alive commands for this session. ToDo: make it part of common IO flow control */ - atomic_t sess_cmd_count; - - spinlock_t sess_list_lock; /* protects search_cmd_list, etc */ - - /* - * List of cmds in this session. Used to find a cmd in the - * session. Protected by sess_list_lock. - */ - struct list_head search_cmd_list; - - struct scst_tgt *tgt; /* corresponding target */ - /* Name of attached initiator */ const char *initiator_name; @@ -882,8 +891,11 @@ struct list_head sess_list_entry; /* List entry for the list that keeps session, waiting for the init */ - struct list_head sess_mgmt_list_entry; + struct list_head sess_init_list_entry; + /* List entry for the list that keeps session, waiting for the shutdown */ + struct list_head sess_shut_list_entry; + /* * Lists of deffered during session initialization commands. * Protected by sess_list_lock. @@ -891,12 +903,16 @@ struct list_head init_deferred_cmd_list; struct list_head init_deferred_mcmd_list; + /* + * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected. + * Async. relating to init_phase, must be a separate variable, because + * session could be unregistered before async. registration is finished. + */ + unsigned long shut_phase; + /* Used if scst_unregister_session() called in wait mode */ struct completion *shutdown_compl; - /* Used to push some unregister_session() works out of IRQ */ - struct work_struct unreg_work; - /* * Functions and data for user callbacks from scst_register_session() * and scst_unregister_session() Modified: trunk/scst/include/scst_user.h =================================================================== --- trunk/scst/include/scst_user.h 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/include/scst_user.h 2007-08-14 16:54:54 UTC (rev 159) @@ -23,7 +23,7 @@ #define DEV_USER_NAME "scst_user" #define DEV_USER_PATH "/dev/" -#define DEV_USER_VERSION 96 +#define DEV_USER_VERSION 961 /* * Chosen so sizeof(scst_user_sess) <= sizeof(scst_user_scsi_cmd_exec) @@ -95,7 +95,7 @@ struct scst_user_dev_desc { - uint8_t version; + uint32_t version; uint8_t type; struct scst_user_opt opt; uint32_t block_size; @@ -168,6 +168,7 @@ aligned_u64 pbuf; int32_t resp_data_len; uint8_t buffer_cached; + uint8_t aborted; uint8_t status; }; Modified: trunk/scst/src/Makefile =================================================================== --- trunk/scst/src/Makefile 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/Makefile 2007-08-14 16:54:54 UTC (rev 159) @@ -81,6 +81,12 @@ install -m 644 Module.symvers $(INSTALL_DIR_H) endif -depmod -a $(KVER) + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + @echo "!! Now don't forget to rebuild and reinstall all your !!" + @echo "!! target drivers, custom dev handlers and necessary user !!" + @echo "!! space applications. Otherwise, because of the versions !!" + @echo "!! mismatch, you could have many problems and crashes! !!" + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" uninstall: cd $(DEV_HANDLERS_DIR) && $(MAKE) $@ Modified: trunk/scst/src/dev_handlers/scst_disk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_disk.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/dev_handlers/scst_disk.c 2007-08-14 16:54:54 UTC (rev 159) @@ -350,13 +350,14 @@ TRACE_ENTRY(); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + switch (opcode) { case WRITE_6: case WRITE_10: @@ -366,24 +367,16 @@ case READ_10: case READ_12: case READ_16: - goto out_compl; + cmd->completed = 1; + break; } -out: - TRACE_EXIT_RES(res); - return res; - -out_compl: - cmd->completed = 1; - cmd->status = 0; - cmd->msg_status = 0; - cmd->host_status = DID_OK; - cmd->driver_status = 0; - -out_uncompl: +out_done: res = SCST_EXEC_COMPLETED; cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - goto out; + + TRACE_EXIT_RES(res); + return res; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_modisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_modisk.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/dev_handlers/scst_modisk.c 2007-08-14 16:54:54 UTC (rev 159) @@ -364,13 +364,14 @@ TRACE_ENTRY(); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + switch (opcode) { case WRITE_6: case WRITE_10: @@ -380,24 +381,16 @@ case READ_10: case READ_12: case READ_16: - goto out_compl; + cmd->completed = 1; + break; } -out: - TRACE_EXIT_RES(res); - return res; - -out_compl: - cmd->completed = 1; - cmd->status = 0; - cmd->msg_status = 0; - cmd->host_status = DID_OK; - cmd->driver_status = 0; - -out_uncompl: +out_done: res = SCST_EXEC_COMPLETED; cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - goto out; + + TRACE_EXIT_RES(res); + return res; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_tape.c =================================================================== --- trunk/scst/src/dev_handlers/scst_tape.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/dev_handlers/scst_tape.c 2007-08-14 16:54:54 UTC (rev 159) @@ -395,34 +395,27 @@ TRACE_ENTRY(); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; - switch (opcode) { - case WRITE_6: - case READ_6: - goto out_compl; - } - -out: - TRACE_EXIT_RES(res); - return res; - -out_compl: - cmd->completed = 1; cmd->status = 0; cmd->msg_status = 0; cmd->host_status = DID_OK; cmd->driver_status = 0; -out_uncompl: + switch (opcode) { + case WRITE_6: + case READ_6: + cmd->completed = 1; + break; + } + +out_done: res = SCST_EXEC_COMPLETED; cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); - goto out; + + TRACE_EXIT_RES(res); + return res; } MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); Modified: trunk/scst/src/dev_handlers/scst_user.c =================================================================== --- trunk/scst/src/dev_handlers/scst_user.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/dev_handlers/scst_user.c 2007-08-14 16:54:54 UTC (rev 159) @@ -124,6 +124,7 @@ unsigned int buf_dirty:1; unsigned int background_exec:1; unsigned int internal_reset_tm:1; + unsigned int aborted:1; struct dev_user_cmd *buf_ucmd; @@ -842,6 +843,7 @@ ucmd->user_cmd.on_free_cmd.pbuf = ucmd->ubuff; ucmd->user_cmd.on_free_cmd.resp_data_len = cmd->resp_data_len; ucmd->user_cmd.on_free_cmd.buffer_cached = ucmd->buff_cached; + ucmd->user_cmd.on_free_cmd.aborted = ucmd->aborted; ucmd->user_cmd.on_free_cmd.status = cmd->status; ucmd->state = UCMD_STATE_ON_FREEING; @@ -1251,6 +1253,7 @@ out_compl: cmd->completed = 1; cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); + /* !! At this point cmd can be already freed !! */ out: TRACE_EXIT_RES(res); @@ -1445,9 +1448,10 @@ struct dev_user_cmd *__dev_user_get_next_cmd(struct list_head *cmd_list) { - struct dev_user_cmd *u = NULL; + struct dev_user_cmd *u; again: + u = NULL; if (!list_empty(cmd_list)) { u = list_entry(cmd_list->next, typeof(*u), ready_cmd_list_entry); TRACE_DBG("Found ready ucmd %p", u); @@ -1457,12 +1461,17 @@ if (u->state == UCMD_STATE_EXECING) { int rc = scst_check_local_events(u->cmd); if (unlikely(rc != 0)) { - if (rc > 0) { - u->cmd->completed = 1; - u->cmd->scst_cmd_done( - u->cmd, SCST_CMD_STATE_DEFAULT); - } else - dev_user_unjam_cmd(u, 0, NULL); + struct scst_user_dev *dev = u->dev; + spin_unlock_irq( + &dev->cmd_lists.cmd_list_lock); + u->cmd->scst_cmd_done(u->cmd, + SCST_CMD_STATE_DEFAULT); + /* + * !! At this point cmd & u can be !! + * !! already freed !! + */ + spin_lock_irq( + &dev->cmd_lists.cmd_list_lock); goto again; } } else if (unlikely(test_bit(SCST_CMD_ABORTED, @@ -1470,10 +1479,11 @@ switch(u->state) { case UCMD_STATE_PARSING: case UCMD_STATE_BUF_ALLOCING: - case UCMD_STATE_EXECING: TRACE_MGMT_DBG("Aborting ucmd %p", u); dev_user_unjam_cmd(u, 0, NULL); goto again; + case UCMD_STATE_EXECING: + EXTRACHECKS_BUG_ON(1); } } } @@ -1819,11 +1829,15 @@ switch(state) { case UCMD_STATE_PARSING: case UCMD_STATE_BUF_ALLOCING: - if (busy) - scst_set_busy(ucmd->cmd); - else - scst_set_cmd_error(ucmd->cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) + ucmd->aborted = 1; + else { + if (busy) + scst_set_busy(ucmd->cmd); + else + scst_set_cmd_error(ucmd->cmd, + SCST_LOAD_SENSE(scst_sense_hardw_error)); + } TRACE_MGMT_DBG("Adding ucmd %p to active list", ucmd); list_add(&ucmd->cmd->cmd_list_entry, &ucmd->cmd->cmd_lists->active_cmd_list); @@ -1835,15 +1849,23 @@ spin_unlock_irqrestore(&dev->cmd_lists.cmd_list_lock, *flags); else spin_unlock_irq(&dev->cmd_lists.cmd_list_lock); - if (busy) - scst_set_busy(ucmd->cmd); - else - scst_set_cmd_error(ucmd->cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + TRACE_MGMT_DBG("EXEC: unjamming ucmd %p", ucmd); - if (!test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) + + if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) + ucmd->aborted = 1; + else { ucmd->cmd->completed = 1; + if (busy) + scst_set_busy(ucmd->cmd); + else + scst_set_cmd_error(ucmd->cmd, + SCST_LOAD_SENSE(scst_sense_hardw_error)); + } + ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT); + /* !! At this point cmd ans ucmd can be already freed !! */ + if (flags != NULL) spin_lock_irqsave(&dev->cmd_lists.cmd_list_lock, *flags); else Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-08-14 16:54:54 UTC (rev 159) @@ -652,12 +652,8 @@ TRACE_ENTRY(); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto done; - else - goto done_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; cmd->status = 0; cmd->msg_status = 0; @@ -669,7 +665,7 @@ thr = vdisk_init_thr_data(cmd->tgt_dev); if (thr == NULL) { scst_set_busy(cmd); - goto done; + goto out_compl; } scst_thr_data_get(&thr->hdr); } else @@ -734,7 +730,7 @@ (uint64_t)virt_dev->file_size, (uint64_t)data_len); scst_set_cmd_error(cmd, SCST_LOAD_SENSE( scst_sense_block_out_range_error)); - goto done; + goto out_compl; } switch (opcode) { @@ -780,7 +776,7 @@ (uint64_t)data_len); do_fsync = 1; if (vdisk_fsync(thr, 0, 0, cmd) != 0) - goto done; + goto out_compl; } if (virt_dev->blockio) { blockio_exec_rw(cmd, thr, lba_start, 1); @@ -815,7 +811,7 @@ (uint64_t)data_len); do_fsync = 1; if (vdisk_fsync(thr, 0, 0, cmd) != 0) - goto done; + goto out_compl; } /* ToDo: BLOCKIO VERIFY */ vdisk_exec_write(cmd, thr, loff); @@ -903,10 +899,10 @@ SCST_LOAD_SENSE(scst_sense_invalid_opcode)); } -done: +out_compl: cmd->completed = 1; -done_uncompl: +out_done: cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT); out: Modified: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/scst.c 2007-08-14 16:54:54 UTC (rev 159) @@ -52,7 +52,14 @@ not be supported. #endif -/* All targets, devices and dev_types management is done under this mutex */ +/* + * All targets, devices and dev_types management is done under this mutex. + * + * It must NOT be used in any works (schedule_work(), etc.), because + * otherwise a deadlock (double lock, actually) is possible, e.g., with + * scst_user detach_tgt(), which is called under scst_mutex and calls + * flush_scheduled_work(). + */ DEFINE_MUTEX(scst_mutex); LIST_HEAD(scst_template_list); @@ -109,7 +116,8 @@ DECLARE_WAIT_QUEUE_HEAD(scst_mgmt_waitQ); spinlock_t scst_mgmt_lock = SPIN_LOCK_UNLOCKED; -LIST_HEAD(scst_sess_mgmt_list); +LIST_HEAD(scst_sess_init_list); +LIST_HEAD(scst_sess_shut_list); DECLARE_WAIT_QUEUE_HEAD(scst_dev_cmd_waitQ); @@ -369,7 +377,7 @@ mutex_lock(&scst_mutex); list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { - sBUG_ON(!sess->shutting_down); + sBUG_ON(sess->shut_phase == SCST_SESS_SPH_READY); } mutex_unlock(&scst_mutex); Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/scst_lib.c 2007-08-14 16:54:54 UTC (rev 159) @@ -1048,6 +1048,7 @@ #endif sess->init_phase = SCST_SESS_IPH_INITING; + sess->shut_phase = SCST_SESS_SPH_READY; atomic_set(&sess->refcnt, 0); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = @@ -1137,8 +1138,8 @@ TRACE_ENTRY(); spin_lock_irqsave(&scst_mgmt_lock, flags); - TRACE_DBG("Adding sess %p to scst_sess_mgmt_list", sess); - list_add_tail(&sess->sess_mgmt_list_entry, &scst_sess_mgmt_list); + TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess); + list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list); spin_unlock_irqrestore(&scst_mgmt_lock, flags); wake_up(&scst_mgmt_waitQ); Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/scst_priv.h 2007-08-14 16:54:54 UTC (rev 159) @@ -198,7 +198,8 @@ extern wait_queue_head_t scst_mgmt_waitQ; extern spinlock_t scst_mgmt_lock; -extern struct list_head scst_sess_mgmt_list; +extern struct list_head scst_sess_init_list; +extern struct list_head scst_sess_shut_list; struct scst_cmd_thread_t { struct task_struct *cmd_thread; Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-08-10 08:40:54 UTC (rev 158) +++ trunk/scst/src/scst_targ.c 2007-08-14 16:54:54 UTC (rev 159) @@ -61,7 +61,7 @@ TRACE_ENTRY(); #ifdef EXTRACHECKS - if (unlikely(sess->shutting_down)) { + if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) { PRINT_ERROR_PR("%s", "New cmd while shutting down the session"); sBUG(); } @@ -145,7 +145,7 @@ cmd->state = SCST_CMD_STATE_XMIT_RESP; /* Keep initiator away from too many BUSY commands */ if (!in_interrupt() && !in_atomic()) - ssleep(2); + msleep(50); else WARN_ON_ONCE(1); } else { @@ -1287,12 +1287,8 @@ TRACE_ENTRY(); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_done; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; cmd->status = 0; cmd->msg_status = 0; @@ -1366,10 +1362,10 @@ if (dev_cnt < cmd->resp_data_len) scst_set_resp_data_len(cmd, dev_cnt); -out_done: +out_compl: cmd->completed = 1; -out_uncompl: +out_done: /* Report the result */ scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); @@ -1382,12 +1378,12 @@ out_err: scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); - goto out_done; + goto out_compl; out_put_hw_err: scst_put_buf(cmd, buffer); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); - goto out_done; + goto out_compl; } static int scst_pre_select(struct scst_cmd *cmd) @@ -1451,12 +1447,8 @@ scst_block_dev_cmd(cmd, 1); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; spin_lock_bh(&dev->dev_lock); @@ -1483,10 +1475,7 @@ TRACE_EXIT_RES(res); return res; -out_compl: - cmd->completed = 1; - -out_uncompl: +out_done: res = SCST_EXEC_COMPLETED; /* Report the result */ scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); @@ -1511,12 +1500,8 @@ scst_block_dev_cmd(cmd, 1); rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_uncompl; - } + if (unlikely(rc != 0)) + goto out_done; spin_lock_bh(&dev->dev_lock); @@ -1544,16 +1529,13 @@ spin_unlock_bh(&dev->dev_lock); if (res == SCST_EXEC_COMPLETED) - goto out_compl; + goto out_done; out: TRACE_EXIT_RES(res); return res; -out_compl: - cmd->completed = 1; - -out_uncompl: +out_done: res = SCST_EXEC_COMPLETED; /* Report the result */ scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); @@ -1629,6 +1611,7 @@ out_complete: res = 1; + cmd->completed = 1; goto out; out_uncomplete: @@ -1786,12 +1769,8 @@ } rc = scst_check_local_events(cmd); - if (unlikely(rc != 0)) { - if (rc > 0) - goto out_compl; - else - goto out_aborted; - } + if (unlikely(rc != 0)) + goto out_done; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) if (unlikely(scst_alloc_request(cmd) != 0)) { @@ -1845,20 +1824,14 @@ out_error: scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); -out_compl: - cmd->completed = 1; - rc = SCST_EXEC_COMPLETED; - scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); - goto out; - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) out_busy: scst_set_busy(cmd); - goto out_compl; - goto out; + cmd->completed = 1; + /* go through */ #endif -out_aborted: +out_done: rc = SCST_EXEC_COMPLETED; /* Report the result. The cmd is not completed */ scst_cmd_done_local(cmd, SCST_CMD_STATE_DEFAULT); @@ -4052,7 +4025,7 @@ atomic_inc(&sess->sess_cmd_count); #ifdef EXTRACHECKS - if (unlikely(sess->shutting_down)) { + if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) { PRINT_ERROR_PR("%s", "New mgmt cmd while shutting down the session"); sBUG(); @@ -4346,9 +4319,9 @@ sess->reg_sess_data = data; sess->init_result_fn = result_fn; spin_lock_irqsave(&scst_mgmt_lock, flags); - TRACE_DBG("Adding sess %p to scst_sess_mgmt_list", sess); - list_add_tail(&sess->sess_mgmt_list_entry, - &scst_sess_mgmt_list); + TRACE_DBG("Adding sess %p to scst_sess_init_list", sess); + list_add_tail(&sess->sess_init_list_entry, + &scst_sess_init_list); spin_unlock_irqrestore(&scst_mgmt_lock, flags); wake_up(&scst_mgmt_waitQ); } else { @@ -4367,47 +4340,6 @@ goto out; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void scst_unreg_work_fn(void *p) -#else -static void scst_unreg_work_fn(struct work_struct *work) -#endif -{ - int i; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct scst_session *sess = (struct scst_session*)p; -#else - struct scst_session *sess = container_of(work, struct scst_session, - unreg_work); -#endif - struct scst_tgt_dev *tgt_dev; - - TRACE_ENTRY(); - - mutex_lock(&scst_mutex); - for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { - struct list_head *sess_tgt_dev_list_head = - &sess->sess_tgt_dev_list_hash[i]; - list_for_each_entry(tgt_dev, sess_tgt_dev_list_head, - sess_tgt_dev_list_entry) { - struct scst_dev_type *handler = tgt_dev->dev->handler; - if (handler && handler->pre_unreg_sess) { - TRACE_DBG("Calling dev handler's pre_unreg_sess(%p)", - tgt_dev); - handler->pre_unreg_sess(tgt_dev); - TRACE_DBG("%s", "Dev handler's pre_unreg_sess() " - "returned"); - } - } - } - mutex_unlock(&scst_mutex); - - scst_sess_put(sess); - - TRACE_EXIT(); - return; -} - /* * Must not been called in parallel with scst_rx_cmd() or * scst_rx_mgmt_fn_*() for the same sess @@ -4429,9 +4361,10 @@ pc = &c; #endif + sess->shut_phase = SCST_SESS_SPH_PRE_UNREG; + spin_lock_irqsave(&scst_mgmt_lock, flags); - sess->shutting_down = 1; sess->unreg_done_fn = unreg_done_fn; if (wait) { sess->shutdown_compl = pc; @@ -4446,14 +4379,8 @@ tm_dbg_task_mgmt("UNREGISTER SESSION", 1); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&sess->unreg_work, scst_unreg_work_fn, sess); -#else - INIT_WORK(&sess->unreg_work, scst_unreg_work_fn); -#endif + scst_sess_put(sess); - schedule_work(&sess->unreg_work); - if (wait) { TRACE_DBG("Waiting for session %p to complete", sess); wait_for_completion(pc); @@ -4467,9 +4394,47 @@ return; } +static void scst_pre_unreg_sess(struct scst_session *sess) +{ + int i; + struct scst_tgt_dev *tgt_dev; + unsigned long flags; + + TRACE_ENTRY(); + + mutex_lock(&scst_mutex); + for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { + struct list_head *sess_tgt_dev_list_head = + &sess->sess_tgt_dev_list_hash[i]; + list_for_each_entry(tgt_dev, sess_tgt_dev_list_head, + sess_tgt_dev_list_entry) { + struct scst_dev_type *handler = tgt_dev->dev->handler; + if (handler && handler->pre_unreg_sess) { + TRACE_DBG("Calling dev handler's pre_unreg_sess(%p)", + tgt_dev); + handler->pre_unreg_sess(tgt_dev); + TRACE_DBG("%s", "Dev handler's pre_unreg_sess() " + "returned"); + } + } + } + mutex_unlock(&scst_mutex); + + sess->shut_phase = SCST_SESS_SPH_SHUTDOWN; + + spin_lock_irqsave(&scst_mgmt_lock, flags); + TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess); + list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list); + spin_unlock_irqrestore(&scst_mgmt_lock, flags); + + TRACE_EXIT(); + return; +} + static inline int test_mgmt_list(void) { - int res = !list_empty(&scst_sess_mgmt_list) || + int res = !list_empty(&scst_sess_init_list) || + !list_empty(&scst_sess_shut_list) || unlikely(kthread_should_stop()); return res; } @@ -4500,36 +4465,64 @@ set_current_state(TASK_RUNNING); remove_wait_queue(&scst_mgmt_waitQ, &wait); } -restart: - list_for_each_entry(sess, &scst_sess_mgmt_list, - sess_mgmt_list_entry) - { - TRACE_DBG("Removing sess %p from scst_sess_mgmt_list", + + while (!list_empty(&scst_sess_init_list)) { + sess = list_entry(scst_sess_init_list.next, + typeof(*sess), sess_init_list_entry); + TRACE_DBG("Removing sess %p from scst_sess_init_list", sess); - list_del(&sess->sess_mgmt_list_entry); + list_del(&sess->sess_init_list_entry); spin_unlock_irq(&scst_mgmt_lock); - if (sess->init_phase == SCST_SESS_IPH_INITING) { + + if (sess->init_phase == SCST_SESS_IPH_INITING) scst_init_session(sess); - } else if (sess->shutting_down) { + else { + PRINT_ERROR_PR("session %p is in " + "scst_sess_init_list, but in unknown " + "init phase %x", sess, + sess->init_phase); + sBUG(); + } + + spin_lock_irq(&scst_mgmt_lock); + } + + while (!list_empty(&scst_sess_shut_list)) { + sess = list_entry(scst_sess_shut_list.next, + typeof(*sess), sess_shut_list_entry); + TRACE_DBG("Removing sess %p from scst_sess_shut_list", + sess); + list_del(&sess->sess_shut_list_entry); + spin_unlock_irq(&scst_mgmt_lock); + + switch(sess->shut_phase) { + case SCST_SESS_SPH_PRE_UNREG: + scst_pre_unreg_sess(sess); + break; + case SCST_SESS_SPH_SHUTDOWN: sBUG_ON(atomic_read(&sess->refcnt) != 0); scst_free_session_callback(sess); - } else { + break; + default: PRINT_ERROR_PR("session %p is in " - "scst_sess_mgmt_list, but in unknown " - "phase %x", sess, sess->init_phase); + "scst_sess_shut_list, but in unknown " + "shut phase %lx", sess, + sess->shut_phase); sBUG(); + break; } + spin_lock_irq(&scst_mgmt_lock); - goto restart; } } spin_unlock_irq(&scst_mgmt_lock); /* * If kthread_should_stop() is true, we are guaranteed to be - * on the module unload, so scst_sess_mgmt_list must be empty. + * on the module unload, so both lists must be empty. */ - sBUG_ON(!list_empty(&scst_sess_mgmt_list)); + sBUG_ON(!list_empty(&scst_sess_init_list)); + sBUG_ON(!list_empty(&scst_sess_shut_list)); TRACE_EXIT(); return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-08-16 09:04:08
|
Revision: 164 http://scst.svn.sourceforge.net/scst/?rev=164&view=rev Author: vlnb Date: 2007-08-16 02:04:05 -0700 (Thu, 16 Aug 2007) Log Message: ----------- scsi_tgt.ko renamed to scst.ko Modified Paths: -------------- trunk/scst/README trunk/scst/src/Makefile trunk/scst/src/dev_handlers/Makefile Added Paths: ----------- trunk/scst/src/scst_main.c Removed Paths: ------------- trunk/scst/src/scst.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-08-15 09:59:46 UTC (rev 163) +++ trunk/scst/README 2007-08-16 09:04:05 UTC (rev 164) @@ -70,7 +70,7 @@ Then you can load any module by typing 'modprobe module_name'. The names are: - - scsi_tgt - SCST itself + - scst - SCST itself - scst_disk - device handler for disks (type 0) - scst_tape - device handler for tapes (type 1) - scst_processor - device handler for processors (type 3) @@ -222,7 +222,7 @@ Module parameters ----------------- -Module scsi_tgt supports the following parameters: +Module scst supports the following parameters: - scst_threads - allows to set count of SCST's threads. By default it is CPU count. Modified: trunk/scst/src/Makefile =================================================================== --- trunk/scst/src/Makefile 2007-08-15 09:59:46 UTC (rev 163) +++ trunk/scst/src/Makefile 2007-08-16 09:04:05 UTC (rev 164) @@ -31,16 +31,16 @@ ifneq ($(KERNELRELEASE),) SCST_INC_DIR := $(SUBDIRS)/../include -obj-m := scsi_tgt.o -scsi_tgt-objs := scst.o scst_targ.o scst_lib.o scst_mem.o scst_proc.o +obj-m := scst.o +scst-objs := scst_main.o scst_targ.o scst_lib.o scst_mem.o scst_proc.o -scsi_tgt-y += scst.o -scsi_tgt-y += scst_targ.o -scsi_tgt-y += scst_lib.o -scsi_tgt-y += scst_proc.o -scsi_tgt-y += scst_mem.o -scsi_tgt-y += scst_debug.o -obj-$(CONFIG_SCSI_TARGET) += scsi_tgt.o dev_handlers/ +scst-y += scst_main.o +scst-y += scst_targ.o +scst-y += scst_lib.o +scst-y += scst_proc.o +scst-y += scst_mem.o +scst-y += scst_debug.o +obj-$(CONFIG_SCSI_TARGET) += scst.o dev_handlers/ obj-$(BUILD_DEV) += $(DEV_HANDLERS_DIR)/ @@ -65,6 +65,7 @@ MOD_VERS := $(shell ls Module.symvers 2>/dev/null) install: all + -rm -f $(INSTALL_DIR)/scsi_tgt.ko $(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd) BUILD_DEV=m \ modules_install install -d $(INSTALL_DIR_H) @@ -90,13 +91,17 @@ uninstall: cd $(DEV_HANDLERS_DIR) && $(MAKE) $@ - rm -f $(INSTALL_DIR)/scsi_tgt.ko + rm -f $(INSTALL_DIR)/scst.ko -rmdir $(INSTALL_DIR) 2>/dev/null -/sbin/depmod -a $(KVER) rm -rf $(INSTALL_DIR_H) endif +ifeq ($(KVER),) INSTALL_DIR := /lib/modules/$(shell uname -r)/extra +else +INSTALL_DIR := /lib/modules/$(KVER)/extra +endif INSTALL_DIR_H := /usr/local/include/scst EXTRA_CFLAGS += -I$(SCST_INC_DIR) -Wextra -Wno-unused-parameter Modified: trunk/scst/src/dev_handlers/Makefile =================================================================== --- trunk/scst/src/dev_handlers/Makefile 2007-08-15 09:59:46 UTC (rev 163) +++ trunk/scst/src/dev_handlers/Makefile 2007-08-16 09:04:05 UTC (rev 164) @@ -60,7 +60,11 @@ rm -f $(INSTALL_DIR)/scst_*.ko endif +ifeq ($(KVER),) INSTALL_DIR := /lib/modules/$(shell uname -r)/extra +else +INSTALL_DIR := /lib/modules/$(KVER)/extra +endif EXTRA_CFLAGS += -I$(SUBDIRS) -I$(SCST_INC_DIR) -Wextra -Wno-unused-parameter Deleted: trunk/scst/src/scst.c =================================================================== --- trunk/scst/src/scst.c 2007-08-15 09:59:46 UTC (rev 163) +++ trunk/scst/src/scst.c 2007-08-16 09:04:05 UTC (rev 164) @@ -1,1714 +0,0 @@ -/* - * scst.c - * - * Copyright (C) 2004-2007 Vladislav Bolkhovitin <vs...@vl...> - * and Leonid Stoljar - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2 - * of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <asm/unistd.h> -#include <asm/string.h> -#include <linux/kthread.h> - -#include "scsi_tgt.h" -#include "scst_priv.h" -#include "scst_mem.h" - -#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) -#warning HIGHMEM kernel configurations are fully supported, but not \ - recommended for performance reasons. Consider change VMSPLIT \ - option or use 64-bit configuration instead. See README file for \ - details. -#endif - -#ifdef SCST_HIGHMEM -#error SCST_HIGHMEM configuration isn't supported and broken, because there \ - is no real point to support it, at least it definitely doesn't worth \ - the effort. Better use no-HIGHMEM kernel with VMSPLIT option \ - or in 64-bit configuration instead. See README file for details. -#endif - -#if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING) -#warning Patch scst_exec_req_fifo.patch was not applied on your kernel and \ - STRICT_SERIALIZING isn't defined. Pass-through dev handlers will \ - not be supported. -#endif - -/* - * All targets, devices and dev_types management is done under this mutex. - * - * It must NOT be used in any works (schedule_work(), etc.), because - * otherwise a deadlock (double lock, actually) is possible, e.g., with - * scst_user detach_tgt(), which is called under scst_mutex and calls - * flush_scheduled_work(). - */ -DEFINE_MUTEX(scst_mutex); - -LIST_HEAD(scst_template_list); -LIST_HEAD(scst_dev_list); -LIST_HEAD(scst_dev_type_list); - -spinlock_t scst_main_lock = SPIN_LOCK_UNLOCKED; - -struct kmem_cache *scst_mgmt_cachep; -mempool_t *scst_mgmt_mempool; -struct kmem_cache *scst_ua_cachep; -mempool_t *scst_ua_mempool; -struct kmem_cache *scst_tgtd_cachep; -struct kmem_cache *scst_sess_cachep; -struct kmem_cache *scst_acgd_cachep; - -LIST_HEAD(scst_acg_list); -struct scst_acg *scst_default_acg; - -spinlock_t scst_init_lock = SPIN_LOCK_UNLOCKED; -DECLARE_WAIT_QUEUE_HEAD(scst_init_cmd_list_waitQ); -LIST_HEAD(scst_init_cmd_list); -unsigned int scst_init_poll_cnt; - -struct kmem_cache *scst_cmd_cachep; - -#if defined(DEBUG) || defined(TRACING) -unsigned long scst_trace_flag = SCST_DEFAULT_LOG_FLAGS; -#endif - -unsigned long scst_flags; -atomic_t scst_cmd_count = ATOMIC_INIT(0); - -spinlock_t scst_cmd_mem_lock = SPIN_LOCK_UNLOCKED; -unsigned long scst_cur_cmd_mem, scst_cur_max_cmd_mem; -unsigned long scst_max_cmd_mem; - -struct scst_sgv_pools scst_sgv; - -struct scst_cmd_lists scst_main_cmd_lists; - -struct scst_tasklet scst_tasklets[NR_CPUS]; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -DECLARE_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn, 0); -#else -DECLARE_DELAYED_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn); -#endif - -spinlock_t scst_mcmd_lock = SPIN_LOCK_UNLOCKED; -LIST_HEAD(scst_active_mgmt_cmd_list); -LIST_HEAD(scst_delayed_mgmt_cmd_list); -DECLARE_WAIT_QUEUE_HEAD(scst_mgmt_cmd_list_waitQ); - -DECLARE_WAIT_QUEUE_HEAD(scst_mgmt_waitQ); -spinlock_t scst_mgmt_lock = SPIN_LOCK_UNLOCKED; -LIST_HEAD(scst_sess_init_list); -LIST_HEAD(scst_sess_shut_list); - -DECLARE_WAIT_QUEUE_HEAD(scst_dev_cmd_waitQ); - -DEFINE_MUTEX(scst_suspend_mutex); -LIST_HEAD(scst_cmd_lists_list); /* protected by scst_suspend_mutex */ - -static int scst_threads; -struct scst_threads_info_t scst_threads_info; - -static int suspend_count; - -int scst_virt_dev_last_id = 1; /* protected by scst_mutex */ - -/* - * This buffer and lock are intended to avoid memory allocation, which - * could fail in improper places. - */ -spinlock_t scst_temp_UA_lock = SPIN_LOCK_UNLOCKED; -uint8_t scst_temp_UA[SCST_SENSE_BUFFERSIZE]; - -module_param_named(scst_threads, scst_threads, int, 0); -MODULE_PARM_DESC(scst_threads, "SCSI target threads count"); - -module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, long, 0); -MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by " - "the SCST commands at any given time in Mb"); - -int scst_register_target_template(struct scst_tgt_template *vtt) -{ - int res = 0; - struct scst_tgt_template *t; - static DEFINE_MUTEX(m); - - TRACE_ENTRY(); - - INIT_LIST_HEAD(&vtt->tgt_list); - - if (!vtt->detect) { - PRINT_ERROR_PR("Target driver %s doesn't have a " - "detect() method.", vtt->name); - res = -EINVAL; - goto out_err; - } - - if (!vtt->release) { - PRINT_ERROR_PR("Target driver %s doesn't have a " - "release() method.", vtt->name); - res = -EINVAL; - goto out_err; - } - - if (!vtt->xmit_response) { - PRINT_ERROR_PR("Target driver %s doesn't have a " - "xmit_response() method.", vtt->name); - res = -EINVAL; - goto out_err; - } - - if (vtt->threads_num < 0) { - PRINT_ERROR_PR("Wrong threads_num value %d for " - "target \"%s\"", vtt->threads_num, - vtt->name); - res = -EINVAL; - goto out_err; - } - - if (!vtt->no_proc_entry) { - res = scst_build_proc_target_dir_entries(vtt); - if (res < 0) - goto out_err; - } - - if (vtt->preprocessing_done == NULL) - vtt->preprocessing_done_atomic = 1; - - if (mutex_lock_interruptible(&m) != 0) - goto out_err; - - if (mutex_lock_interruptible(&scst_mutex) != 0) - goto out_m_up; - list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { - if (strcmp(t->name, vtt->name) == 0) { - PRINT_ERROR_PR("Target driver %s already registered", - vtt->name); - mutex_unlock(&scst_mutex); - goto out_cleanup; - } - } - mutex_unlock(&scst_mutex); - - TRACE_DBG("%s", "Calling target driver's detect()"); - res = vtt->detect(vtt); - TRACE_DBG("Target driver's detect() returned %d", res); - if (res < 0) { - PRINT_ERROR_PR("%s", "The detect() routine failed"); - res = -EINVAL; - goto out_cleanup; - } - - mutex_lock(&scst_mutex); - list_add_tail(&vtt->scst_template_list_entry, &scst_template_list); - mutex_unlock(&scst_mutex); - - res = 0; - - PRINT_INFO_PR("Target template %s registered successfully", vtt->name); - - mutex_unlock(&m); - -out: - TRACE_EXIT_RES(res); - return res; - -out_m_up: - mutex_unlock(&m); - -out_cleanup: - scst_cleanup_proc_target_dir_entries(vtt); - -out_err: - PRINT_ERROR_PR("Failed to register target template %s", vtt->name); - goto out; -} - -void scst_unregister_target_template(struct scst_tgt_template *vtt) -{ - struct scst_tgt *tgt; - struct scst_tgt_template *t; - int found = 0; - - TRACE_ENTRY(); - - mutex_lock(&scst_mutex); - - list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { - if (strcmp(t->name, vtt->name) == 0) { - found = 1; - break; - } - } - if (!found) { - PRINT_ERROR_PR("Target driver %s isn't registered", vtt->name); - goto out_up; - } - -restart: - list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) { - mutex_unlock(&scst_mutex); - scst_unregister(tgt); - mutex_lock(&scst_mutex); - goto restart; - } - list_del(&vtt->scst_template_list_entry); - - PRINT_INFO_PR("Target template %s unregistered successfully", vtt->name); - -out_up: - mutex_unlock(&scst_mutex); - - scst_cleanup_proc_target_dir_entries(vtt); - - TRACE_EXIT(); - return; -} - -struct scst_tgt *scst_register(struct scst_tgt_template *vtt, - const char *target_name) -{ - struct scst_tgt *tgt; - - TRACE_ENTRY(); - - tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); - if (tgt == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", "kzalloc() failed"); - goto out_err; - } - - INIT_LIST_HEAD(&tgt->sess_list); - init_waitqueue_head(&tgt->unreg_waitQ); - tgt->tgtt = vtt; - tgt->sg_tablesize = vtt->sg_tablesize; - spin_lock_init(&tgt->tgt_lock); - INIT_LIST_HEAD(&tgt->retry_cmd_list); - atomic_set(&tgt->finished_cmds, 0); - init_timer(&tgt->retry_timer); - tgt->retry_timer.data = (unsigned long)tgt; - tgt->retry_timer.function = scst_tgt_retry_timer_fn; - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - if (target_name != NULL) { - int len = strlen(target_name) + 1 + - strlen(SCST_DEFAULT_ACG_NAME) + 1; - - tgt->default_group_name = kmalloc(len, GFP_KERNEL); - if (tgt->default_group_name == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of default " - "group name failed"); - goto out_free_err; - } - sprintf(tgt->default_group_name, "%s_%s", SCST_DEFAULT_ACG_NAME, - target_name); - } - - if (scst_build_proc_target_entries(tgt) < 0) - goto out_free_name; - else - list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list); - - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - PRINT_INFO_PR("Target %s for template %s registered successfully", - target_name, vtt->name); - -out: - TRACE_EXIT(); - return tgt; - -out_free_name: - if (tgt->default_group_name) - kfree(tgt->default_group_name); - -out_free_err: - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - kfree(tgt); - tgt = NULL; - -out_err: - PRINT_ERROR_PR("Failed to register target for template %s", vtt->name); - goto out; -} - -static inline int test_sess_list(struct scst_tgt *tgt) -{ - int res; - mutex_lock(&scst_mutex); - res = list_empty(&tgt->sess_list); - mutex_unlock(&scst_mutex); - return res; -} - -void scst_unregister(struct scst_tgt *tgt) -{ - struct scst_session *sess; - struct scst_tgt_template *vtt = tgt->tgtt; - - TRACE_ENTRY(); - - TRACE_DBG("%s", "Calling target driver's release()"); - tgt->tgtt->release(tgt); - TRACE_DBG("%s", "Target driver's release() returned"); - - mutex_lock(&scst_mutex); - list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { - sBUG_ON(sess->shut_phase == SCST_SESS_SPH_READY); - } - mutex_unlock(&scst_mutex); - - TRACE_DBG("%s", "Waiting for sessions shutdown"); - wait_event(tgt->unreg_waitQ, test_sess_list(tgt)); - TRACE_DBG("%s", "wait_event() returned"); - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - list_del(&tgt->tgt_list_entry); - - scst_cleanup_proc_target_entries(tgt); - - if (tgt->default_group_name) - kfree(tgt->default_group_name); - - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - del_timer_sync(&tgt->retry_timer); - - kfree(tgt); - - PRINT_INFO_PR("Target for template %s unregistered successfully", - vtt->name); - - TRACE_EXIT(); - return; -} - -void scst_suspend_activity(void) -{ - TRACE_ENTRY(); - - mutex_lock(&scst_suspend_mutex); - - TRACE_MGMT_DBG("suspend_count %d", suspend_count); - suspend_count++; - if (suspend_count > 1) - goto out_up; - - set_bit(SCST_FLAG_SUSPENDING, &scst_flags); - set_bit(SCST_FLAG_SUSPENDED, &scst_flags); - smp_mb__after_set_bit(); - - TRACE_MGMT_DBG("Waiting for %d active commands to complete", - atomic_read(&scst_cmd_count)); - wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0); - TRACE_MGMT_DBG("%s", "wait_event() returned"); - - clear_bit(SCST_FLAG_SUSPENDING, &scst_flags); - smp_mb__after_clear_bit(); - - TRACE_MGMT_DBG("Waiting for %d active commands finally to complete", - atomic_read(&scst_cmd_count)); - wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0); - TRACE_MGMT_DBG("%s", "wait_event() returned"); - -out_up: - mutex_unlock(&scst_suspend_mutex); - - TRACE_EXIT(); - return; -} - -void scst_resume_activity(void) -{ - struct scst_cmd_lists *l; - - TRACE_ENTRY(); - - mutex_lock(&scst_suspend_mutex); - - TRACE_MGMT_DBG("suspend_count %d", suspend_count); - suspend_count--; - if (suspend_count > 0) - goto out_up; - - clear_bit(SCST_FLAG_SUSPENDED, &scst_flags); - smp_mb__after_clear_bit(); - - list_for_each_entry(l, &scst_cmd_lists_list, lists_list_entry) { - wake_up_all(&l->cmd_list_waitQ); - } - wake_up_all(&scst_init_cmd_list_waitQ); - - spin_lock_irq(&scst_mcmd_lock); - if (!list_empty(&scst_delayed_mgmt_cmd_list)) { - struct scst_mgmt_cmd *m; - m = list_entry(scst_delayed_mgmt_cmd_list.next, typeof(*m), - mgmt_cmd_list_entry); - TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active " - "mgmt cmd list", m); - list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list); - } - spin_unlock_irq(&scst_mcmd_lock); - wake_up_all(&scst_mgmt_cmd_list_waitQ); - -out_up: - mutex_unlock(&scst_suspend_mutex); - - TRACE_EXIT(); - return; -} - -static int scst_register_device(struct scsi_device *scsidp) -{ - int res = 0; - struct scst_device *dev; - struct scst_dev_type *dt; - - TRACE_ENTRY(); - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - res = scst_alloc_device(GFP_KERNEL, &dev); - if (res != 0) - goto out_up; - - dev->type = scsidp->type; - - dev->rq_disk = alloc_disk(1); - if (dev->rq_disk == NULL) { - res = -ENOMEM; - goto out_free_dev; - } - dev->rq_disk->major = SCST_MAJOR; - - dev->scsi_dev = scsidp; - - list_add_tail(&dev->dev_list_entry, &scst_dev_list); - - list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { - if (dt->type == scsidp->type) { - res = scst_assign_dev_handler(dev, dt); - if (res != 0) - goto out_free; - break; - } - } - -out_up: - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - if (res == 0) { - PRINT_INFO_PR("Attached SCSI target mid-level at " - "scsi%d, channel %d, id %d, lun %d, type %d", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type); - } - else { - PRINT_ERROR_PR("Failed to attach SCSI target mid-level " - "at scsi%d, channel %d, id %d, lun %d, type %d", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type); - } - - TRACE_EXIT_RES(res); - return res; - -out_free: - list_del(&dev->dev_list_entry); - put_disk(dev->rq_disk); - -out_free_dev: - scst_free_device(dev); - goto out_up; -} - -static void scst_unregister_device(struct scsi_device *scsidp) -{ - struct scst_device *d, *dev = NULL; - struct scst_acg_dev *acg_dev, *aa; - - TRACE_ENTRY(); - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - list_for_each_entry(d, &scst_dev_list, dev_list_entry) { - if (d->scsi_dev == scsidp) { - dev = d; - TRACE_DBG("Target device %p found", dev); - break; - } - } - if (dev == NULL) { - PRINT_ERROR_PR("%s", "Target device not found"); - goto out_unblock; - } - - list_del(&dev->dev_list_entry); - - list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list, - dev_acg_dev_list_entry) - { - scst_acg_remove_dev(acg_dev->acg, dev); - } - - scst_assign_dev_handler(dev, NULL); - - put_disk(dev->rq_disk); - scst_free_device(dev); - - PRINT_INFO_PR("Detached SCSI target mid-level from scsi%d, channel %d, " - "id %d, lun %d, type %d", scsidp->host->host_no, - scsidp->channel, scsidp->id, scsidp->lun, scsidp->type); - -out_unblock: - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - TRACE_EXIT(); - return; -} - -static int scst_dev_handler_check(struct scst_dev_type *dev_handler) -{ - int res = 0; - - if (dev_handler->parse == NULL) { - PRINT_ERROR_PR("scst dev_type driver %s doesn't have a " - "parse() method.", dev_handler->name); - res = -EINVAL; - goto out; - } - - if (dev_handler->exec == NULL) - dev_handler->exec_atomic = 1; - - if (dev_handler->dev_done == NULL) - dev_handler->dev_done_atomic = 1; - -out: - TRACE_EXIT_RES(res); - return res; -} - -int scst_register_virtual_device(struct scst_dev_type *dev_handler, - const char *dev_name) -{ - int res, rc; - struct scst_device *dev = NULL; - - TRACE_ENTRY(); - - if (dev_handler == NULL) { - PRINT_ERROR_PR("%s: valid device handler must be supplied", - __FUNCTION__); - res = -EINVAL; - goto out; - } - - if (dev_name == NULL) { - PRINT_ERROR_PR("%s: device name must be non-NULL", __FUNCTION__); - res = -EINVAL; - goto out; - } - - res = scst_dev_handler_check(dev_handler); - if (res != 0) - goto out; - - scst_suspend_activity(); - if (mutex_lock_interruptible(&scst_mutex) != 0) { - res = -EINTR; - goto out_resume; - } - - res = scst_alloc_device(GFP_KERNEL, &dev); - if (res != 0) - goto out_up; - - dev->type = dev_handler->type; - dev->scsi_dev = NULL; - dev->virt_name = dev_name; - dev->virt_id = scst_virt_dev_last_id++; - - list_add_tail(&dev->dev_list_entry, &scst_dev_list); - - res = dev->virt_id; - - rc = scst_assign_dev_handler(dev, dev_handler); - if (rc != 0) { - res = rc; - goto out_free_del; - } - -out_up: - mutex_unlock(&scst_mutex); - -out_resume: - scst_resume_activity(); - -out: - if (res > 0) { - PRINT_INFO_PR("Attached SCSI target mid-level to virtual " - "device %s (id %d)", dev_name, dev->virt_id); - } - else { - PRINT_INFO_PR("Failed to attach SCSI target mid-level to " - "virtual device %s", dev_name); - } - - TRACE_EXIT_RES(res); - return res; - -out_free_del: - list_del(&dev->dev_list_entry); - scst_free_device(dev); - goto out_up; -} - -void scst_unregister_virtual_device(int id) -{ - struct scst_device *d, *dev = NULL; - struct scst_acg_dev *acg_dev, *aa; - - TRACE_ENTRY(); - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - list_for_each_entry(d, &scst_dev_list, dev_list_entry) { - if (d->virt_id == id) { - dev = d; - TRACE_DBG("Target device %p found", dev); - break; - } - } - if (dev == NULL) { - PRINT_ERROR_PR("%s", "Target device not found"); - goto out_unblock; - } - - list_del(&dev->dev_list_entry); - - list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list, - dev_acg_dev_list_entry) - { - scst_acg_remove_dev(acg_dev->acg, dev); - } - - scst_assign_dev_handler(dev, NULL); - - PRINT_INFO_PR("Detached SCSI target mid-level from virtual device %s " - "(id %d)", dev->virt_name, dev->virt_id); - - scst_free_device(dev); - -out_unblock: - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - TRACE_EXIT(); - return; -} - -int scst_register_dev_driver(struct scst_dev_type *dev_type) -{ - struct scst_dev_type *dt; - struct scst_device *dev; - int res; - int exist; - - TRACE_ENTRY(); - - res = scst_dev_handler_check(dev_type); - if (res != 0) - goto out_err; - -#if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING) - if (dev_type->exec == NULL) { - PRINT_ERROR_PR("Pass-through dev handlers (handler \"%s\") not " - "supported. Consider applying on your kernel patch " - "scst_exec_req_fifo.patch or define STRICT_SERIALIZING", - dev_type->name); - res = -EINVAL; - goto out_err; - } -#endif - - scst_suspend_activity(); - if (mutex_lock_interruptible(&scst_mutex) != 0) { - res = -EINTR; - goto out_err; - } - - exist = 0; - list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { - if (strcmp(dt->name, dev_type->name) == 0) { - PRINT_ERROR_PR("Device type handler \"%s\" already " - "exist", dt->name); - exist = 1; - break; - } - } - if (exist) - goto out_up; - - res = scst_build_proc_dev_handler_dir_entries(dev_type); - if (res < 0) { - goto out_up; - } - - list_add_tail(&dev_type->dev_type_list_entry, &scst_dev_type_list); - - list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { - if ((dev->scsi_dev == NULL) || (dev->handler != NULL)) - continue; - if (dev->scsi_dev->type == dev_type->type) - scst_assign_dev_handler(dev, dev_type); - } - - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - if (res == 0) { - PRINT_INFO_PR("Device handler \"%s\" for type %d registered " - "successfully", dev_type->name, dev_type->type); - } - -out: - TRACE_EXIT_RES(res); - return res; - -out_up: - mutex_unlock(&scst_mutex); - -out_err: - scst_resume_activity(); - PRINT_ERROR_PR("Failed to register device handler \"%s\" for type %d", - dev_type->name, dev_type->type); - goto out; -} - -void scst_unregister_dev_driver(struct scst_dev_type *dev_type) -{ - struct scst_device *dev; - struct scst_dev_type *dt; - int found = 0; - - TRACE_ENTRY(); - - scst_suspend_activity(); - mutex_lock(&scst_mutex); - - list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { - if (strcmp(dt->name, dev_type->name) == 0) { - found = 1; - break; - } - } - if (!found) { - PRINT_ERROR_PR("Dev handler \"%s\" isn't registered", - dev_type->name); - goto out_up; - } - - list_for_each_entry(dev, &scst_dev_list, dev_list_entry) { - if (dev->handler == dev_type) { - scst_assign_dev_handler(dev, NULL); - TRACE_DBG("Dev handler removed from device %p", dev); - } - } - - list_del(&dev_type->dev_type_list_entry); - - mutex_unlock(&scst_mutex); - scst_resume_activity(); - - scst_cleanup_proc_dev_handler_dir_entries(dev_type); - - PRINT_INFO_PR("Device handler \"%s\" for type %d unloaded", - dev_type->name, dev_type->type); - -out: - TRACE_EXIT(); - return; - -out_up: - mutex_unlock(&scst_mutex); - scst_resume_activity(); - goto out; -} - -int scst_register_virtual_dev_driver(struct scst_dev_type *dev_type) -{ - int res; - - TRACE_ENTRY(); - - res = scst_dev_handler_check(dev_type); - if (res != 0) - goto out_err; - - if (!dev_type->no_proc) { - res = scst_build_proc_dev_handler_dir_entries(dev_type); - if (res < 0) - goto out_err; - } - - if (dev_type->type != -1) { - PRINT_INFO_PR("Virtual device handler %s for type %d " - "registered successfully", dev_type->name, - dev_type->type); - } else { - PRINT_INFO_PR("Virtual device handler \"%s\" registered " - "successfully", dev_type->name); - } - -out: - TRACE_EXIT_RES(res); - return res; - -out_err: - PRINT_ERROR_PR("Failed to register virtual device handler \"%s\"", - dev_type->name); - goto out; -} - -void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type) -{ - TRACE_ENTRY(); - - if (!dev_type->no_proc) - scst_cleanup_proc_dev_handler_dir_entries(dev_type); - - PRINT_INFO_PR("Device handler \"%s\" unloaded", dev_type->name); - - TRACE_EXIT(); - return; -} - -/* Called under scst_mutex and suspended activity */ -int scst_add_dev_threads(struct scst_device *dev, int num) -{ - int i, res = 0; - int n = 0; - struct scst_cmd_thread_t *thr; - char nm[12]; - - TRACE_ENTRY(); - - list_for_each_entry(thr, &dev->threads_list, thread_list_entry) { - n++; - } - - for (i = 0; i < num; i++) { - thr = kmalloc(sizeof(*thr), GFP_KERNEL); - if (!thr) { - res = -ENOMEM; - PRINT_ERROR_PR("Failed to allocate thr %d", res); - goto out; - } - strncpy(nm, dev->handler->name, ARRAY_SIZE(nm)-1); - nm[ARRAY_SIZE(nm)-1] = '\0'; - thr->cmd_thread = kthread_run(scst_cmd_thread, - &dev->cmd_lists, "%sd%d_%d", nm, dev->dev_num, n++); - if (IS_ERR(thr->cmd_thread)) { - res = PTR_ERR(thr->cmd_thread); - PRINT_ERROR_PR("kthread_create() failed: %d", res); - kfree(thr); - goto out; - } - list_add(&thr->thread_list_entry, &dev->threads_list); - } - -out: - TRACE_EXIT_RES(res); - return res; -} - -/* Called under scst_mutex and suspended activity */ -static int scst_create_dev_threads(struct scst_device *dev) -{ - int res = 0; - int threads_num; - - TRACE_ENTRY(); - - if (dev->handler->threads_num <= 0) - goto out; - - threads_num = dev->handler->threads_num; - - spin_lock_init(&dev->cmd_lists.cmd_list_lock); - INIT_LIST_HEAD(&dev->cmd_lists.active_cmd_list); - init_waitqueue_head(&dev->cmd_lists.cmd_list_waitQ); - - res = scst_add_dev_threads(dev, threads_num); - if (res != 0) - goto out; - - mutex_lock(&scst_suspend_mutex); - list_add_tail(&dev->cmd_lists.lists_list_entry, - &scst_cmd_lists_list); - mutex_unlock(&scst_suspend_mutex); - - dev->p_cmd_lists = &dev->cmd_lists; - -out: - TRACE_EXIT_RES(res); - return res; -} - -/* Called under scst_mutex and suspended activity */ -void scst_del_dev_threads(struct scst_device *dev, int num) -{ - struct scst_cmd_thread_t *ct, *tmp; - int i = 0; - - TRACE_ENTRY(); - - list_for_each_entry_safe(ct, tmp, &dev->threads_list, - thread_list_entry) { - int 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; - } - - TRACE_EXIT(); - return; -} - -/* Called under scst_mutex and suspended activity */ -static void scst_stop_dev_threads(struct scst_device *dev) -{ - TRACE_ENTRY(); - - if (list_empty(&dev->threads_list)) - goto out; - - scst_del_dev_threads(dev, -1); - - if (dev->p_cmd_lists == &dev->cmd_lists) { - mutex_lock(&scst_suspend_mutex); - list_del(&dev->cmd_lists.lists_list_entry); - mutex_unlock(&scst_suspend_mutex); - } - -out: - TRACE_EXIT(); - return; -} - -/* The activity supposed to be suspended and scst_mutex held */ -int scst_assign_dev_handler(struct scst_device *dev, - struct scst_dev_type *handler) -{ - int res = 0; - struct scst_tgt_dev *tgt_dev; - LIST_HEAD(attached_tgt_devs); - - TRACE_ENTRY(); - - if (dev->handler == handler) - goto out; - - if (dev->handler && dev->handler->detach_tgt) { - list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) { - TRACE_DBG("Calling dev handler's detach_tgt(%p)", - tgt_dev); - dev->handler->detach_tgt(tgt_dev); - TRACE_DBG("%s", "Dev handler's detach_tgt() returned"); - } - } - - if (dev->handler && dev->handler->detach) { - TRACE_DBG("%s", "Calling dev handler's detach()"); - dev->handler->detach(dev); - TRACE_DBG("%s", "Old handler's detach() returned"); - } - - scst_stop_dev_threads(dev); - - dev->handler = handler; - - if (handler) { - res = scst_create_dev_threads(dev); - if (res != 0) - goto out_null; - } - - if (handler && handler->attach) { - TRACE_DBG("Calling new dev handler's attach(%p)", dev); - res = handler->attach(dev); - TRACE_DBG("New dev handler's attach() returned %d", res); - if (res != 0) { - PRINT_ERROR_PR("New device handler's %s attach() " - "failed: %d", handler->name, res); - } - goto out_thr_null; - } - - if (handler && handler->attach_tgt) { - list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) { - TRACE_DBG("Calling dev handler's attach_tgt(%p)", - tgt_dev); - res = handler->attach_tgt(tgt_dev); - TRACE_DBG("%s", "Dev handler's attach_tgt() returned"); - if (res != 0) { - PRINT_ERROR_PR("Device handler's %s attach_tgt() " - "failed: %d", handler->name, res); - goto out_err_detach_tgt; - } - list_add_tail(&tgt_dev->extra_tgt_dev_list_entry, - &attached_tgt_devs); - } - } - -out_thr_null: - if (res != 0) - scst_stop_dev_threads(dev); - -out_null: - if (res != 0) - dev->handler = NULL; - -out: - TRACE_EXIT_RES(res); - return res; - -out_err_detach_tgt: - if (handler && handler->detach_tgt) { - list_for_each_entry(tgt_dev, &attached_tgt_devs, - extra_tgt_dev_list_entry) - { - TRACE_DBG("Calling handler's detach_tgt(%p)", - tgt_dev); - handler->detach_tgt(tgt_dev); - TRACE_DBG("%s", "Handler's detach_tgt() returned"); - } - } - if (handler && handler->detach) { - TRACE_DBG("%s", "Calling handler's detach()"); - handler->detach(dev); - TRACE_DBG("%s", "Handler's detach() returned"); - } - goto out_null; -} - -int scst_cmd_threads_count(void) -{ - int i; - - /* Just to lower the race window, when user can get just changed value */ - mutex_lock(&scst_threads_info.cmd_threads_mutex); - i = scst_threads_info.nr_cmd_threads; - mutex_unlock(&scst_threads_info.cmd_threads_mutex); - return i; -} - -static void scst_threads_info_init(void) -{ - memset(&scst_threads_info, 0, sizeof(scst_threads_info)); - mutex_init(&scst_threads_info.cmd_threads_mutex); - INIT_LIST_HEAD(&scst_threads_info.cmd_threads_list); -} - -/* scst_threads_info.cmd_threads_mutex supposed to be held */ -void __scst_del_cmd_threads(int num) -{ - struct scst_cmd_thread_t *ct, *tmp; - int i; - - TRACE_ENTRY(); - - i = scst_threads_info.nr_cmd_threads; - if (num <= 0 || num > i) { - PRINT_ERROR_PR("can not del %d cmd threads from %d", num, i); - return; - } - - list_for_each_entry_safe(ct, tmp, &scst_threads_info.cmd_threads_list, - thread_list_entry) { - int res; - - res = kthread_stop(ct->cmd_thread); - if (res < 0) { - TRACE_MGMT_DBG("kthread_stop() failed: %d", res); - } - list_del(&ct->thread_list_entry); - kfree(ct); - scst_threads_info.nr_cmd_threads--; - --num; - if (num == 0) - break; - } - - TRACE_EXIT(); - return; -} - -/* scst_threads_info.cmd_threads_mutex supposed to be held */ -int __scst_add_cmd_threads(int num) -{ - int res = 0, i; - static int scst_thread_num = 0; - - TRACE_ENTRY(); - - for (i = 0; i < num; i++) { - struct scst_cmd_thread_t *thr; - - thr = kmalloc(sizeof(*thr), GFP_KERNEL); - if (!thr) { - res = -ENOMEM; - PRINT_ERROR_PR("fail to allocate thr %d", res); - goto out_error; - } - thr->cmd_thread = kthread_run(scst_cmd_thread, - &scst_main_cmd_lists, "scsi_tgt%d", - scst_thread_num++); - if (IS_ERR(thr->cmd_thread)) { - res = PTR_ERR(thr->cmd_thread); - PRINT_ERROR_PR("kthread_create() failed: %d", res); - kfree(thr); - goto out_error; - } - list_add(&thr->thread_list_entry, - &scst_threads_info.cmd_threads_list); - scst_threads_info.nr_cmd_threads++; - } - res = 0; - -out: - TRACE_EXIT_RES(res); - return res; - -out_error: - if (i > 0) - __scst_del_cmd_threads(i - 1); - goto out; -} - -int scst_add_cmd_threads(int num) -{ - int res; - - TRACE_ENTRY(); - - mutex_lock(&scst_threads_info.cmd_threads_mutex); - res = __scst_add_cmd_threads(num); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); - - TRACE_EXIT_RES(res); - return res; -} - -void scst_del_cmd_threads(int num) -{ - TRACE_ENTRY(); - - mutex_lock(&scst_threads_info.cmd_threads_mutex); - __scst_del_cmd_threads(num); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); - - TRACE_EXIT(); - return; -} - -static void scst_stop_all_threads(void) -{ - TRACE_ENTRY(); - - mutex_lock(&scst_threads_info.cmd_threads_mutex); - __scst_del_cmd_threads(scst_threads_info.nr_cmd_threads); - if (scst_threads_info.mgmt_cmd_thread) - kthread_stop(scst_threads_info.mgmt_cmd_thread); - if (scst_threads_info.mgmt_thread) - kthread_stop(scst_threads_info.mgmt_thread); - if (scst_threads_info.init_cmd_thread) - kthread_stop(scst_threads_info.init_cmd_thread); - mutex_unlock(&scst_threads_info.cmd_threads_mutex); - - TRACE_EXIT(); - return; -} - -static int scst_start_all_threads(int num) -{ - int res; - - TRACE_ENTRY(); - - mutex_lock(&scst_threads_info.cmd_threads_mutex); - res = __scst_add_cmd_threads(num); - if (res < 0) - goto out; - - scst_threads_info.init_cmd_thread = kthread_run(scst_init_cmd_thread, - NULL, "scsi_tgt_init"); - if (IS_ERR(scst_threads_info.init_cmd_thread)) { - res = PTR_ERR(scst_threads_info.init_cmd_thread); - PRINT_ERROR_PR("kthread_create() for init cmd failed: %d", res); - scst_threads_info.init_cmd_thread = NULL; - goto out; - } - - scst_threads_info.mgmt_cmd_thread = kthread_run(scst_mgmt_cmd_thread, - NULL, "scsi_tgt_mc"); - if (IS_ERR(scst_threads_info.mgmt_cmd_thread)) { - res = PTR_ERR(scst_threads_info.mgmt_cmd_thread); - PRINT_ERROR_PR("kthread_create() for mcmd failed: %d", res); - scst_threads_info.mgmt_cmd_thread = NULL; - goto out; - } - - scst_threads_info.mgmt_thread = kthread_run(scst_mgmt_thread, - NULL, "scsi_tgt_mgmt"); - if (IS_ERR(scst_threads_info.mgmt_thread)) { - res = PTR_ERR(scst_threads_info.mgmt_thread); - PRINT_ERROR_PR("kthread_create() for mgmt failed: %d", res); - scst_threads_info.mgmt_thread = NULL; - goto out; - } - -out: - mutex_unlock(&scst_threads_info.cmd_threads_mutex); - TRACE_EXIT_RES(res); - return res; -} - -void scst_get(void) -{ - __scst_get(0); -} - -void scst_put(void) -{ - __scst_put(); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -static int scst_add(struct class_device *cdev) -#else -static int scst_add(struct class_device *cdev, struct class_interface *intf) -#endif -{ - struct scsi_device *scsidp; - int res = 0; - - TRACE_ENTRY(); - - scsidp = to_scsi_device(cdev->dev); - res = scst_register_device(scsidp); - - TRACE_EXIT(); - return res; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -static void scst_remove(struct class_device *cdev) -#else -static void scst_remove(struct class_device *cdev, struct class_interface *intf) -#endif -{ - struct scsi_device *scsidp; - - TRACE_ENTRY(); - - scsidp = to_scsi_device(cdev->dev); - scst_unregister_device(scsidp); - - TRACE_EXIT(); - return; -} - -static struct class_interface scst_interface = { - .add = scst_add, - .remove = scst_remove, -}; - -static int __init init_scst(void) -{ - int res = 0, i; - struct scst_cmd *cmd; - int scst_num_cpus; - - TRACE_ENTRY(); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - { - struct scsi_request *req; - BUILD_BUG_ON(sizeof(cmd->sense_buffer) != - sizeof(req->sr_sense_buffer)); - } -#else - { - struct scsi_sense_hdr *shdr; - BUILD_BUG_ON((sizeof(cmd->sense_buffer) < sizeof(*shdr)) && - (sizeof(cmd->sense_buffer) >= SCST_SENSE_BUFFERSIZE)); - } -#endif - { - struct scst_tgt_dev *t; - struct scst_cmd *c; - BUILD_BUG_ON(sizeof(t->curr_sn) != sizeof(t->expected_sn)); - BUILD_BUG_ON(sizeof(c->sn) != sizeof(t->expected_sn)); - } - - BUILD_BUG_ON(SCST_DATA_UNKNOWN != DMA_BIDIRECTIONAL); - BUILD_BUG_ON(SCST_DATA_WRITE != DMA_TO_DEVICE); - BUILD_BUG_ON(SCST_DATA_READ != DMA_FROM_DEVICE); - BUILD_BUG_ON(SCST_DATA_NONE != DMA_NONE); - - spin_lock_init(&scst_main_cmd_lists.cmd_list_lock); - INIT_LIST_HEAD(&scst_main_cmd_lists.active_cmd_list); - init_waitqueue_head(&scst_main_cmd_lists.cmd_list_waitQ); - list_add_tail(&scst_main_cmd_lists.lists_list_entry, - &scst_cmd_lists_list); - - scst_num_cpus = num_online_cpus(); - - /* ToDo: register_cpu_notifier() */ - - if (scst_threads == 0) - scst_threads = scst_num_cpus; - - if (scst_threads < scst_num_cpus) { - PRINT_ERROR_PR("%s", "scst_threads can not be less than " - "CPUs count"); - scst_threads = scst_num_cpus; - } - - scst_threads_info_init(); - -#define INIT_CACHEP(p, s, t, o) do { \ - p = kmem_cache_create(s, sizeof(struct t), 0, \ - SCST_SLAB_FLAGS, NULL, NULL); \ - TRACE_MEM("Slab create: %s at %p size %zd", s, p, \ - sizeof(struct t)); \ - if (p == NULL) { res = -ENOMEM; goto o; } \ - } while (0) - - INIT_CACHEP(scst_mgmt_cachep, SCST_MGMT_CMD_CACHE_STRING, - scst_mgmt_cmd, out); - INIT_CACHEP(scst_ua_cachep, SCST_UA_CACHE_STRING, - scst_tgt_dev_UA, out_destroy_mgmt_cache); - INIT_CACHEP(scst_cmd_cachep, SCST_CMD_CACHE_STRING, - scst_cmd, out_destroy_ua_cache); - INIT_CACHEP(scst_sess_cachep, SCST_SESSION_CACHE_STRING, - scst_session, out_destroy_cmd_cache); - INIT_CACHEP(scst_tgtd_cachep, SCST_TGT_DEV_CACHE_STRING, - scst_tgt_dev, out_destroy_sess_cache); - INIT_CACHEP(scst_acgd_cachep, SCST_ACG_DEV_CACHE_STRING, - scst_acg_dev, out_destroy_tgt_cache); - - scst_mgmt_mempool = mempool_create(10, mempool_alloc_slab, - mempool_free_slab, scst_mgmt_cachep); - if (scst_mgmt_mempool == NULL) { - res = -ENOMEM; - goto out_destroy_acg_cache; - } - - scst_ua_mempool = mempool_create(25, mempool_alloc_slab, - mempool_free_slab, scst_ua_cachep); - if (scst_ua_mempool == NULL) { - res = -ENOMEM; - goto out_destroy_mgmt_mempool; - } - - res = scst_sgv_pools_init(&scst_sgv); - if (res != 0) - goto out_destroy_ua_mempool; - - scst_default_acg = scst_alloc_add_acg(SCST_DEFAULT_ACG_NAME); - if (scst_default_acg == NULL) { - res = -ENOMEM; - goto out_destroy_sgv_pool; - } - - res = scsi_register_interface(&scst_interface); - if (res != 0) - goto out_free_acg; - - scst_scsi_op_list_init(); - - for (i = 0; i < (int)ARRAY_SIZE(scst_tasklets); i++) { - spin_lock_init(&scst_tasklets[i].tasklet_lock); - INIT_LIST_HEAD(&scst_tasklets[i].tasklet_cmd_list); - tasklet_init(&scst_tasklets[i].tasklet, (void*)scst_cmd_tasklet, - (unsigned long)&scst_tasklets[i]); - } - - TRACE_DBG("%d CPUs found, starting %d threads", scst_num_cpus, - scst_threads); - - res = scst_start_all_threads(scst_threads); - if (res < 0) - goto out_thread_free; - - res = scst_proc_init_module(); - if (res != 0) - goto out_thread_free; - - if (scst_max_cmd_mem == 0) { - struct sysinfo si; - si_meminfo(&si); -#if BITS_PER_LONG == 32 - scst_max_cmd_mem = min(((uint64_t)si.totalram << PAGE_SHIFT) >> 2, - (uint64_t)1 << 30); -#else - scst_max_cmd_mem = (si.totalram << PAGE_SHIFT) >> 2; -#endif - } else - scst_max_cmd_mem <<= 20; - - scst_cur_max_cmd_mem = scst_max_cmd_mem; - - PRINT_INFO_PR("SCST version %s loaded successfully (max mem for " - "commands %ld Mb)", SCST_VERSION_STRING, scst_max_cmd_mem >> 20); - -out: - TRACE_EXIT_RES(res); - return res; - -out_thread_free: - scst_stop_all_threads(); - - scsi_unregister_interface(&scst_interface); - -out_free_acg: - scst_destroy_acg(scst_default_acg); - -out_destroy_sgv_pool: - scst_sgv_pools_deinit(&scst_sgv); - -out_destroy_ua_mempool: - mempool_destroy(scst_ua_mempool); - -out_destroy_mgmt_mempool: - mempool_destroy(scst_mgmt_mempool); - -out_destroy_acg_cache: - kmem_cache_destroy(scst_acgd_cachep); - -out_destroy_tgt_cache: - kmem_cache_destroy(scst_tgtd_cachep); - -out_destroy_sess_cache: - kmem_cache_destroy(scst_sess_cachep); - -out_destroy_cmd_cache: - kmem_cache_destroy(scst_cmd_cachep); - -out_destroy_ua_cache: - kmem_cache_destroy(scst_ua_cachep); - -out_destroy_mgmt_cache: - kmem_cache_destroy(scst_mgmt_cachep); - goto out; -} - -static void __exit exit_scst(void) -{ -#ifdef CONFIG_LOCKDEP - static /* To hide the lockdep's warning about non-static key */ -#endif - DECLARE_MUTEX_LOCKED(shm); - - TRACE_ENTRY(); - - /* ToDo: unregister_cpu_notifier() */ - - if (test_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags)) { - cancel_delayed_work(&scst_cmd_mem_work); - flush_scheduled_work(); - } - - scst_proc_cleanup_module(); - - scst_stop_all_threads(); - - scsi_unregister_interface(&scst_interface); - scst_destroy_acg(scst_default_acg); - - scst_sgv_pools_deinit(&scst_sgv); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define DEINIT_CACHEP(p, s) do { \ - if (kmem_cache_destroy(p)) { \ - PRINT_INFO_PR("kmem_cache_destroy of %s returned an "\ - "error", s); \ - } \ - p = NULL; \ - } while (0) -#else -#define DEINIT_CACHEP(p, s) do { \ - kmem_cache_destroy(p); \ - p = NULL; \ - } while (0) -#endif - - mempool_destroy(scst_mgmt_mempool); - mempool_destroy(scst_ua_mempool); - - DEINIT_CACHEP(scst_mgmt_cachep, SCST_MGMT_CMD_CACHE_STRING); - DEINIT_CACHEP(scst_ua_cachep, SCST_UA_CACHE_STRING); - DEINIT_CACHEP(scst_cmd_cachep, SCST_CMD_CACHE_STRING); - DEINIT_CACHEP(scst_sess_cachep, SCST_SESSION_CACHE_STRING); - DEINIT_CACHEP(scst_tgtd_cachep, SCST_TGT_DEV_CACHE_STRING); - DEINIT_CACHEP(scst_acgd_cachep, SCST_ACG_DEV_CACHE_STRING); - - PRINT_INFO_PR("%s", "SCST unloaded"); - - TRACE_EXIT(); - return; -} - -/* - * Device Handler Side (i.e. scst_vdisk) - */ -EXPORT_SYMBOL(scst_register_dev_driver); -EXPORT_SYMBOL(scst_unregister_dev_driver); -EXPORT_SYMBOL(scst_register); -EXPORT_SYMBOL(scst_unregister); - -EXPORT_SYMBOL(scst_register_virtual_device); -EXPORT_SYMBOL(scst_unregister_virtual_device); -EXPORT_SYMBOL(scst_register_virtual_dev_driver); -EXPORT_SYMBOL(scst_unregister_virtual_dev_driver); - -EXPORT_SYMBOL(scst_set_busy); -EXPORT_SYMBOL(scst_set_cmd_error_status); -EXPORT_SYMBOL(scst_set_cmd_error); -EXPORT_SYMBOL(scst_set_resp_data_len); - -EXPORT_SYMBOL(scst_process_active_cmd); - -/* - * Target Driver Side (i.e. HBA) - */ -EXPORT_SYMBOL(scst_register_session); -EXPORT_SYMBOL(scst_unregister_session); - -EXPORT_SYMBOL(scst_register_target_template); -EXPORT_SYMBOL(scst_unregister_target_template); - -EXPORT_SYMBOL(scst_cmd_init_done); -EXPORT_SYMBOL(scst_tgt_cmd_done); -EXPORT_SYMBOL(scst_restart_cmd); -EXPORT_SYMBOL(scst_rx_cmd); -EXPORT_SYMBOL(scst_rx_data); -EXPORT_SYMBOL(scst_rx_mgmt_fn_tag); -EXPORT_SYMBOL(scst_rx_mgmt_fn_lun); - -EXPORT_SYMBOL(scst_find_cmd); -EXPORT_SYMBOL(scst_find_cmd_by_tag); - -/* - * Global Commands - */ -EXPORT_SYMBOL(scst_suspend_activity); -EXPORT_SYMBOL(scst_resume_activity); - -EXPORT_SYMBOL(scst_add_cmd_threads); -EXPORT_SYMBOL(scst_del_cmd_threads); - -#if defined(DEBUG) || defined(TRACING) -EXPORT_SYMBOL(scst_proc_log_entry_read); -EXPORT_SYMBOL(scst_proc_log_entry_write); -#endif - -EXPORT_SYMBOL(scst_create_proc_entry); -EXPORT_SYMBOL(scst_single_seq_open); - -EXPORT_SYMBOL(__scst_get_buf); -EXPORT_SYMBOL(scst_check_mem); -EXPORT_SYMBOL(scst_get); -EXPORT_SYMBOL(scst_put); - -EXPORT_SYMBOL(scst_alloc); -EXPORT_SYMBOL(scst_free); - -EXPORT_SYMBOL(scst_check_local_events); - -/* Tgt_dev's threads local storage */ -EXPORT_SYMBOL(scst_add_thr_data); -EXPORT_SYMBOL(scst_del_all_thr_data); -EXPORT_SYMBOL(scst_dev_del_all_thr_data); -EXPORT_SYMBOL(scst_find_thr_data); - -/* SGV pool routines */ -EXPORT_SYMBOL(sgv_pool_create); -EXPORT_SYMBOL(sgv_pool_destroy); -EXPORT_SYMBOL(sgv_pool_set_allocator); -EXPORT_SYMBOL(sgv_pool_alloc); -EXPORT_SYMBOL(sgv_pool_free); -EXPORT_SYMBOL(sgv_get_priv); - -/* Generic parse() routines */ -EXPORT_SYMBOL(scst_calc_block_shift); -EXPORT_SYMBOL(scst_sbc_generic_parse); -EXPORT_SYMBOL(scst_cdrom_generic_parse); -EXPORT_SYMBOL(scst_modisk_generic_parse); -EXPORT_SYMBOL(scst_tape_generic_parse); -EXPORT_SYMBOL(scst_changer_generic_parse); -EXPORT_SYMBOL(scst_processor_generic_parse); -EXPORT_SYMBOL(scst_raid_generic_parse); - -/* Generic dev_done() routines */ -EXPORT_SYMBOL(scst_block_generic_dev_done); -EXPORT_SYMBOL(scst_tape_generic_dev_done); - -/* - * Other Commands - */ -EXPORT_SYMBOL(scst_get_cdb_info); -EXPORT_SYMBOL(scst_cmd_get_tgt_priv_lock); -EXPORT_SYMBOL(scst_cmd_set_tgt_priv_lock); - -#ifdef DEBUG -EXPORT_SYMBOL(scst_random); -#endif - -module_init(init_scst); -module_exit(exit_scst); - -MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SCSI target core"); -MODULE_VERSION(SCST_VERSION_STRING); Copied: trunk/scst/src/scst_main.c (from rev 159, trunk/scst/src/scst.c) =================================================================== --- trunk/scst/src/scst_main.c (rev 0) +++ trunk/scst/src/scst_main.c 2007-08-16 09:04:05 UTC (rev 164) @@ -0,0 +1,1714 @@ +/* + * scst.c + * + * Copyright (C) 2004-2007 Vladislav Bolkhovitin <vs...@vl...> + * and Leonid Stoljar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <asm/unistd.h> +#include <asm/string.h> +#include <linux/kthread.h> + +#include "scsi_tgt.h" +#include "scst_priv.h" +#include "scst_mem.h" + +#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) +#warning HIGHMEM kernel configurations are fully supported, but not \ + recommended for performance reasons. Consider change VMSPLIT \ + option or use 64-bit configuration instead. See README file for \ + details. +#endif + +#ifdef SCST_HIGHMEM +#error SCST_HIGHMEM configuration isn't supported and broken, because there \ + is no real point to support it, at least it definitely doesn't worth \ + the effort. Better use no-HIGHMEM kernel with VMSPLIT option \ + or in 64-bit configuration instead. See README file for details. +#endif + +#if !defined(SCSI_EXEC_REQ_FIFO_DEFINED) && !defined(STRICT_SERIALIZING) +#warning Patch scst_exec_req_fifo.patch was not applied on your kernel and \ + STRICT_SERIALIZING isn't defined. Pass-through dev handlers will \ + not be supported. +#endif + +/* + * All targets, devices and dev_types management is done under this mutex. + * + * It must NOT be used in any works (schedule_work(), etc.), because + * otherwise a deadlock (double lock, actually) is possible, e.g., with + * scst_user detach_tgt(), which is called under scst_mutex and calls + * flush_scheduled_work(). + */ +DEFINE_MUTEX(scst_mutex); + +LIST_HEAD(scst_template_list); +LIST_HEAD(scst_dev_list); +LIST_HEAD(scst_dev_type_list); + +spinlock_t scst_main_lock = SPIN_LOCK_UNLOCKED; + +struct kmem_cache *scst_mgmt_cachep; +mempool_t *scst_mgmt_mempool; +struct kmem_cache *scst_ua_cachep; +mempool_t *scst_ua_mempool; +struct kmem_cache *scst_tgtd_cachep; +struct kmem_cache *scst_sess_cachep; +struct kmem_cache *scst_acgd_cachep; + +LIST_HEAD(scst_acg_list); +struct scst_acg *scst_default_acg; + +spinlock_t scst_init_lock = SPIN_LOCK_UNLOCKED; +DECLARE_WAIT_QUEUE_HEAD(scst_init_cmd_list_waitQ); +LIST_HEAD(scst_init_cmd_list); +unsigned int scst_init_poll_cnt; + +struct kmem_cache *scst_cmd_cachep; + +#if defined(DEBUG) || defined(TRACING) +unsigned long scst_trace_flag = SCST_DEFAULT_LOG_FLAGS; +#endif + +unsigned long scst_flags; +atomic_t scst_cmd_count = ATOMIC_INIT(0); + +spinlock_t scst_cmd_mem_lock = SPIN_LOCK_UNLOCKED; +unsigned long scst_cur_cmd_mem, scst_cur_max_cmd_mem; +unsigned long scst_max_cmd_mem; + +struct scst_sgv_pools scst_sgv; + +struct scst_cmd_lists scst_main_cmd_lists; + +struct scst_tasklet scst_tasklets[NR_CPUS]; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +DECLARE_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn, 0); +#else +DECLARE_DELAYED_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn); +#endif + +spinlock_t scst_mcmd_lock = SPIN_LOCK_UNLOCKED; +LIST_HEAD(scst_active_mgmt_cmd_list); +LIST_HEAD(scst_delayed_mgmt_cmd_list); +DECLARE_WAIT_QUEUE_HEAD(scst_mgmt_cmd_list_waitQ); + +DECLARE_WAIT_QUEUE_HEAD(scst_mgmt_waitQ); +spinlock_t scst_mgmt_lock = SPIN_LOCK_UNLOCKED; +LIST_HEAD(scst_sess_init_list); +LIST_HEAD(scst_sess_shut_list); + +DECLARE_WAIT_QUEUE_HEAD(scst_dev_cmd_waitQ); + +DEFINE_MUTEX(scst_suspend_mutex); +LIST_HEAD(scst_cmd_lists_list); /* protected by scst_suspend_mutex */ + +static int scst_threads; +struct scst_threads_info_t scst_threads_info; + +static int suspend_count; + +int scst_virt_dev_last_id = 1; /* protected by scst_mutex */ + +/* + * This buffer and lock are intended to avoid memory allocation, which + * could fail in improper places. + */ +spinlock_t scst_temp_UA_lock = SPIN_LOCK_UNLOCKED; +uint8_t scst_temp_UA[SCST_SENSE_BUFFERSIZE]; + +module_param_named(scst_threads, scst_threads, int, 0); +MODULE_PARM_DESC(scst_threads, "SCSI target threads count"); + +module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, long, 0); +MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by " + "the SCST commands at any given time in Mb"); + +int scst_register_target_template(struct scst_tgt_template *vtt) +{ + int res = 0; + struct scst_tgt_template *t; + static DEFINE_MUTEX(m); + + TRACE_ENTRY(); + + INIT_LIST_HEAD(&vtt->tgt_list); + + if (!vtt->detect) { + PRINT_ERROR_PR("Target driver %s doesn't have a " + "detect() method.", vtt->name); + res = -EINVAL; + goto out_err; + } + + if (!vtt->release) { + PRINT_ERROR_PR("Target driver %s doesn't have a " + "release() method.", vtt->name); + res = -EINVAL; + goto out_err; + } + + if (!vtt->xmit_response) { + PRINT_ERROR_PR("Target driver %s doesn't have a " + "xmit_response() method.", vtt->name); + res = -EINVAL; + goto out_err; + } + + if (vtt->threads_num < 0) { + PRINT_ERROR_PR("Wrong threads_num value %d for " + "target \"%s\"", vtt->threads_num, + vtt->name); + res = -EINVAL; + goto out_err; + } + + if (!vtt->no_proc_entry) { + res = scst_build_proc_target_dir_entries(vtt); + if (res < 0) + goto out_err; + } + + if (vtt->preprocessing_done == NULL) + vtt->preprocessing_done_atomic = 1; + + if (mutex_lock_interruptible(&m) != 0) + goto out_err; + + if (mutex_lock_interruptible(&scst_mutex) != 0) + goto out_m_up; + list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { + if (strcmp(t->name, vtt->name) == 0) { + PRINT_ERROR_PR("Target driver %s already registered", + vtt->name); + mutex_unlock(&scst_mutex); + goto out_cleanup; + } + } + mutex_unlock(&scst_mutex); + + TRACE_DBG("%s", "Calling target driver's detect()"); + res = vtt->detect(vtt); + TRACE_DBG("Target driver's detect() returned %d", res); + if (res < 0) { + PRINT_ERROR_PR("%s", "The detect() routine failed"); + res = -EINVAL; + goto out_cleanup; + } + + mutex_lock(&scst_mutex); + list_add_tail(&vtt->scst_template_list_entry, &scst_template_list); + mutex_unlock(&scst_mutex); + + res = 0; + + PRINT_INFO_PR("Target template %s registered successfully", vtt->name); + + mutex_unlock(&m); + +out: + TRACE_EXIT_RES(res); + return res; + +out_m_up: + mutex_unlock(&m); + +out_cleanup: + scst_cleanup_proc_target_dir_entries(vtt); + +out_err: + PRINT_ERROR_PR("Failed to register target template %s", vtt->name); + goto out; +} + +void scst_unregister_target_template(struct scst_tgt_template *vtt) +{ + struct scst_tgt *tgt; + struct scst_tgt_template *t; + int found = 0; + + TRACE_ENTRY(); + + mutex_lock(&scst_mutex); + + list_for_each_entry(t, &scst_template_list, scst_template_list_entry) { + if (strcmp(t->name, vtt->name) == 0) { + found = 1; + break; + } + } + if (!found) { + PRINT_ERROR_PR("Target driver %s isn't registered", vtt->name); + goto out_up; + } + +restart: + list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) { + mutex_unlock(&scst_mutex); + scst_unregister(tgt); + mutex_lock(&scst_mutex); + goto restart; + } + list_del(&vtt->scst_template_list_entry); + + PRINT_INFO_PR("Target template %s unregistered successfully", vtt->name); + +out_up: + mutex_unlock(&scst_mutex); + + scst_cleanup_proc_target_dir_entries(vtt); + + TRACE_EXIT(); + return; +} + +struct scst_tgt *scst_register(struct scst_tgt_template *vtt, + const char *target_name) +{ + struct scst_tgt *tgt; + + TRACE_ENTRY(); + + tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); + if (tgt == NULL) { + TRACE(TRACE_OUT_OF_MEM, "%s", "kzalloc() failed"); + goto out_err; + } + + INIT_LIST_HEAD(&tgt->sess_list); + init_waitqueue_head(&tgt->unreg_waitQ); + tgt->tgtt = vtt; + tgt->sg_tablesize = vtt->sg_tablesize; + spin_lock_init(&tgt->tgt_lock); + INIT_LIST_HEAD(&tgt->retry_cmd_list); + atomic_set(&tgt->finished_cmds, 0); + init_timer(&tgt->retry_timer); + tgt->retry_timer.data = (unsigned long)tgt; + tgt->retry_timer.function = scst_tgt_retry_timer_fn; + + scst_suspend_activity(); + mutex_lock(&scst_mutex); + + if (target_name != NULL) { + int len = strlen(target_name) + 1 + + strlen(SCST_DEFAULT_ACG_NAME) + 1; + + tgt->default_group_name = kmalloc(len, GFP_KERNEL); + if (tgt->default_group_name == NULL) { + TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of default " + "group name failed"); + goto out_free_err; + } + sprintf(tgt->default_group_name, "%s_%s", SCST_DEFAULT_ACG_NAME, + target_name); + } + + if (scst_build_proc_target_entries(tgt) < 0) + goto out_free_name; + else + list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list); + + mutex_unlock(&scst_mutex); + scst_resume_activity(); + + PRINT_INFO_PR("Target %s for template %s registered successfully", + target_name, vtt->name); + +out: + TRACE_EXIT(); + return tgt; + +out_free_name: + if (tgt->default_group_name) + kfree(tgt->default_group_name); + +out_free_err: + mutex_unlock(&scst_mutex); + scst_resume_activity(); + + kfree(tgt); + tgt = NULL; + +out_err: + PRINT_ERROR_PR("Failed to register target for template %s", vtt->name); + goto out; +} + +static inline int test_sess_list(struct scst_tgt *tgt) +{ + int res; + mutex_lock(&scst_mutex); + res = list_empty(&tgt->sess_list); + mutex_unlock(&scst_mutex); + return res; +} + +void scst_unregister(struct scst_tgt *tgt) +{ + struct scst_session *sess; + struct scst_tgt_template *vtt = tgt->tgtt; + + TRACE_ENTRY(); + + TRACE_DBG("%s", "Calling target driver's release()"); + tgt->tgtt->release(tgt); + TRACE_DBG("%s", "Target driver's release() returned"); + + mutex_lock(&scst_mutex); + list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { + sBUG_ON(sess->shut_phase == SCST_SESS_SPH_READY); + } + mutex_unlock(&scst_mutex); + + TRACE_DBG("%s", "Waiting for sessions shutdown"); + wait_event(tgt->unreg_waitQ, test_sess_list(tgt)); + TRACE_DBG("%s", "wait_event() returned"); + + scst_suspend_activity(); + mutex_lock(&scst_mutex); + + list_del(&tgt->tgt_list_entry); + + scst_cleanup_proc_target_entries(tgt); + + if (tgt->default_group_name) + kfree(tgt->default_group_name); + + mutex_unlock(&scst_mutex); + scst_resume_activity(); + + del_timer_sync(&tgt->retry_timer); + + kfree(tgt); + + PRINT_INFO_PR("Target for template %s unregistered successfully", + vtt->name); + + TRACE_EXIT(); + return; +} + +void scst_suspend_activity(void) +{ + TRACE_ENTRY(); + + mutex_lock(&scst_suspend_mutex); + + TRACE_MGMT_DBG("suspend_count %d", suspend_count); + suspend_count++; + if (suspend_count > 1) + goto out_up; + + set_bit(SCST_FLAG_SUSPENDING, &scst_flags); + set_bit(SCST_FLAG_SUSPENDED, &scst_flags); + smp_mb__after_set_bit(); + + TRACE_MGMT_DBG("Waiting for %d active commands to complete", + atomic_read(&scst_cmd_count)); + wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0); + TRACE_MGMT_DBG("%s", "wait_event() returned"); + + clear_bit(SCST_FLAG_SUSPENDING, &scst_flags); + smp_mb__after_clear_bit(); + + TRACE_MGMT_DBG("Waiting for %d active commands finally to complete", + atomic_read(&scst_cmd_count)); + wait_event(scst_dev_cmd_waitQ, atomic_read(&scst_cmd_count) == 0); + TRACE_MGMT_DBG("%s", "wait_event() returned"); + +out_up: + mutex_unlock(&scst_suspend_mutex); + + TRACE_EXIT(); + return; +} + +void scst_resume_activity(void) +{ + struct scst_cmd_lists *l; + + TRACE_ENTRY(); + + mutex_lock(&scst_suspend_mutex); + + TRACE_MGMT_DBG("suspend_count %d", suspend_count); + suspend_count--; + if (suspend_count > 0) + goto out_up; + + clear_bit(SCST_FLAG_SUSPENDED, &scst_flags); + smp_mb__after_clear_bit(); + + list_for_each_entry(l, &scst_cmd_lists_list, lists_list_entry) { + wake_up_all(&l->cmd_list_waitQ); + } + wake_up_all(&scst_init_cmd_list_waitQ); + + spin_lock_irq(&scst_mcmd_lock); + if (!list_empty(&scst_delayed_mgmt_cmd_list)) { + struct scst_mgmt_cmd *m; + m = list_entry(scst_delayed_mgmt_cmd_list.next, typeof(*m), + mgmt_cmd_list_entry); + TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active " + "mgmt cmd list", m); + list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list); + } + spin_unlock_irq(&scst_mcmd_lock); + wake_up_all(&scst_mgmt_cmd_list_waitQ); + +out_up: + mutex_unlock(&scst_suspend_mutex); + + TRACE_EXIT(); + return; +} + +static int scst_register_device(struct scsi_device *scsidp) +{ + int res = 0; + struct scst_device *dev; + struct scst_dev_type *dt; + + TRACE_ENTRY(); + + scst_suspend_activity(); + mutex_lock(&scst_mutex); + + res = scst_alloc_device(GFP_KERNEL, &dev); + if (res != 0) + goto out_up; + + dev->type = scsidp->type; + + dev->rq_disk = alloc_disk(1); + if (dev->rq_disk == NULL) { + res = -ENOMEM; + goto out_free_dev; + } + dev->rq_disk->major = SCST_MAJOR; + + dev->scsi_dev = scsidp; + + list_add_tail(&dev->dev_list_entry, &scst_dev_list); + + list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) { + if (dt->type == scsidp->type) { + res = scst_assign_dev_handler(dev, dt); + if (res != 0) + goto out_free; + break; + } + } + +out_up: + mutex_unlock(&scst_mutex); + scst_resume_activity(); + + if (res == 0) { + PRINT_INFO_PR("Attached SCSI target mid-level at " + "scsi%d, channel %d, id %d, lun %d, type %d", + scsidp->host->host_no, scsidp->channel, scsidp->id, + scsidp->lun, scsidp->type); + } + else { + PRINT_ERROR_PR("Failed to attach SCSI target mid-level " + "at scsi%d, channel %d, id %d, lun %d, type %d", + scsidp->host->host_no, scsidp->channel, scsidp->id, + scsidp->lun, scsidp->type); + } + + TRACE_EXIT_RES(res); + return res; + +out_free: + list_del(&dev->dev_list_entry); + put_disk(dev->rq_disk); + +out_free_dev: + scst_free_device(dev); + goto out_up; +} + +static void scst_unregister_device(struct scsi_device *scsidp) +{ + struct scst_device *d, *dev = NULL; + struct scst_acg_dev *acg_dev, *aa; + + TRACE_ENTRY(); + + scst_suspend_activity(); + mutex_lock(&scst_mutex); + + list_for_each_entry(d, &scst_dev_list, dev_list_entry) { + if (d->scsi_dev == scsidp) { + dev = d; + TRACE_DBG("Target device %p found", dev); + break; + } + } + if (dev ==... [truncated message content] |
From: <vl...@us...> - 2007-08-24 16:54:55
|
Revision: 170 http://scst.svn.sourceforge.net/scst/?rev=170&view=rev Author: vlnb Date: 2007-08-24 09:54:19 -0700 (Fri, 24 Aug 2007) Log Message: ----------- - Calling pre_exec() moved to the separate state - Minor cleanups Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-08-24 16:40:56 UTC (rev 169) +++ trunk/scst/include/scsi_tgt.h 2007-08-24 16:54:19 UTC (rev 170) @@ -66,23 +66,26 @@ /* Waiting for data from the initiator (until scst_rx_data() called) */ #define SCST_CMD_STATE_DATA_WAIT 8 +/* Target driver's pre_exec() is going to be called */ +#define SCST_CMD_STATE_PRE_EXEC 9 + /* CDB is going to be sent to SCSI mid-level for execution */ -#define SCST_CMD_STATE_SEND_TO_MIDLEV 9 +#define SCST_CMD_STATE_SEND_TO_MIDLEV 10 /* Waiting for CDB's execution finish */ -#define SCST_CMD_STATE_EXECUTING 10 +#define SCST_CMD_STATE_EXECUTING 11 /* Dev handler's dev_done() is going to be called */ -#define SCST_CMD_STATE_DEV_DONE 11 +#define SCST_CMD_STATE_DEV_DONE 12 /* Target driver's xmit_response() is going to be called */ -#define SCST_CMD_STATE_XMIT_RESP 12 +#define SCST_CMD_STATE_XMIT_RESP 13 /* Waiting for response's transmission finish */ -#define SCST_CMD_STATE_XMIT_WAIT 13 +#define SCST_CMD_STATE_XMIT_WAIT 14 /* The cmd finished */ -#define SCST_CMD_STATE_FINISHED 14 +#define SCST_CMD_STATE_FINISHED 15 /************************************************************* ** Can be retuned instead of cmd's state by dev handlers' Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-08-24 16:40:56 UTC (rev 169) +++ trunk/scst/src/scst_lib.c 2007-08-24 16:54:19 UTC (rev 170) @@ -2636,7 +2636,6 @@ void __scst_block_dev(struct scst_device *dev) { dev->block_count++; - smp_mb(); TRACE_MGMT_DBG("Device BLOCK(new %d), dev %p", dev->block_count, dev); } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-08-24 16:40:56 UTC (rev 169) +++ trunk/scst/src/scst_targ.c 2007-08-24 16:54:19 UTC (rev 170) @@ -452,6 +452,7 @@ case SCST_CMD_STATE_PREPARE_SPACE: case SCST_CMD_STATE_DEV_PARSE: case SCST_CMD_STATE_RDY_TO_XFER: + case SCST_CMD_STATE_PRE_EXEC: case SCST_CMD_STATE_SEND_TO_MIDLEV: case SCST_CMD_STATE_DEV_DONE: case SCST_CMD_STATE_XMIT_RESP: @@ -677,7 +678,7 @@ break; default: - cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV; + cmd->state = SCST_CMD_STATE_PRE_EXEC; break; } @@ -726,7 +727,7 @@ cmd->state = SCST_CMD_STATE_RDY_TO_XFER; break; default: - cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV; + cmd->state = SCST_CMD_STATE_PRE_EXEC; break; } if (cmd->no_sn) @@ -826,7 +827,7 @@ } if (cmd->tgtt->rdy_to_xfer == NULL) { - cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV; + cmd->state = SCST_CMD_STATE_PRE_EXEC; res = SCST_CMD_STATE_RES_CONT_SAME; goto out; } @@ -971,7 +972,7 @@ switch (status) { case SCST_RX_STATUS_SUCCESS: - cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV; + cmd->state = SCST_CMD_STATE_PRE_EXEC; /* Small context optimization */ if ((pref_context == SCST_CONTEXT_TASKLET) || (pref_context == SCST_CONTEXT_DIRECT_ATOMIC)) { @@ -1007,12 +1008,17 @@ return; } -static int scst_tgt_pre_exec(struct scst_cmd *cmd, int *action) +static int scst_tgt_pre_exec(struct scst_cmd *cmd) { - int res = 0, rc; + int rc; TRACE_ENTRY(); + cmd->state = SCST_CMD_STATE_SEND_TO_MIDLEV; + + if (cmd->tgtt->pre_exec == NULL) + goto out; + TRACE_DBG("Calling pre_exec(%p)", cmd); rc = cmd->tgtt->pre_exec(cmd); TRACE_DBG("pre_exec() returned %d", rc); @@ -1021,8 +1027,6 @@ switch(rc) { case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET: cmd->state = SCST_CMD_STATE_DEV_DONE; - *action = SCST_CMD_STATE_RES_CONT_SAME; - res = -1; break; case SCST_PREPROCESS_STATUS_ERROR_FATAL: set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags); @@ -1031,8 +1035,6 @@ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); cmd->state = SCST_CMD_STATE_DEV_DONE; - *action = SCST_CMD_STATE_RES_CONT_SAME; - res = -1; break; default: sBUG(); @@ -1040,8 +1042,9 @@ } } - TRACE_EXIT_RES(res); - return res; +out: + TRACE_EXIT(); + return SCST_CMD_STATE_RES_CONT_SAME; } static void scst_inc_check_expected_sn(struct scst_cmd *cmd) @@ -1892,12 +1895,6 @@ res = SCST_CMD_STATE_RES_CONT_NEXT; - if (cmd->tgtt->pre_exec != NULL) { - rc = scst_tgt_pre_exec(cmd, &res); - if (unlikely(rc != 0)) - goto out; - } - if (unlikely(scst_inc_on_dev_cmd(cmd) != 0)) goto out; @@ -2339,12 +2336,13 @@ } switch (state) { + case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_DEV_PARSE: case SCST_CMD_STATE_PREPARE_SPACE: case SCST_CMD_STATE_RDY_TO_XFER: + case SCST_CMD_STATE_PRE_EXEC: case SCST_CMD_STATE_SEND_TO_MIDLEV: case SCST_CMD_STATE_DEV_DONE: - case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: cmd->state = state; res = SCST_CMD_STATE_RES_CONT_SAME; @@ -2908,7 +2906,10 @@ switch (cmd->state) { case SCST_CMD_STATE_DEV_PARSE: res = scst_parse_cmd(cmd); - break; + if ((res != SCST_CMD_STATE_RES_CONT_SAME) || + (cmd->state != SCST_CMD_STATE_PREPARE_SPACE)) + break; + /* else go through */ case SCST_CMD_STATE_PREPARE_SPACE: res = scst_prepare_space(cmd); @@ -2918,6 +2919,13 @@ res = scst_rdy_to_xfer(cmd); break; + case SCST_CMD_STATE_PRE_EXEC: + res = scst_tgt_pre_exec(cmd); + if ((res != SCST_CMD_STATE_RES_CONT_SAME) || + (cmd->state != SCST_CMD_STATE_SEND_TO_MIDLEV)) + break; + /* else go through */ + case SCST_CMD_STATE_SEND_TO_MIDLEV: if (tm_dbg_check_cmd(cmd) != 0) { res = SCST_CMD_STATE_RES_CONT_NEXT; @@ -2932,6 +2940,10 @@ case SCST_CMD_STATE_DEV_DONE: res = scst_dev_done(cmd); + if ((res != SCST_CMD_STATE_RES_CONT_SAME) || + (cmd->state != SCST_CMD_STATE_XMIT_RESP)) + break; + /* else go through */ break; case SCST_CMD_STATE_XMIT_RESP: @@ -2959,6 +2971,7 @@ case SCST_CMD_STATE_DEV_PARSE: case SCST_CMD_STATE_PREPARE_SPACE: case SCST_CMD_STATE_RDY_TO_XFER: + case SCST_CMD_STATE_PRE_EXEC: case SCST_CMD_STATE_SEND_TO_MIDLEV: case SCST_CMD_STATE_DEV_DONE: case SCST_CMD_STATE_XMIT_RESP: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-09-24 17:06:45
|
Revision: 190 http://scst.svn.sourceforge.net/scst/?rev=190&view=rev Author: vlnb Date: 2007-09-24 09:07:04 -0700 (Mon, 24 Sep 2007) Log Message: ----------- Fix from Jianxi Chen <pa...@us...>, which fixes problem with devices >2TB in size Modified Paths: -------------- trunk/scst/README trunk/scst/src/dev_handlers/scst_vdisk.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-09-19 09:19:29 UTC (rev 189) +++ trunk/scst/README 2007-09-24 16:07:04 UTC (rev 190) @@ -660,4 +660,7 @@ * Terry Greeniaus <tgr...@yo...> for fixes. + * Jianxi Chen <pa...@us...> for fixing problems with + devices >2TB in size + Vladislav Bolkhovitin <vs...@vl...>, http://scst.sourceforge.net Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2007-09-19 09:19:29 UTC (rev 189) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2007-09-24 16:07:04 UTC (rev 190) @@ -713,9 +713,10 @@ lba_start |= ((u64)cdb[3]) << 48; lba_start |= ((u64)cdb[4]) << 40; lba_start |= ((u64)cdb[5]) << 32; - lba_start |= ((u64)cdb[6]) << 16; - lba_start |= ((u64)cdb[7]) << 8; - lba_start |= ((u64)cdb[8]); + lba_start |= ((u64)cdb[6]) << 24; + lba_start |= ((u64)cdb[7]) << 16; + lba_start |= ((u64)cdb[8]) << 8; + lba_start |= ((u64)cdb[9]); data_len = cmd->bufflen; break; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-09-25 09:11:11
|
Revision: 191 http://scst.svn.sourceforge.net/scst/?rev=191&view=rev Author: vlnb Date: 2007-09-25 02:11:08 -0700 (Tue, 25 Sep 2007) Log Message: ----------- - Patch from Krzysztof Blaszkowski: move SGV cache /proc support in the scst_mem.c - Minor doc fix Modified Paths: -------------- trunk/scst/README trunk/scst/src/scst_mem.c trunk/scst/src/scst_mem.h trunk/scst/src/scst_proc.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-09-24 16:07:04 UTC (rev 190) +++ trunk/scst/README 2007-09-25 09:11:08 UTC (rev 191) @@ -660,7 +660,7 @@ * Terry Greeniaus <tgr...@yo...> for fixes. - * Jianxi Chen <pa...@us...> for fixing problems with + * Jianxi Chen <pa...@us...> for fixing problem with devices >2TB in size Vladislav Bolkhovitin <vs...@vl...>, http://scst.sourceforge.net Modified: trunk/scst/src/scst_mem.c =================================================================== --- trunk/scst/src/scst_mem.c 2007-09-24 16:07:04 UTC (rev 190) +++ trunk/scst/src/scst_mem.c 2007-09-25 09:11:08 UTC (rev 191) @@ -62,11 +62,10 @@ static int sgv_max_local_order, sgv_max_trans_order; -atomic_t sgv_other_total_alloc; +static atomic_t sgv_other_total_alloc; +static DEFINE_MUTEX(scst_sgv_pool_mutex); +static LIST_HEAD(scst_sgv_pool_list); -DEFINE_MUTEX(scst_sgv_pool_mutex); -LIST_HEAD(scst_sgv_pool_list); - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) static void sgv_dtor(void *data, struct kmem_cache *k, unsigned long f); #endif @@ -817,3 +816,43 @@ TRACE_EXIT(); return; } + +static void scst_do_sgv_read(struct seq_file *seq, const struct sgv_pool *pool) +{ + int i; + + seq_printf(seq, "\n%-30s %-11d %-11d\n", pool->name, + atomic_read(&pool->acc.hit_alloc), + atomic_read(&pool->acc.total_alloc)); + + for (i = 0; i < SGV_POOL_ELEMENTS; i++) { + seq_printf(seq, " %-28s %-11d %-11d\n", pool->cache_names[i], + atomic_read(&pool->cache_acc[i].hit_alloc), + atomic_read(&pool->cache_acc[i].total_alloc)); + } + + seq_printf(seq, " %-28s %-11d %-11d\n", "big/other", atomic_read(&pool->big_alloc), + atomic_read(&pool->other_alloc)); + + return; +} + +int sgv_pool_procinfo_show(struct seq_file *seq, void *v) +{ + struct sgv_pool *pool; + + TRACE_ENTRY(); + + seq_printf(seq, "%-30s %-11s %-11s", "Name", "Hit", "Total"); + + mutex_lock(&scst_sgv_pool_mutex); + list_for_each_entry(pool, &scst_sgv_pool_list, sgv_pool_list_entry) { + scst_do_sgv_read(seq, pool); + } + mutex_unlock(&scst_sgv_pool_mutex); + + seq_printf(seq, "\n%-42s %-11d\n", "other", atomic_read(&sgv_other_total_alloc)); + + TRACE_EXIT(); + return 0; +} Modified: trunk/scst/src/scst_mem.h =================================================================== --- trunk/scst/src/scst_mem.h 2007-09-24 16:07:04 UTC (rev 190) +++ trunk/scst/src/scst_mem.h 2007-09-25 09:11:08 UTC (rev 191) @@ -15,6 +15,7 @@ */ #include <asm/scatterlist.h> +#include <linux/seq_file.h> #define SGV_POOL_ELEMENTS 11 @@ -85,9 +86,6 @@ #endif }; -extern atomic_t sgv_other_total_alloc; -extern struct mutex scst_sgv_pool_mutex; -extern struct list_head scst_sgv_pool_list; int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered); @@ -100,3 +98,5 @@ extern int scst_sgv_pools_init(struct scst_sgv_pools *pools); extern void scst_sgv_pools_deinit(struct scst_sgv_pools *pools); +extern int sgv_pool_procinfo_show(struct seq_file *seq, void *v); + Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2007-09-24 16:07:04 UTC (rev 190) +++ trunk/scst/src/scst_proc.c 2007-09-25 09:11:08 UTC (rev 191) @@ -1719,49 +1719,10 @@ .show = scst_sessions_info_show, }; -static void scst_do_sgv_read(struct seq_file *seq, const struct sgv_pool *pool) -{ - int i; - seq_printf(seq, "\n%-30s %-11d %-11d\n", pool->name, - atomic_read(&pool->acc.hit_alloc), - atomic_read(&pool->acc.total_alloc)); - - for (i = 0; i < SGV_POOL_ELEMENTS; i++) { - seq_printf(seq, " %-28s %-11d %-11d\n", pool->cache_names[i], - atomic_read(&pool->cache_acc[i].hit_alloc), - atomic_read(&pool->cache_acc[i].total_alloc)); - } - - seq_printf(seq, " %-28s %-11d %-11d\n", "big/other", atomic_read(&pool->big_alloc), - atomic_read(&pool->other_alloc)); - - return; -} - -static int scst_sgv_info_show(struct seq_file *seq, void *v) -{ - struct sgv_pool *pool; - - TRACE_ENTRY(); - - seq_printf(seq, "%-30s %-11s %-11s", "Name", "Hit", "Total"); - - mutex_lock(&scst_sgv_pool_mutex); - list_for_each_entry(pool, &scst_sgv_pool_list, sgv_pool_list_entry) { - scst_do_sgv_read(seq, pool); - } - mutex_unlock(&scst_sgv_pool_mutex); - - seq_printf(seq, "\n%-42s %-11d\n", "other", atomic_read(&sgv_other_total_alloc)); - - TRACE_EXIT(); - return 0; -} - static struct scst_proc_data scst_sgv_proc_data = { SCST_DEF_RW_SEQ_OP(NULL) - .show = scst_sgv_info_show, + .show = sgv_pool_procinfo_show, }; static int scst_groups_names_show(struct seq_file *seq, void *v) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-09-25 09:17:18
|
Revision: 192 http://scst.svn.sourceforge.net/scst/?rev=192&view=rev Author: vlnb Date: 2007-09-25 02:17:16 -0700 (Tue, 25 Sep 2007) Log Message: ----------- - Patch from Krzysztof Blaszkowski <kb...@sy...> with cosmetic cleanups by me. It implements new SGV cache low memory management backend with memory flow control facility - Version changed to -pre3 Modified Paths: -------------- trunk/scst/ChangeLog trunk/scst/README trunk/scst/src/scst_lib.c trunk/scst/src/scst_main.c trunk/scst/src/scst_mem.c trunk/scst/src/scst_mem.h trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/ChangeLog =================================================================== --- trunk/scst/ChangeLog 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/ChangeLog 2007-09-25 09:17:16 UTC (rev 192) @@ -1,6 +1,9 @@ Summary of changes between versions 0.9.5 and 0.9.6 --------------------------------------------------- + - New SGV cache low memory management backend with memory flow control + facility was implemented, thanks to Krzysztof Blaszkowski. + - FILEIO was renamed to VDISK. BLOCKIO added to it, thanks to Ross S. W. Walker and Vu Pham. Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/README 2007-09-25 09:17:16 UTC (rev 192) @@ -660,6 +660,8 @@ * Terry Greeniaus <tgr...@yo...> for fixes. + * Krzysztof Blaszkowski <kb...@sy...> for many fixes and bug reports. + * Jianxi Chen <pa...@us...> for fixing problem with devices >2TB in size Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_lib.c 2007-09-25 09:17:16 UTC (rev 192) @@ -359,8 +359,8 @@ tgt_dev->sess = sess; atomic_set(&tgt_dev->tgt_dev_cmd_count, 0); - tgt_dev->gfp_mask = __GFP_NOWARN; - tgt_dev->pool = &scst_sgv.norm; + + scst_sgv_pool_use_norm(tgt_dev); if (dev->scsi_dev != NULL) { ini_sg = dev->scsi_dev->host->sg_tablesize; @@ -376,18 +376,14 @@ if ((sess->tgt->tgtt->use_clustering || ini_use_clustering) && !sess->tgt->tgtt->no_clustering) { - TRACE_MEM("%s", "Use clustering"); - tgt_dev->pool = &scst_sgv.norm_clust; + scst_sgv_pool_use_norm_clust(tgt_dev); } if (sess->tgt->tgtt->unchecked_isa_dma || ini_unchecked_isa_dma) { - TRACE_MEM("%s", "Use ISA DMA memory"); - tgt_dev->gfp_mask |= GFP_DMA; - tgt_dev->pool = &scst_sgv.dma; + scst_sgv_pool_use_dma(tgt_dev); } else { #ifdef SCST_HIGHMEM - gfp_mask |= __GFP_HIGHMEM; - tgt_dev->pool = &scst_sgv.highmem; + scst_sgv_pool_use_highmem(tgt_dev); #endif } Modified: trunk/scst/src/scst_main.c =================================================================== --- trunk/scst/src/scst_main.c 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_main.c 2007-09-25 09:17:16 UTC (rev 192) @@ -97,17 +97,10 @@ unsigned long scst_cur_cmd_mem, scst_cur_max_cmd_mem; unsigned long scst_max_cmd_mem; -struct scst_sgv_pools scst_sgv; - struct scst_cmd_lists scst_main_cmd_lists; struct scst_tasklet scst_tasklets[NR_CPUS]; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -DECLARE_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn, 0); -#else -DECLARE_DELAYED_WORK(scst_cmd_mem_work, scst_cmd_mem_work_fn); -#endif spinlock_t scst_mcmd_lock = SPIN_LOCK_UNLOCKED; LIST_HEAD(scst_active_mgmt_cmd_list); @@ -1451,7 +1444,19 @@ goto out_destroy_mgmt_mempool; } - res = scst_sgv_pools_init(&scst_sgv); + if (scst_max_cmd_mem == 0) { + struct sysinfo si; + si_meminfo(&si); +#if BITS_PER_LONG == 32 + scst_max_cmd_mem = min(((uint64_t)si.totalram << PAGE_SHIFT) >> 2, + (uint64_t)1 << 30); +#else + scst_max_cmd_mem = (si.totalram << PAGE_SHIFT) >> 2; +#endif + } else + scst_max_cmd_mem <<= 20; + + res = scst_sgv_pools_init(scst_max_cmd_mem, 0); if (res != 0) goto out_destroy_ua_mempool; @@ -1485,20 +1490,7 @@ if (res != 0) goto out_thread_free; - if (scst_max_cmd_mem == 0) { - struct sysinfo si; - si_meminfo(&si); -#if BITS_PER_LONG == 32 - scst_max_cmd_mem = min(((uint64_t)si.totalram << PAGE_SHIFT) >> 2, - (uint64_t)1 << 30); -#else - scst_max_cmd_mem = (si.totalram << PAGE_SHIFT) >> 2; -#endif - } else - scst_max_cmd_mem <<= 20; - scst_cur_max_cmd_mem = scst_max_cmd_mem; - PRINT_INFO_PR("SCST version %s loaded successfully (max mem for " "commands %ld Mb)", SCST_VERSION_STRING, scst_max_cmd_mem >> 20); @@ -1515,7 +1507,7 @@ scst_destroy_acg(scst_default_acg); out_destroy_sgv_pool: - scst_sgv_pools_deinit(&scst_sgv); + scst_sgv_pools_deinit(); out_destroy_ua_mempool: mempool_destroy(scst_ua_mempool); @@ -1554,11 +1546,6 @@ /* ToDo: unregister_cpu_notifier() */ - if (test_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags)) { - cancel_delayed_work(&scst_cmd_mem_work); - flush_scheduled_work(); - } - scst_proc_cleanup_module(); scst_stop_all_threads(); @@ -1566,7 +1553,7 @@ scsi_unregister_interface(&scst_interface); scst_destroy_acg(scst_default_acg); - scst_sgv_pools_deinit(&scst_sgv); + scst_sgv_pools_deinit(); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) #define DEINIT_CACHEP(p, s) do { \ @@ -1656,7 +1643,6 @@ EXPORT_SYMBOL(scst_single_seq_open); EXPORT_SYMBOL(__scst_get_buf); -EXPORT_SYMBOL(scst_check_mem); EXPORT_SYMBOL(scst_get); EXPORT_SYMBOL(scst_put); Modified: trunk/scst/src/scst_mem.c =================================================================== --- trunk/scst/src/scst_mem.c 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_mem.c 2007-09-25 09:17:16 UTC (rev 192) @@ -2,6 +2,8 @@ * scst_mem.c * * Copyright (C) 2006-2007 Vladislav Bolkhovitin <vs...@vl...> + * Copyright (C) 2007 Krzysztof Blaszkowski <kb...@sy...> + * Copyright (C) 2007 CMS Distribution Limited * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,26 +35,10 @@ #include "scst_priv.h" #include "scst_mem.h" -/* - * This implementation of sgv_pool is not the best, because the SLABs could get - * fragmented and too much undesirable memory could be kept, plus - * under memory pressure the cached objects could be purged too quickly. - * From other side it's simple, works well, and doesn't require any modifications - * of the existing SLAB code. - */ +#define PURGE_INTERVAL (15 * HZ) +#define PURGE_TIME_AFTER (15 * HZ) +#define SHRINK_TIME_AFTER (1 * HZ) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#warning SCST on 2.6.22+ kernels will run in performance degraded mode, \ -because some unresponsible mainline kernel developers have deleted in those \ -kernels support for destructors in SLAB cache and made that change without \ -even set that feature in the deprecated status for some time to allow \ -depending on it projects to fix themself without disturbing their users. \ -Blame those people for that! So, now to run in full power on those kernels \ -SCST requires a complete rewrite of one of its major low level parts: all \ -kmem_cache_*() functions in this file should be replaced with new ones with \ -similar functionality. -#endif - /* Chosen to have one page per slab for all orders */ #ifdef CONFIG_DEBUG_SLAB #define SGV_MAX_LOCAL_SLAB_ORDER 4 @@ -60,14 +46,35 @@ #define SGV_MAX_LOCAL_SLAB_ORDER 5 #endif -static int sgv_max_local_order, sgv_max_trans_order; +static struct scst_sgv_pools_manager sgv_pools_mgr; -static atomic_t sgv_other_total_alloc; -static DEFINE_MUTEX(scst_sgv_pool_mutex); -static LIST_HEAD(scst_sgv_pool_list); +void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev) +{ + tgt_dev->gfp_mask = __GFP_NOWARN; + tgt_dev->pool = &sgv_pools_mgr.default_set.norm; +} -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -static void sgv_dtor(void *data, struct kmem_cache *k, unsigned long f); +void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev) +{ + TRACE_MEM("%s", "Use clustering"); + tgt_dev->gfp_mask = __GFP_NOWARN; + tgt_dev->pool = &sgv_pools_mgr.default_set.norm_clust; +} + +void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev) +{ + TRACE_MEM("%s", "Use ISA DMA memory"); + tgt_dev->gfp_mask = __GFP_NOWARN | GFP_DMA; + tgt_dev->pool = &sgv_pools_mgr.default_set.dma; +} + +#ifdef SCST_HIGHMEM +void scst_sgv_pool_use_highmem(struct scst_tgt_dev *tgt_dev) +{ + TRACE_MEM("%s", "Use HIGHMEM"); + tgt_dev->gfp_mask = __GFP_NOWARN | __GFP_HIGHMEM; + tgt_dev->pool = &sgv_pools_mgr.default_set.highmem; +} #endif static int scst_check_clustering(struct scatterlist *sg, int cur, int hint) @@ -106,7 +113,7 @@ } /* ToDo: implement more intelligent search */ - for (i = cur - 1; i >= 0; i--) { + for(i = cur - 1; i >= 0; i--) { pfn = page_to_pfn(sg[i].page); pfn_next = pfn + (sg[i].length >> PAGE_SHIFT); full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0; @@ -144,7 +151,7 @@ TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count); - for (i = 0; i < sg_count; i++) { + for(i = 0; i < sg_count; i++) { struct page *p = sg[i].page; int len = sg[i].length; int pages = @@ -153,7 +160,7 @@ TRACE_MEM("page %lx, len %d, pages %d", (unsigned long)p, len, pages); - while (pages > 0) { + while(pages > 0) { int order = 0; /* @@ -209,10 +216,10 @@ gfp_mask |= __GFP_ZERO; #endif - for (pg = 0; pg < pages; pg++) { + for(pg = 0; pg < pages; pg++) { void *rc; #ifdef DEBUG_OOM - if (((gfp_mask & __GFP_NOFAIL) == 0) && + if (((gfp_mask & __GFP_NOFAIL) != __GFP_NOFAIL) && ((scst_random() % 10000) == 55)) rc = NULL; else @@ -233,11 +240,11 @@ if (clustered && (trans_tbl != NULL)) { pg = 0; - for (i = 0; i < pages; i++) { + for(i = 0; i < pages; i++) { int n = (sg[i].length >> PAGE_SHIFT) + ((sg[i].length & ~PAGE_MASK) != 0); trans_tbl[i].pg_count = pg; - for (j = 0; j < n; j++) + for(j = 0; j < n; j++) trans_tbl[pg++].sg_num = i+1; TRACE_MEM("i=%d, n=%d, pg_count=%d", i, n, trans_tbl[i].pg_count); @@ -273,7 +280,7 @@ } if (obj->owner_pool->clustered) { - if (order <= sgv_max_trans_order) { + if (order <= sgv_pools_mgr.sgv_max_trans_order) { obj->trans_tbl = (struct trans_tbl_ent*)obj->sg_entries_data; /* * No need to clear trans_tbl, if needed, it will be @@ -305,6 +312,190 @@ goto out; } +static void sgv_dtor_and_free(struct sgv_pool_obj *obj) +{ + if (obj->sg_count != 0) { + obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, + obj->sg_count, obj->allocator_priv); + } + if (obj->sg_entries != obj->sg_entries_data) { + if (obj->trans_tbl != (struct trans_tbl_ent*)obj->sg_entries_data) { + /* kfree() handles NULL parameter */ + kfree(obj->trans_tbl); + obj->trans_tbl = NULL; + } + kfree(obj->sg_entries); + } + + kmem_cache_free(obj->owner_pool->caches[obj->order], obj); + return; +} + +static struct sgv_pool_obj *sgv_pool_cached_get(struct sgv_pool *pool, + int order, unsigned long gfp_mask) +{ + struct sgv_pool_obj *obj; + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + if (likely(!list_empty(&pool->recycling_lists[order]))) { + obj = list_entry(pool->recycling_lists[order].next, + struct sgv_pool_obj, + recycle_entry.recycling_list_entry); + list_del(&obj->recycle_entry.sorted_recycling_list_entry); + list_del(&obj->recycle_entry.recycling_list_entry); + sgv_pools_mgr.mgr.thr.inactive_pages_total -= 1 << order; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + EXTRACHECKS_BUG_ON(obj->order != order); + + return obj; + } + + pool->acc.cached_entries++; + pool->acc.cached_pages += (1 << order); + + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + obj = kmem_cache_alloc(pool->caches[order], + gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); + if (likely(obj)) { + memset(obj, 0, sizeof(*obj)); + obj->order = order; + obj->owner_pool = pool; + } else { + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + pool->acc.cached_entries--; + pool->acc.cached_pages -= (1 << order); + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + } + + return obj; +} + +static void sgv_pool_cached_put(struct sgv_pool_obj *sgv) +{ + struct sgv_pool *owner = sgv->owner_pool; + int sched = 0; + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + list_add(&sgv->recycle_entry.recycling_list_entry, + &owner->recycling_lists[sgv->order]); + list_add_tail(&sgv->recycle_entry.sorted_recycling_list_entry, + &sgv_pools_mgr.mgr.sorted_recycling_list); + sgv->recycle_entry.time_stamp = jiffies; + + sgv_pools_mgr.mgr.thr.inactive_pages_total += 1 << sgv->order; + if (!sgv_pools_mgr.mgr.pitbool_running) { + sgv_pools_mgr.mgr.pitbool_running = 1; + sched = 1; + } + + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + if (sched) + schedule_delayed_work(&sgv_pools_mgr.mgr.apit_pool, + PURGE_INTERVAL); +} + +/* Must be called under pool_mgr_lock held */ +static void __sgv_pool_cached_purge(struct sgv_pool_obj *e) +{ + int pages = 1 << e->order; + + list_del(&e->recycle_entry.sorted_recycling_list_entry); + list_del(&e->recycle_entry.recycling_list_entry); + e->owner_pool->acc.cached_entries--; + e->owner_pool->acc.cached_pages -= pages; + sgv_pools_mgr.mgr.thr.inactive_pages_total -= pages; + + return; +} + +/* Must be called under pool_mgr_lock held */ +static int sgv_pool_cached_purge(struct sgv_pool_obj *e, int t, + unsigned long rt) +{ + EXTRACHECKS_BUG_ON(t == 0); + EXTRACHECKS_BUG_ON(rt == 0); + + if (time_after(rt, (e->recycle_entry.time_stamp + t))) { + __sgv_pool_cached_purge(e); + return 0; + } + return 1; +} + +/* Called under pool_mgr_lock held, but drops/reaquire it inside */ +static int sgv_pool_oom_free_objs(int pgs) +{ + TRACE_MEM("Shrinking pools about %d pages", pgs); + while((sgv_pools_mgr.mgr.thr.inactive_pages_total > + sgv_pools_mgr.mgr.thr.lo_wmk) && + (pgs > 0)) { + struct sgv_pool_obj *e; + + sBUG_ON(list_empty(&sgv_pools_mgr.mgr.sorted_recycling_list)); + + e = list_entry(sgv_pools_mgr.mgr.sorted_recycling_list.next, + struct sgv_pool_obj, + recycle_entry.sorted_recycling_list_entry); + + __sgv_pool_cached_purge(e); + pgs -= 1 << e->order; + + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_dtor_and_free(e); + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + } + + TRACE_MEM("Pages remaining %d ", pgs); + return pgs; +} + +static int sgv_pool_hiwmk_check(int pages_to_alloc, int no_fail) +{ + int res = 0; + int pages = pages_to_alloc; + + if (unlikely(no_fail)) + goto out; + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + pages += sgv_pools_mgr.mgr.thr.active_pages_total; + pages += sgv_pools_mgr.mgr.thr.inactive_pages_total; + + if (unlikely((u32)pages > sgv_pools_mgr.mgr.thr.hi_wmk)) { + pages -= sgv_pools_mgr.mgr.thr.hi_wmk; + sgv_pools_mgr.mgr.thr.releases_on_hiwmk++; + + pages = sgv_pool_oom_free_objs(pages); + if (pages > 0) { + static int q; + if (q < 100) { + q++; + TRACE(TRACE_OUT_OF_MEM, "Requested amount of " + "memory for being executed commands " + "exceeds allowed maximum %dMB, " + "should you increase scst_max_cmd_mem " + "(requested %d pages)? (This message " + "will be shown only the first 100 " + "times)", sgv_pools_mgr.mgr.thr.hi_wmk >> + (20-PAGE_SHIFT), pages_to_alloc); + } + sgv_pools_mgr.mgr.thr.releases_failed++; + res = -ENOMEM; + goto out_unlock; + } + } + +out_unlock: + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + +out: + return res; +} + struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, unsigned long gfp_mask, int flags, int *count, struct sgv_pool_obj **sgv, void *priv) @@ -315,10 +506,11 @@ int pages_to_alloc; struct kmem_cache *cache; int no_cached = flags & SCST_POOL_ALLOC_NO_CACHED; + int no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL); sBUG_ON(size == 0); - pages = (size >> PAGE_SHIFT) + ((size & ~PAGE_MASK) != 0); + pages = ((size + PAGE_SIZE - 1) >> PAGE_SHIFT); order = get_order(size); TRACE_MEM("size=%d, pages=%d, order=%d, flags=%x, *sgv %p", size, pages, @@ -326,18 +518,22 @@ if (*sgv != NULL) { obj = *sgv; - TRACE_MEM("Supplied sgv_obj %p", obj); + + TRACE_MEM("Supplied sgv_obj %p, sgv_order %d", obj, obj->order); + EXTRACHECKS_BUG_ON(obj->order != order); + EXTRACHECKS_BUG_ON(obj->sg_count != 0); pages_to_alloc = (1 << order); - cache = obj->owner_cache; - EXTRACHECKS_BUG_ON(cache != pool->caches[order]); - EXTRACHECKS_BUG_ON(obj->sg_count != 0); - goto alloc; - } - - if ((order < SGV_POOL_ELEMENTS) && !no_cached) { + cache = pool->caches[obj->order]; + if (sgv_pool_hiwmk_check(pages_to_alloc, no_fail) != 0) { + obj->sg_count = 0; + if ((flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL)) + goto out_return1; + else + goto out_fail_free_sg_entries; + } + } else if ((order < SGV_POOL_ELEMENTS) && !no_cached) { cache = pool->caches[order]; - obj = kmem_cache_alloc(cache, - gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); + obj = sgv_pool_cached_get(pool, order, gfp_mask); if (unlikely(obj == NULL)) { TRACE(TRACE_OUT_OF_MEM, "Allocation of " "sgv_pool_obj failed (size %d)", size); @@ -345,7 +541,7 @@ } if (obj->sg_count != 0) { TRACE_MEM("Cached sgv_obj %p", obj); - EXTRACHECKS_BUG_ON(obj->owner_cache != cache); + EXTRACHECKS_BUG_ON(obj->order != order); atomic_inc(&pool->acc.hit_alloc); atomic_inc(&pool->cache_acc[order].hit_alloc); goto success; @@ -356,9 +552,7 @@ goto out_fail_free; } TRACE_MEM("Brand new sgv_obj %p", obj); - obj->owner_cache = cache; - obj->owner_pool = pool; - if (order <= sgv_max_local_order) { + if (order <= sgv_pools_mgr.sgv_max_local_order) { obj->sg_entries = obj->sg_entries_data; TRACE_MEM("sg_entries %p", obj->sg_entries); memset(obj->sg_entries, 0, @@ -388,6 +582,15 @@ if ((flags & SCST_POOL_NO_ALLOC_ON_CACHE_MISS) && (flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL)) goto out_return; + + obj->allocator_priv = priv; + if (sgv_pool_hiwmk_check(pages_to_alloc, no_fail) != 0) { + obj->sg_count = 0; + if ((flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL)) + goto out_return1; + else + goto out_fail_free_sg_entries; + } } else { int sz; pages_to_alloc = pages; @@ -402,13 +605,17 @@ goto out_fail; } obj->owner_pool = pool; + obj->order = -1 - order; obj->sg_entries = obj->sg_entries_data; - TRACE_MEM("Big or no_cached sgv_obj %p (size %d)", obj, sz); + obj->allocator_priv = priv; + + if (sgv_pool_hiwmk_check(pages_to_alloc, no_fail) != 0) { + obj->sg_count = 0; + goto out_fail_free_sg_entries; + } + TRACE_MEM("Big or no_cached sgv_obj %p (size %d)", obj, sz); } - obj->allocator_priv = priv; - -alloc: obj->sg_count = scst_alloc_sg_entries(obj->sg_entries, pages_to_alloc, gfp_mask, pool->clustered, obj->trans_tbl, &pool->alloc_fns, priv); @@ -422,6 +629,10 @@ success: atomic_inc(&pool->acc.total_alloc); + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_pools_mgr.mgr.thr.active_pages_total += 1 << order; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + if (cache) { int sg; atomic_inc(&pool->cache_acc[order].total_alloc); @@ -439,9 +650,9 @@ } else { cnt = obj->sg_count; if (no_cached) - atomic_inc(&pool->other_alloc); + atomic_inc(&pool->acc.other_alloc); else - atomic_inc(&pool->big_alloc); + atomic_inc(&pool->acc.big_alloc); } *count = cnt; @@ -483,12 +694,9 @@ } out_fail_free: - if (cache) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) - sgv_dtor(obj, NULL, 0); -#endif - kmem_cache_free(pool->caches[order], obj); - } else + if (cache) + sgv_pool_cached_put(obj); + else kfree(obj); out_fail: @@ -506,60 +714,27 @@ void sgv_pool_free(struct sgv_pool_obj *sgv) { - TRACE_MEM("Freeing sgv_obj %p, owner_cache %p, sg_entries %p, " - "sg_count %d, allocator_priv %p", sgv, sgv->owner_cache, + int order = sgv->order; + + TRACE_MEM("Freeing sgv_obj %p, order %d, sg_entries %p, " + "sg_count %d, allocator_priv %p", sgv, order, sgv->sg_entries, sgv->sg_count, sgv->allocator_priv); - if (sgv->owner_cache != NULL) { - struct kmem_cache *c = sgv->owner_cache; + if (order >= 0) { sgv->sg_entries[sgv->orig_sg].length = sgv->orig_length; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) - sgv_dtor(sgv, NULL, 0); -#endif - kmem_cache_free(c, sgv); + sgv_pool_cached_put(sgv); } else { sgv->owner_pool->alloc_fns.free_pages_fn(sgv->sg_entries, sgv->sg_count, sgv->allocator_priv); kfree(sgv); + order = -order - 1; } - return; -} -static void sgv_ctor(void *data, struct kmem_cache *c, unsigned long flags) -{ - struct sgv_pool_obj *obj = data; - -#ifdef SLAB_CTOR_VERIFY - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) != - SLAB_CTOR_CONSTRUCTOR) - return; -#endif - - TRACE_MEM("Constructor for sgv_obj %p", obj); - memset(obj, 0, sizeof(*obj)); + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_pools_mgr.mgr.thr.active_pages_total -= 1 << order; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); return; } -static void sgv_dtor(void *data, struct kmem_cache *k, unsigned long f) -{ - struct sgv_pool_obj *obj = data; - if (obj->sg_count != 0) { - obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, - obj->sg_count, obj->allocator_priv); - } - if (obj->sg_entries != obj->sg_entries_data) { - if (obj->trans_tbl != (struct trans_tbl_ent*)obj->sg_entries_data) { - /* kfree() handles NULL parameter */ - kfree(obj->trans_tbl); - obj->trans_tbl = NULL; - } - kfree(obj->sg_entries); - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) - memset(obj, 0, sizeof(*obj)); -#endif - return; -} - struct scatterlist *scst_alloc(int size, unsigned long gfp_mask, int use_clustering, int *count) { @@ -567,11 +742,17 @@ int pages = (size >> PAGE_SHIFT) + ((size & ~PAGE_MASK) != 0); struct sgv_pool_alloc_fns sys_alloc_fns = { scst_alloc_sys_pages, scst_free_sys_sg_entries }; + int no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL); TRACE_ENTRY(); - atomic_inc(&sgv_other_total_alloc); + atomic_inc(&sgv_pools_mgr.sgv_other_total_alloc); + if (sgv_pool_hiwmk_check(pages, no_fail) != 0) { + res = NULL; + goto out; + } + res = kzalloc(pages*sizeof(*res), gfp_mask); if (res == NULL) goto out; @@ -581,6 +762,10 @@ if (*count <= 0) goto out_free; + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_pools_mgr.mgr.thr.active_pages_total += pages; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + out: TRACE_MEM("Alloced sg %p (count %d)", res, *count); @@ -596,10 +781,24 @@ void scst_free(struct scatterlist *sg, int count) { TRACE_MEM("Freeing sg=%p", sg); + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_pools_mgr.mgr.thr.active_pages_total -= count; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + scst_free_sys_sg_entries(sg, count, NULL); kfree(sg); + return; } +static void sgv_pool_cached_init(struct sgv_pool *pool) +{ + int i; + for(i = 0; i < SGV_POOL_ELEMENTS; i++) { + INIT_LIST_HEAD(&pool->recycling_lists[i]); + } +} + int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered) { int res = -ENOMEM; @@ -610,8 +809,8 @@ memset(pool, 0, sizeof(*pool)); - atomic_set(&pool->other_alloc, 0); - atomic_set(&pool->big_alloc, 0); + atomic_set(&pool->acc.other_alloc, 0); + atomic_set(&pool->acc.big_alloc, 0); atomic_set(&pool->acc.total_alloc, 0); atomic_set(&pool->acc.hit_alloc, 0); @@ -647,13 +846,8 @@ scnprintf(pool->cache_names[i], sizeof(pool->cache_names[i]), "%s-%luK", name, (PAGE_SIZE >> 10) << i); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) pool->caches[i] = kmem_cache_create(pool->cache_names[i], - size, 0, SCST_SLAB_FLAGS, sgv_ctor, NULL); -#else - pool->caches[i] = kmem_cache_create(pool->cache_names[i], - size, 0, SCST_SLAB_FLAGS, sgv_ctor, sgv_dtor); -#endif + size, 0, SCST_SLAB_FLAGS, NULL, NULL); if (pool->caches[i] == NULL) { TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool cache " "%s(%d) failed", name, i); @@ -661,10 +855,13 @@ } } - mutex_lock(&scst_sgv_pool_mutex); - list_add_tail(&pool->sgv_pool_list_entry, &scst_sgv_pool_list); - mutex_unlock(&scst_sgv_pool_mutex); + sgv_pool_cached_init(pool); + mutex_lock(&sgv_pools_mgr.scst_sgv_pool_mutex); + list_add_tail(&pool->sgv_pool_list_entry, + &sgv_pools_mgr.scst_sgv_pool_list); + mutex_unlock(&sgv_pools_mgr.scst_sgv_pool_mutex); + res = 0; out: @@ -688,16 +885,34 @@ TRACE_ENTRY(); + mutex_lock(&sgv_pools_mgr.scst_sgv_pool_mutex); + list_del(&pool->sgv_pool_list_entry); + mutex_unlock(&sgv_pools_mgr.scst_sgv_pool_mutex); + for(i = 0; i < SGV_POOL_ELEMENTS; i++) { + struct sgv_pool_obj *e; + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + while(!list_empty(&pool->recycling_lists[i])) { + e = list_entry(pool->recycling_lists[i].next, + struct sgv_pool_obj, + recycle_entry.recycling_list_entry); + + __sgv_pool_cached_purge(e); + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + EXTRACHECKS_BUG_ON(e->owner_pool != pool); + sgv_dtor_and_free(e); + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + } + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + if (pool->caches[i]) kmem_cache_destroy(pool->caches[i]); pool->caches[i] = NULL; } - mutex_lock(&scst_sgv_pool_mutex); - list_del(&pool->sgv_pool_list_entry); - mutex_unlock(&scst_sgv_pool_mutex); - TRACE_EXIT(); } @@ -747,72 +962,175 @@ TRACE_EXIT(); } -int scst_sgv_pools_init(struct scst_sgv_pools *pools) +static int sgv_pool_cached_shrinker(int nr, gfp_t gfpm) { + TRACE_ENTRY(); + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + if (nr > 0) { + struct sgv_pool_obj *e; + unsigned long rt = jiffies; + + while(!list_empty(&sgv_pools_mgr.mgr.sorted_recycling_list)) { + e = list_entry( + sgv_pools_mgr.mgr.sorted_recycling_list.next, + struct sgv_pool_obj, + recycle_entry.sorted_recycling_list_entry); + + if (sgv_pool_cached_purge(e, SHRINK_TIME_AFTER, rt) == 0) { + nr -= 1 << e->order; + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_dtor_and_free(e); + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + } else + break; + + if (nr <= 0) + break; + } + } + + nr = sgv_pools_mgr.mgr.thr.inactive_pages_total; + + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + TRACE_EXIT(); + return nr; +} + +static void sgv_pool_cached_pitbool(void *p) +{ + u32 total_pages; + struct sgv_pool_obj *e; + unsigned long rt = jiffies; + + TRACE_ENTRY(); + + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + sgv_pools_mgr.mgr.pitbool_running = 0; + + while(!list_empty(&sgv_pools_mgr.mgr.sorted_recycling_list)) { + e = list_entry(sgv_pools_mgr.mgr.sorted_recycling_list.next, + struct sgv_pool_obj, + recycle_entry.sorted_recycling_list_entry); + + if (sgv_pool_cached_purge(e, PURGE_TIME_AFTER, rt) == 0) { + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + sgv_dtor_and_free(e); + spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + } else + break; + } + + total_pages = sgv_pools_mgr.mgr.thr.inactive_pages_total; + + spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); + + if (total_pages) { + schedule_delayed_work(&sgv_pools_mgr.mgr.apit_pool, + PURGE_INTERVAL); + } + + TRACE_EXIT(); + return; +} + +int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark) +{ int res; + struct scst_sgv_pools_manager *pools = &sgv_pools_mgr; + TRACE_ENTRY(); + memset(pools, 0, sizeof(*pools)); - sgv_max_local_order = get_order( + sgv_pools_mgr.mgr.thr.hi_wmk = mem_hwmark >> PAGE_SHIFT; + sgv_pools_mgr.mgr.thr.lo_wmk = mem_lwmark >> PAGE_SHIFT; + + sgv_pools_mgr.sgv_max_local_order = get_order( ((((PAGE_SIZE - sizeof(struct sgv_pool_obj)) / (sizeof(struct trans_tbl_ent) + sizeof(struct scatterlist))) * PAGE_SIZE) & PAGE_MASK)) - 1; - sgv_max_trans_order = get_order( + sgv_pools_mgr.sgv_max_trans_order = get_order( ((((PAGE_SIZE - sizeof(struct sgv_pool_obj)) / (sizeof(struct trans_tbl_ent))) * PAGE_SIZE) & PAGE_MASK)) - 1; TRACE_MEM("sgv_max_local_order %d, sgv_max_trans_order %d", - sgv_max_local_order, sgv_max_trans_order); + sgv_pools_mgr.sgv_max_local_order, sgv_pools_mgr.sgv_max_trans_order); - atomic_set(&sgv_other_total_alloc, 0); + atomic_set(&pools->sgv_other_total_alloc, 0); + INIT_LIST_HEAD(&pools->scst_sgv_pool_list); + mutex_init(&pools->scst_sgv_pool_mutex); + + INIT_LIST_HEAD(&pools->mgr.sorted_recycling_list); + spin_lock_init(&pools->mgr.pool_mgr_lock); - res = sgv_pool_init(&pools->norm, "sgv", 0); + res = sgv_pool_init(&pools->default_set.norm, "sgv", 0); if (res != 0) goto out; - res = sgv_pool_init(&pools->norm_clust, "sgv-clust", 1); + res = sgv_pool_init(&pools->default_set.norm_clust, "sgv-clust", 1); if (res != 0) goto out_free_clust; - res = sgv_pool_init(&pools->dma, "sgv-dma", 0); + res = sgv_pool_init(&pools->default_set.dma, "sgv-dma", 0); if (res != 0) goto out_free_norm; #ifdef SCST_HIGHMEM - res = sgv_pool_init(&pools->highmem, "sgv-high", 0); + res = sgv_pool_init(&pools->default_set.highmem, "sgv-high", 0); if (res != 0) goto out_free_dma; #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + INIT_DELAYED_WORK(&pools->mgr.apit_pool, + (void (*)(struct work_struct *))sgv_pool_cached_pitbool); +#else + INIT_WORK(&pools->mgr.apit_pool, sgv_pool_cached_pitbool, NULL); +#endif + + pools->mgr.sgv_shrinker = set_shrinker(DEFAULT_SEEKS, + sgv_pool_cached_shrinker); + out: TRACE_EXIT_RES(res); return res; #ifdef SCST_HIGHMEM out_free_dma: - sgv_pool_deinit(&pools->dma); + sgv_pool_deinit(&pools->default_set.dma); #endif out_free_norm: - sgv_pool_deinit(&pools->norm); + sgv_pool_deinit(&pools->default_set.norm); out_free_clust: - sgv_pool_deinit(&pools->norm_clust); + sgv_pool_deinit(&pools->default_set.norm_clust); goto out; } -void scst_sgv_pools_deinit(struct scst_sgv_pools *pools) +void scst_sgv_pools_deinit(void) { + struct scst_sgv_pools_manager *pools = &sgv_pools_mgr; + TRACE_ENTRY(); + remove_shrinker(pools->mgr.sgv_shrinker); + cancel_delayed_work(&pools->mgr.apit_pool); + #ifdef SCST_HIGHMEM - sgv_pool_deinit(&pools->highmem); + sgv_pool_deinit(&pools->default_set.highmem); #endif - sgv_pool_deinit(&pools->dma); - sgv_pool_deinit(&pools->norm); - sgv_pool_deinit(&pools->norm_clust); + sgv_pool_deinit(&pools->default_set.dma); + sgv_pool_deinit(&pools->default_set.norm); + sgv_pool_deinit(&pools->default_set.norm_clust); + flush_scheduled_work(); + TRACE_EXIT(); return; } @@ -821,18 +1139,21 @@ { int i; - seq_printf(seq, "\n%-30s %-11d %-11d\n", pool->name, + seq_printf(seq, "\n%-30s %-11d %-11d %d/%d (P/O)\n", pool->name, atomic_read(&pool->acc.hit_alloc), - atomic_read(&pool->acc.total_alloc)); + atomic_read(&pool->acc.total_alloc), + pool->acc.cached_pages, + pool->acc.cached_entries); - for (i = 0; i < SGV_POOL_ELEMENTS; i++) { + for(i = 0; i < SGV_POOL_ELEMENTS; i++) { seq_printf(seq, " %-28s %-11d %-11d\n", pool->cache_names[i], atomic_read(&pool->cache_acc[i].hit_alloc), atomic_read(&pool->cache_acc[i].total_alloc)); } - seq_printf(seq, " %-28s %-11d %-11d\n", "big/other", atomic_read(&pool->big_alloc), - atomic_read(&pool->other_alloc)); + seq_printf(seq, " %-28s %-11d %-11d\n", "big/other", + atomic_read(&pool->acc.big_alloc), + atomic_read(&pool->acc.other_alloc)); return; } @@ -843,15 +1164,27 @@ TRACE_ENTRY(); - seq_printf(seq, "%-30s %-11s %-11s", "Name", "Hit", "Total"); + seq_printf(seq, "%-42s %d/%d\n%-42s %d/%d\n%-42s %d/%d\n\n", + "Inactive/active pages", + sgv_pools_mgr.mgr.thr.inactive_pages_total, + sgv_pools_mgr.mgr.thr.active_pages_total, + "Hi/lo watermarks [pages]", sgv_pools_mgr.mgr.thr.hi_wmk, + sgv_pools_mgr.mgr.thr.lo_wmk, "Hi watermark releases/failures", + sgv_pools_mgr.mgr.thr.releases_on_hiwmk, + sgv_pools_mgr.mgr.thr.releases_failed); - mutex_lock(&scst_sgv_pool_mutex); - list_for_each_entry(pool, &scst_sgv_pool_list, sgv_pool_list_entry) { + seq_printf(seq, "%-30s %-11s %-11s %-11s", "Name", "Hit", "Total", + "Cached"); + + mutex_lock(&sgv_pools_mgr.scst_sgv_pool_mutex); + list_for_each_entry(pool, &sgv_pools_mgr.scst_sgv_pool_list, + sgv_pool_list_entry) { scst_do_sgv_read(seq, pool); } - mutex_unlock(&scst_sgv_pool_mutex); + mutex_unlock(&sgv_pools_mgr.scst_sgv_pool_mutex); - seq_printf(seq, "\n%-42s %-11d\n", "other", atomic_read(&sgv_other_total_alloc)); + seq_printf(seq, "\n%-42s %-11d\n", "other", + atomic_read(&sgv_pools_mgr.sgv_other_total_alloc)); TRACE_EXIT(); return 0; Modified: trunk/scst/src/scst_mem.h =================================================================== --- trunk/scst/src/scst_mem.h 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_mem.h 2007-09-25 09:17:16 UTC (rev 192) @@ -15,6 +15,7 @@ */ #include <asm/scatterlist.h> +#include <linux/workqueue.h> #include <linux/seq_file.h> #define SGV_POOL_ELEMENTS 11 @@ -37,7 +38,14 @@ struct sgv_pool_obj { - struct kmem_cache *owner_cache; + int order; + + struct { + unsigned long time_stamp; /* jiffies, protected by pool_mgr_lock */ + struct list_head recycling_list_entry; + struct list_head sorted_recycling_list_entry; + } recycle_entry; + struct sgv_pool *owner_pool; int orig_sg; int orig_length; @@ -51,8 +59,15 @@ struct sgv_pool_acc { atomic_t total_alloc, hit_alloc; + u32 cached_pages, cached_entries; + atomic_t big_alloc, other_alloc; }; +struct sgv_pool_cache_acc +{ + atomic_t total_alloc, hit_alloc; +}; + struct sgv_pool_alloc_fns { struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask, @@ -68,25 +83,58 @@ /* 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 */ struct kmem_cache *caches[SGV_POOL_ELEMENTS]; - atomic_t big_alloc, other_alloc; + struct list_head recycling_lists[SGV_POOL_ELEMENTS]; /* protected by pool_mgr_lock */ + struct sgv_pool_acc acc; - struct sgv_pool_acc cache_acc[SGV_POOL_ELEMENTS]; + struct sgv_pool_cache_acc cache_acc[SGV_POOL_ELEMENTS]; char cache_names[SGV_POOL_ELEMENTS][25]; char name[25]; struct list_head sgv_pool_list_entry; }; -struct scst_sgv_pools +struct scst_sgv_pools_manager { - struct sgv_pool norm_clust, norm; - struct sgv_pool dma; + struct { + struct sgv_pool norm_clust, norm; + struct sgv_pool dma; #ifdef SCST_HIGHMEM - struct sgv_pool highmem; + struct sgv_pool highmem; #endif + } default_set; + + struct sgv_pool_mgr { + spinlock_t pool_mgr_lock; + struct list_head sorted_recycling_list; /* protected by pool_mgr_lock */ + int pitbool_running:1; /* protected by pool_mgr_lock */ + + struct sgv_mem_throttling { + u32 inactive_pages_total; + u32 active_pages_total; + + u32 hi_wmk; /* compared against inactive_pages_total + active_pages_total */ + u32 lo_wmk; /* compared against inactive_pages_total only */ + + u32 releases_on_hiwmk; + u32 releases_failed; + } thr; /* protected by pool_mgr_lock */ + + struct shrinker *sgv_shrinker; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct delayed_work apit_pool; +#else + struct work_struct apit_pool; +#endif + } mgr; + + int sgv_max_local_order, sgv_max_trans_order; + + atomic_t sgv_other_total_alloc; + struct mutex scst_sgv_pool_mutex; + struct list_head scst_sgv_pool_list; }; - int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered); void sgv_pool_deinit(struct sgv_pool *pool); @@ -96,7 +144,13 @@ return obj->sg_entries; } -extern int scst_sgv_pools_init(struct scst_sgv_pools *pools); -extern void scst_sgv_pools_deinit(struct scst_sgv_pools *pools); +extern int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark); +extern void scst_sgv_pools_deinit(void); extern int sgv_pool_procinfo_show(struct seq_file *seq, void *v); +void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev); +void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev); +void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev); +#ifdef SCST_HIGHMEM +void scst_sgv_pool_use_highmem(struct scst_tgt_dev *tgt_dev); +#endif Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_priv.h 2007-09-25 09:17:16 UTC (rev 192) @@ -174,14 +174,6 @@ extern struct scst_cmd_lists scst_main_cmd_lists; -extern spinlock_t scst_cmd_mem_lock; -extern unsigned long scst_max_cmd_mem, scst_cur_max_cmd_mem, scst_cur_cmd_mem; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -extern struct work_struct scst_cmd_mem_work; -#else -extern struct delayed_work scst_cmd_mem_work; -#endif - extern spinlock_t scst_mcmd_lock; /* The following lists protected by scst_mcmd_lock */ extern struct list_head scst_active_mgmt_cmd_list; @@ -248,11 +240,6 @@ int scst_init_cmd_thread(void *arg); int scst_mgmt_cmd_thread(void *arg); int scst_mgmt_thread(void *arg); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -void scst_cmd_mem_work_fn(void *p); -#else -void scst_cmd_mem_work_fn(struct work_struct *work); -#endif int scst_add_dev_threads(struct scst_device *dev, int num); void scst_del_dev_threads(struct scst_device *dev, int num); Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-09-25 09:11:08 UTC (rev 191) +++ trunk/scst/src/scst_targ.c 2007-09-25 09:17:16 UTC (rev 192) @@ -498,100 +498,8 @@ goto out; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -void scst_cmd_mem_work_fn(void *p) -#else -void scst_cmd_mem_work_fn(struct work_struct *work) -#endif -{ - TRACE_ENTRY(); - spin_lock_bh(&scst_cmd_mem_lock); - scst_cur_max_cmd_mem += (scst_cur_max_cmd_mem >> 3); - if (scst_cur_max_cmd_mem < scst_max_cmd_mem) { - TRACE_MGMT_DBG("%s", "Schedule cmd_mem_work"); - schedule_delayed_work(&scst_cmd_mem_work, SCST_CMD_MEM_TIMEOUT); - } else { - scst_cur_max_cmd_mem = scst_max_cmd_mem; - clear_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags); - } - TRACE_MGMT_DBG("New max cmd mem %ld Mb", scst_cur_max_cmd_mem >> 20); - - spin_unlock_bh(&scst_cmd_mem_lock); - - TRACE_EXIT(); - return; -} - -int scst_check_mem(struct scst_cmd *cmd) -{ - int res = 0; - - TRACE_ENTRY(); - - if (cmd->mem_checked) - goto out; - - spin_lock_bh(&scst_cmd_mem_lock); - - scst_cur_cmd_mem += cmd->bufflen; - cmd->mem_checked = 1; - if (likely(scst_cur_cmd_mem <= scst_cur_max_cmd_mem)) - goto out_unlock; - - TRACE(TRACE_OUT_OF_MEM, "Total memory allocated by commands (%ld Kb) " - "is too big, returning QUEUE FULL to initiator \"%s\" (maximum " - "allowed %ld Kb)", scst_cur_cmd_mem >> 10, - (cmd->sess->initiator_name[0] == '\0') ? - "Anonymous" : cmd->sess->initiator_name, - scst_cur_max_cmd_mem >> 10); - - scst_cur_cmd_mem -= cmd->bufflen; - cmd->mem_checked = 0; - scst_set_busy(cmd); - cmd->state = SCST_CMD_STATE_XMIT_RESP; - res = 1; - -out_unlock: - spin_unlock_bh(&scst_cmd_mem_lock); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static void scst_low_cur_max_cmd_mem(void) -{ - TRACE_ENTRY(); - - if (test_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags)) { - cancel_delayed_work(&scst_cmd_mem_work); - flush_scheduled_work(); - clear_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags); - } - - spin_lock_bh(&scst_cmd_mem_lock); - - scst_cur_max_cmd_mem = (scst_cur_cmd_mem >> 1) + - (scst_cur_cmd_mem >> 2); - if (scst_cur_max_cmd_mem < 16*1024*1024) - scst_cur_max_cmd_mem = 16*1024*1024; - - if (!test_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags)) { - TRACE_MGMT_DBG("%s", "Schedule cmd_mem_work"); - schedule_delayed_work(&scst_cmd_mem_work, SCST_CMD_MEM_TIMEOUT); - set_bit(SCST_FLAG_CMD_MEM_WORK_SCHEDULED, &scst_flags); - } - - spin_unlock_bh(&scst_cmd_mem_lock); - - TRACE_MGMT_DBG("New max cmd mem %ld Mb", scst_cur_max_cmd_mem >> 20); - - TRACE_EXIT(); - return; -} - static int scst_prepare_space(struct scst_cmd *cmd) { int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME; @@ -623,15 +531,12 @@ } alloc: - r = scst_check_mem(cmd); - if (unlikely(r != 0)) - goto out; - else if (!cmd->data_buf_alloced) { + if (!cmd->data_buf_alloced) { r = scst_alloc_space(cmd); } else { TRACE_MEM("%s", "data_buf_alloced set, returning"); } - + check: if (r != 0) { if (scst_cmd_atomic(cmd)) { @@ -689,7 +594,6 @@ out_no_space: TRACE(TRACE_OUT_OF_MEM, "Unable to allocate or build requested buffer " "(size %d), sending BUSY or QUEUE FULL status", cmd->bufflen); - scst_low_cur_max_cmd_mem(); scst_set_busy(cmd); cmd->state = SCST_CMD_STATE_DEV_DONE; res = SCST_CMD_STATE_RES_CONT_SAME; @@ -2551,12 +2455,6 @@ TRACE_ENTRY(); - if (cmd->mem_checked) { - spin_lock_bh(&scst_cmd_mem_lock); - scst_cur_cmd_mem -= cmd->bufflen; - spin_unlock_bh(&scst_cmd_mem_lock); - } - atomic_dec(&cmd->sess->sess_cmd_count); if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-10-25 09:54:06
|
Revision: 210 http://scst.svn.sourceforge.net/scst/?rev=210&view=rev Author: vlnb Date: 2007-10-25 02:54:00 -0700 (Thu, 25 Oct 2007) Log Message: ----------- - Cleanups and fixes in transfer length and direction processing. Modified Paths: -------------- trunk/scst/README trunk/scst/include/scst_const.h trunk/scst/src/Makefile trunk/scst/src/scst_cdbprobe.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_main.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/README 2007-10-25 09:54:00 UTC (rev 210) @@ -172,35 +172,67 @@ There are the following compilation options, that could be commented in/out in Makefile: - - DEBUG - turns on some debugging code, including some logging. Makes - the driver considerably bigger and slower, producing large amount of - log data. + - DEBUG - if defined, turns on some debugging code, including some + logging. Makes the driver considerably bigger and slower, producing + large amount of log data. - - TRACING - turns on ability to log events. Makes the driver considerably - bigger and lead to some performance loss. + - TRACING - if defined, turns on ability to log events. Makes the + driver considerably bigger and lead to some performance loss. - - EXTRACHECKS - adds extra validity checks in the various places. + - EXTRACHECKS - if defined, adds extra validity checks in the various + places. - - DEBUG_TM - turns on task management functions debugging, when on - LUN 0 in the default access control group some of the commands will - be delayed for about 60 sec., so making the remote initiator send TM - functions, eg ABORT TASK and TARGET RESET. Also set TM_DBG_GO_OFFLINE - symbol in the Makefile to 1 if you want that the device eventually - become completely unresponsive, or to 0 otherwise to circle around - ABORTs and RESETs code. Needs DEBUG turned on. + - USE_EXPECTED_VALUES - if not defined (default), initiator supplied + expected data transfer length and direction will be used only for + verification purposes to return error or warn in case if one of them + is invalid. Instead, locally decoded from SCSI command values will be + used. This is necessary for security reasons, because otherwise a + faulty initiator can crash target by supplying invalid value in one + of those parameters. This is especially important in case of + pass-through mode. If USE_EXPECTED_VALUES is defined, initiator + supplied expected data transfer length and direction will override + the locally decoded values. This might be necessary if internal SCST + commands translation table doesn't contain SCSI command, which is + used in your environment. You can know that if you have messages like + "Unknown opcode XX for YY. Should you update scst_scsi_op_table?" in + your kernel log and your initiator returns an error. Also report + those messages in the SCST mailing list + scs...@li.... Note, that not all SCSI transports + support supplying expected values. - - STRICT_SERIALIZING - makes SCST send all commands to underlying SCSI - device synchronously, one after one. This makes task management more - reliable, with cost of some performance penalty. This is mostly - actual for stateful SCSI devices like tapes, where the result of - command's execution depends from device's settings set by previous - commands. Disk and RAID devices are stateless in the most cases. The - current SCSI core in Linux doesn't allow to abort all commands - reliably if they sent asynchronously to a stateful device. Turned off - by default, turn it on if you use stateful device(s) and need as much - error recovery reliability as possible. As a side effect, no kernel - patching is necessary. + - DEBUG_TM - if defined, turns on task management functions debugging, + when on LUN 0 in the default access control group some of the + commands will be delayed for about 60 sec., so making the remote + initiator send TM functions, eg ABORT TASK and TARGET RESET. Also + define TM_DBG_GO_OFFLINE symbol in the Makefile to 1 if you want that + the device eventually become completely unresponsive, or to 0 + otherwise to circle around ABORTs and RESETs code. Needs DEBUG turned + on. + - STRICT_SERIALIZING - if defined, makes SCST send all commands to + underlying SCSI device synchronously, one after one. This makes task + management more reliable, with cost of some performance penalty. This + is mostly actual for stateful SCSI devices like tapes, where the + result of command's execution depends from device's settings defined + by previous commands. Disk and RAID devices are stateless in the most + cases. The current SCSI core in Linux doesn't allow to abort all + commands reliably if they sent asynchronously to a stateful device. + Turned off by default, turn it on if you use stateful device(s) and + need as much error recovery reliability as possible. As a side + effect, no kernel patching is necessary. + + - ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ - if defined, it will be allowed + to submit pass-through commands to real SCSI devices via the SCSI + middle layer using scsi_execute_async() function from soft IRQ + context (tasklets). This used to be the default, but currently it + seems the SCSI middle layer starts expecting only thread context on + the IO submit path, so it is disabled now by default. Enabling it + will decrease amount of context switches and improve performance. It + is more or less safe, in the worst case, if in your configuration the + SCSI middle layer really doesn't expect SIRQ context in + scsi_execute_async() function, you will get a warning message in the + kernel log. + - SCST_HIGHMEM - if defined on HIGHMEM systems with 2.6 kernels, it allows SCST to use HIGHMEM. This is very experimental feature, which is currently broken and unsupported, since it is unclear, if it @@ -216,8 +248,8 @@ HIGHMEM kernel configurations are fully supported, but not recommended for performance reasons, except for scst_user, where they are not supported, because this module deals with user supplied memory on a -zero-copy manner. Consider change VMSPLIT option or use 64-bit system -configuration instead. +zero-copy manner. If you need to use it, consider change VMSPLIT option +or use 64-bit system configuration instead. For changing VMSPLIT option (CONFIG_VMSPLIT to be precise) you should in "make menuconfig" command set the following variables: @@ -437,15 +469,23 @@ workloads write through caching might perform better, than write back one with the barrier protection turned on. -IMPORTANT: Many disk and partition table management utilities don't support +IMPORTANT: Some disk and partition table management utilities don't support ========= block sizes >512 bytes, therefore make sure that your favorite one - supports it. Also, if you export disk file or device with - some block size, different from one, with which it was - already divided on partitions, you could get various weird + supports it. Currently only cfdisk is known to work only with + 512 bytes blocks, other utilities like fdisk on Linux or + standard disk manager on Windows are proved to work well with + non-512 bytes blocks. Note, if you export a disk file or + device with some block size, different from one, with which + it was already partitioned, you could get various weird things like utilities hang up or other unexpected behavior. - Hence, to be sure, zero the exported file or device before the - first access to it from the remote initiator with another - block size. + Hence, to be sure, zero the exported file or device before + the first access to it from the remote initiator with another + block size. On Window initiator make sure you "Set Signature" + in the disk manager on the imported from the target drive + before doing any other partitioning on it. After you + successfully mounted a file system over non-512 bytes block + size device, the block size stops matter, any program will + work with files on such file system. BLOCKIO VDISK mode ------------------ @@ -465,9 +505,10 @@ their data access, can actually see worse performance with non-discriminate caching. -4) Multiple layers of targets were the secondary/triary layers need to -have a consistent view of the primary targets in order to preserve data -integrity which a page cache backed IO type might not provide reliably. +4) Multiple layers of targets were the secondary and above layers need +to have a consistent view of the primary targets in order to preserve +data integrity which a page cache backed IO type might not provide +reliably. Also it has an advantage over FILEIO that it doesn't copy data between the system cache and the commands data buffers, so it saves a @@ -533,6 +574,8 @@ - Disable in Makefile STRICT_SERIALIZING, EXTRACHECKS, TRACING, DEBUG*, SCST_STRICT_SECURITY, SCST_HIGHMEM + - For pass-through devices enable ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ. + 2. For target drivers: - Disable in Makefiles EXTRACHECKS, TRACING, DEBUG* @@ -552,7 +595,8 @@ than for performance. If you use SCST version taken directly from its SVN repository, you can -set the above options using debug2perf script file. +set the above options, except ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, using +debug2perf script file. 4. For kernel: Modified: trunk/scst/include/scst_const.h =================================================================== --- trunk/scst/include/scst_const.h 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/include/scst_const.h 2007-10-25 09:54:00 UTC (rev 210) @@ -121,6 +121,7 @@ #define scst_sense_read_error MEDIUM_ERROR, 0x11, 0 #define scst_sense_write_error MEDIUM_ERROR, 0x03, 0 #define scst_sense_not_ready NOT_READY, 0x04, 0x10 +#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0 /************************************************************* * SCSI opcodes not listed anywhere else Modified: trunk/scst/src/Makefile =================================================================== --- trunk/scst/src/Makefile 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/Makefile 2007-10-25 09:54:00 UTC (rev 210) @@ -116,6 +116,9 @@ EXTRA_CFLAGS += -DEXTRACHECKS +#EXTRA_CFLAGS += -DUSE_EXPECTED_VALUES +#EXTRA_CFLAGS += -DALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ + #EXTRA_CFLAGS += -fno-inline #EXTRA_CFLAGS += -DTRACING Modified: trunk/scst/src/scst_cdbprobe.h =================================================================== --- trunk/scst/src/scst_cdbprobe.h 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/scst_cdbprobe.h 2007-10-25 09:54:00 UTC (rev 210) @@ -249,16 +249,6 @@ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2}, {0x2F, "O OO O ", "VERIFY(10)", SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2}, -/* - {0x30, "O OO O ", "SEARCH DATA HIGH(10)", - SCST_DATA_NONE, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, - {0x31, " O ", "OBJECT POSITION", - SCST_DATA_NONE, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, - {0x31, "O OO O ", "SEARCH DATA EQUAL(10)", - SCST_DATA_NONE, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, - {0x32, "O OO O ", "SEARCH DATA LOW(10)", - SCST_DATA_NONE, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, -*/ {0x33, "O OO O ", "SET LIMITS(10)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x34, " O ", "READ POSITION", @@ -402,7 +392,7 @@ {0x93, " M ", "ERASE(16)", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x9E, "O ", "SERVICE ACTION IN", - SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, /* 12-bytes length CDB */ {0xA0, "VVVVVVVVVV M ", "REPORT LUN", @@ -443,7 +433,7 @@ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0xAC, " O ", "ERASE(12)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, - {0xAC, " O ", "GET PERFORMANCE", + {0xAC, " M ", "GET PERFORMANCE", SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, {0xAD, " O ", "READ DVD STRUCTURE", SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2}, @@ -467,8 +457,8 @@ SCST_DATA_READ, FLAG_NONE, 9, get_trans_len_1}, {0xB6, " O ", "SEND VOLUME TAG", SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1}, - {0xB6, " O ", "SET STREAMING", - SCST_DATA_WRITE, FLAG_NONE, 0, get_trans_len_none}, + {0xB6, " M ", "SET STREAMING", + SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_2}, {0xB7, " O ", "READ DEFECT DATA(12)", SCST_DATA_READ, FLAG_NONE, 9, get_trans_len_1}, {0xB8, " O ", "READ ELEMENT STATUS", Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/scst_lib.c 2007-10-25 09:54:00 UTC (rev 210) @@ -1626,7 +1626,7 @@ static uint32_t get_trans_len_read_capacity(const uint8_t *cdb, uint8_t off) { - return 8; + return READ_CAP_LEN; } static uint32_t get_trans_len_single(const uint8_t *cdb, uint8_t off) @@ -1698,7 +1698,7 @@ #ifdef EXTRACHECKS if (unlikely((info_p->transfer_len == 0) && (info_p->direction != SCST_DATA_NONE))) { - TRACE_DBG("Warning! transfer_len 0, direction %d change on %d", + TRACE_MGMT_DBG("Warning! transfer_len 0, direction %d change on %d", info_p->direction, SCST_DATA_NONE); info_p->direction = SCST_DATA_NONE; } @@ -1846,10 +1846,6 @@ info_cdb->direction, info_cdb->flags, info_cdb->transfer_len); switch (cmd->cdb[0]) { - case READ_CAPACITY: - cmd->bufflen = READ_CAP_LEN; - cmd->data_direction = SCST_DATA_READ; - break; case SERVICE_ACTION_IN: if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) { cmd->bufflen = READ_CAP16_LEN; @@ -1911,18 +1907,6 @@ cmd->cdb[1] &= 0x1f; switch (cmd->cdb[0]) { - case READ_CAPACITY: - cmd->bufflen = READ_CAP_LEN; - cmd->data_direction = SCST_DATA_READ; - break; - case GPCMD_SET_STREAMING: - cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) + - ((*(cmd->cdb + 10)) & 0xff); - cmd->bufflen &= 0xffff; - break; - case GPCMD_READ_CD: - cmd->bufflen = cmd->bufflen >> 8; - break; case VERIFY_6: case VERIFY: case VERIFY_12: @@ -1972,18 +1956,6 @@ cmd->cdb[1] &= 0x1f; switch (cmd->cdb[0]) { - case READ_CAPACITY: - cmd->bufflen = READ_CAP_LEN; - cmd->data_direction = SCST_DATA_READ; - break; - case 0xB6 /* SET_STREAMING */ : - cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) + - ((*(cmd->cdb + 10)) & 0xff); - cmd->bufflen &= 0xffff; - break; - case 0xBE /* READ_CD */ : - cmd->bufflen = cmd->bufflen >> 8; - break; case VERIFY_6: case VERIFY: case VERIFY_12: Modified: trunk/scst/src/scst_main.c =================================================================== --- trunk/scst/src/scst_main.c 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/scst_main.c 2007-10-25 09:54:00 UTC (rev 210) @@ -606,8 +606,13 @@ goto out; } - if (dev_handler->exec == NULL) + if (dev_handler->exec == NULL) { +#ifdef ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ dev_handler->exec_atomic = 1; +#else + dev_handler->exec_atomic = 0; +#endif + } if (dev_handler->dev_done == NULL) dev_handler->dev_done_atomic = 1; Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/scst_priv.h 2007-10-25 09:54:00 UTC (rev 210) @@ -126,6 +126,8 @@ return SCST_CONTEXT_DIRECT; } +extern unsigned long scst_max_cmd_mem; + #define SCST_MGMT_CMD_CACHE_STRING "scst_mgmt_cmd" extern struct kmem_cache *scst_mgmt_cachep; extern mempool_t *scst_mgmt_mempool; Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-10-23 15:35:20 UTC (rev 209) +++ trunk/scst/src/scst_targ.c 2007-10-25 09:54:00 UTC (rev 210) @@ -305,23 +305,20 @@ */ if (unlikely(scst_get_cdb_info(cmd->cdb, dev->handler->type, - &cdb_info) != 0)) - { - static int t; - if (t < 10) { - t++; - PRINT_INFO_PR("Unknown opcode 0x%02x for %s. " - "Should you update scst_scsi_op_table?", - cmd->cdb[0], dev->handler->name); - } + &cdb_info) != 0)) { + PRINT_ERROR_PR("Unknown opcode 0x%02x for %s. " + "Should you update scst_scsi_op_table?", + cmd->cdb[0], dev->handler->name); +#ifdef USE_EXPECTED_VALUES if (scst_cmd_is_expected_set(cmd)) { TRACE(TRACE_SCSI, "Using initiator supplied values: " "direction %d, transfer_len %d", cmd->expected_data_direction, cmd->expected_transfer_len); cmd->data_direction = cmd->expected_data_direction; + cmd->bufflen = cmd->expected_transfer_len; - /* Restore (most probably) lost CDB length */ + /* Restore (likely) lost CDB length */ cmd->cdb_len = scst_get_cdb_len(cmd->cdb); if (cmd->cdb_len == -1) { PRINT_ERROR_PR("Unable to get CDB length for " @@ -333,13 +330,17 @@ } } else { PRINT_ERROR_PR("Unknown opcode 0x%02x for %s and " - "target %s not supplied expected values. " - "Returning INVALID OPCODE.", cmd->cdb[0], - dev->handler->name, cmd->tgtt->name); + "target %s not supplied expected values", + cmd->cdb[0], dev->handler->name, cmd->tgtt->name); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode)); goto out_xmit; } +#else + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_invalid_opcode)); + goto out_xmit; +#endif } else { TRACE(TRACE_SCSI, "op_name <%s>, direction=%d (expected %d, " "set %s), transfer_len=%d (expected len %d), flags=%d", @@ -349,13 +350,25 @@ cdb_info.transfer_len, cmd->expected_transfer_len, cdb_info.flags); - /* Restore (most probably) lost CDB length */ - cmd->cdb_len = cdb_info.cdb_len; + cmd->data_direction = cdb_info.direction; - cmd->data_direction = cdb_info.direction; - if (!(cdb_info.flags & SCST_UNKNOWN_LENGTH)) + if (unlikely((cdb_info.flags & SCST_UNKNOWN_LENGTH) != 0)) { + if (scst_cmd_is_expected_set(cmd)) { + /* + * Command data length can't be easily + * determined from the CDB. Get it from + * the supplied expected value, but + * limit it to some reasonable value (50MB). + */ + cmd->bufflen = min(cmd->expected_transfer_len, + 50*1024*1024); + } else + cmd->bufflen = 0; + } else cmd->bufflen = cdb_info.transfer_len; - /* else cmd->bufflen remained as it was inited in 0 */ + + /* Restore (likely) lost CDB length */ + cmd->cdb_len = cdb_info.cdb_len; } if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) { @@ -402,25 +415,14 @@ if (state == SCST_CMD_STATE_DEFAULT) state = SCST_CMD_STATE_PREPARE_SPACE; - } - else + } else state = SCST_CMD_STATE_PREPARE_SPACE; - if (scst_cmd_is_expected_set(cmd)) { - if (cmd->expected_transfer_len < cmd->bufflen) { - TRACE(TRACE_SCSI, "cmd->expected_transfer_len(%d) < " - "cmd->bufflen(%d), using expected_transfer_len " - "instead", cmd->expected_transfer_len, - cmd->bufflen); - cmd->bufflen = cmd->expected_transfer_len; - } - } - if (cmd->data_len == -1) cmd->data_len = cmd->bufflen; - if (cmd->data_buf_alloced && (orig_bufflen > cmd->bufflen)) { - PRINT_ERROR_PR("Target driver supplied data buffer (size %d), " + if (cmd->data_buf_alloced && unlikely((orig_bufflen > cmd->bufflen))) { + PRINT_ERROR_PR("Dev handler supplied data buffer (size %d), " "is less, than required (size %d)", cmd->bufflen, orig_bufflen); goto out_error; @@ -448,6 +450,42 @@ } #endif + if (scst_cmd_is_expected_set(cmd)) { +#ifdef USE_EXPECTED_VALUES +# ifdef EXTRACHECKS + if ((cmd->data_direction != cmd->expected_data_direction) || + (cmd->bufflen != cmd->expected_transfer_len)) { + PRINT_ERROR_PR("Expected values don't match decoded ones: " + "data_direction %d, expected_data_direction %d, " + "bufflen %d, expected_transfer_len %d", + cmd->data_direction, cmd->expected_data_direction, + cmd->bufflen, cmd->expected_transfer_len); + } +# endif + cmd->data_direction = cmd->expected_data_direction; + cmd->bufflen = cmd->expected_transfer_len; +#else + if (unlikely(cmd->data_direction != cdb_info.direction)) { + PRINT_ERROR_PR("Expected data direction %d for opcode " + "0x%02x (handler %s, target %s) doesn't match " + "decoded value %d", cmd->data_direction, + cmd->cdb[0], dev->handler->name, + cmd->tgtt->name, cdb_info.direction); + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_invalid_message)); + goto out_dev_done; + } + if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) { + PRINT_INFO_PR("Warning: expected transfer length %d for " + "opcode 0x%02x (handler %s, target %s) doesn't " + "match decoded value %d. Faulty initiator?", + cmd->expected_transfer_len, cmd->cdb[0], + dev->handler->name, cmd->tgtt->name, + cmd->bufflen); + } +#endif + } + switch (state) { case SCST_CMD_STATE_PREPARE_SPACE: case SCST_CMD_STATE_DEV_PARSE: @@ -488,6 +526,10 @@ out_error: /* dev_done() will be called as part of the regular cmd's finish */ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + +#ifndef USE_EXPECTED_VALUES +out_dev_done: +#endif cmd->state = SCST_CMD_STATE_DEV_DONE; res = SCST_CMD_STATE_RES_CONT_SAME; goto out; @@ -498,8 +540,6 @@ goto out; } - - static int scst_prepare_space(struct scst_cmd *cmd) { int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2007-12-14 16:51:39
|
Revision: 236 http://scst.svn.sourceforge.net/scst/?rev=236&view=rev Author: vlnb Date: 2007-12-14 08:51:36 -0800 (Fri, 14 Dec 2007) Log Message: ----------- - Makes sessions registration/unregistration independant from other activities - Cleanups - Docs update Modified Paths: -------------- trunk/scst/README trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_main.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/README 2007-12-14 16:51:36 UTC (rev 236) @@ -676,15 +676,18 @@ - Make sure that your target hardware (e.g. target FC or network card) and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to - which your disks connected) don't share the same PCI bus. They have - to work in parallel, so it will be better if they don't compete for - the bus. The problem is not only in the bandwidth, which they have to - share, but also in the interaction between cards during that - competition. This is very important, because in some cases if target - and backend storage controllers share the same PCI bus, it could lead - up to 5-10 times less performance, than expected. If you have no - choice, but PCI bus sharing, set in the BIOS PCI latency as low as - possible. + which your disks connected) don't share the same PCI bus. You can + check it using lspci utility. They have to work in parallel, so it + will be better if they don't compete for the bus. The problem is not + only in the bandwidth, which they have to share, but also in the + interaction between cards during that competition. This is very + important, because in some cases if target and backend storage + controllers share the same PCI bus, it could lead up to 5-10 times + less performance, than expected. Moreover, some motherboard (by + Supermicro, particularly) have serious stability issues if there are + several high speed devices on the same bus working in parallel. If + you have no choice, but PCI bus sharing, set in the BIOS PCI latency + as low as possible. IMPORTANT: If you use on initiator some versions of Windows (at least W2K) ========= you can't get good write performance for VDISK FILEIO devices with Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/include/scsi_tgt.h 2007-12-14 16:51:36 UTC (rev 236) @@ -1355,8 +1355,8 @@ struct list_head dev_list_entry; /* - * List of tgt_dev's, one per session, protected by scst_mutex and - * suspended activity + * List of tgt_dev's, one per session, protected by scst_mutex or + * dev_lock for reads and both for writes */ struct list_head dev_tgt_dev_list; Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_lib.c 2007-12-14 16:51:36 UTC (rev 236) @@ -206,8 +206,7 @@ #ifdef EXTRACHECKS if (!list_empty(&dev->dev_tgt_dev_list) || - !list_empty(&dev->dev_acg_dev_list)) - { + !list_empty(&dev->dev_acg_dev_list)) { PRINT_ERROR("%s: dev_tgt_dev_list or dev_acg_dev_list " "is not empty!", __FUNCTION__); sBUG(); @@ -311,8 +310,7 @@ /* Freeing acg_devs */ list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list, - acg_dev_list_entry) - { + acg_dev_list_entry) { struct scst_tgt_dev *tgt_dev, *tt; list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list, @@ -325,8 +323,7 @@ /* Freeing names */ list_for_each_entry_safe(n, nn, &acg->acn_list, - acn_list_entry) - { + acn_list_entry) { list_del(&n->acn_list_entry); kfree(n->name); kfree(n); @@ -339,10 +336,7 @@ return res; } -/* - * No spin locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess, struct scst_acg_dev *acg_dev) { @@ -479,10 +473,12 @@ goto out_thr_free; } } - + + spin_lock_bh(&dev->dev_lock); list_add_tail(&tgt_dev->dev_tgt_dev_list_entry, &dev->dev_tgt_dev_list); if (dev->dev_reserved) __set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags); + spin_unlock_bh(&dev->dev_lock); sess_tgt_dev_list_head = &sess->sess_tgt_dev_list_hash[HASH_VAL(tgt_dev->lun)]; @@ -508,10 +504,7 @@ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev); -/* - * No locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* No locks supposed to be held, scst_mutex - held */ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev) { TRACE_ENTRY(); @@ -533,10 +526,7 @@ return; } -/* - * No locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev) { struct scst_device *dev = tgt_dev->dev; @@ -546,7 +536,10 @@ tm_dbg_deinit_tgt_dev(tgt_dev); + spin_lock_bh(&dev->dev_lock); list_del(&tgt_dev->dev_tgt_dev_list_entry); + spin_unlock_bh(&dev->dev_lock); + list_del(&tgt_dev->sess_tgt_dev_list_entry); scst_clear_reservation(tgt_dev); @@ -572,7 +565,7 @@ return; } -/* The activity supposed to be suspended and scst_mutex held */ +/* scst_mutex supposed to be held */ int scst_sess_alloc_tgt_devs(struct scst_session *sess) { int res = 0; @@ -582,8 +575,7 @@ TRACE_ENTRY(); list_for_each_entry(acg_dev, &sess->acg->acg_dev_list, - acg_dev_list_entry) - { + acg_dev_list_entry) { tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev); if (tgt_dev == NULL) { res = -ENOMEM; @@ -600,7 +592,7 @@ goto out; } -/* scst_mutex supposed to be held and activity suspended */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ void scst_sess_free_tgt_devs(struct scst_session *sess) { int i; @@ -1062,15 +1054,17 @@ } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */ +/* scst_mutex supposed to be held */ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev) { struct scst_device *dev = tgt_dev->dev; + int release = 0; TRACE_ENTRY(); + spin_lock_bh(&dev->dev_lock); if (dev->dev_reserved && - !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) - { + !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) { /* This is one who holds the reservation */ struct scst_tgt_dev *tgt_dev_tmp; list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, @@ -1079,9 +1073,11 @@ &tgt_dev_tmp->tgt_dev_flags); } dev->dev_reserved = 0; + } + spin_unlock_bh(&dev->dev_lock); + if (release) scst_send_release(tgt_dev); - } TRACE_EXIT(); return; @@ -1149,7 +1145,6 @@ { TRACE_ENTRY(); - scst_suspend_activity(); mutex_lock(&scst_mutex); TRACE_DBG("Removing sess %p from the list", sess); @@ -1162,7 +1157,6 @@ wake_up_all(&sess->tgt->unreg_waitQ); mutex_unlock(&scst_mutex); - scst_resume_activity(); kfree(sess->initiator_name); kmem_cache_free(scst_sess_cachep, sess); @@ -2332,7 +2326,6 @@ /* Clear RESERVE'ation, if necessary */ if (dev->dev_reserved) { - /* Either scst_mutex held or exclude_cmd non-NULL */ 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 " @@ -2452,7 +2445,7 @@ goto out; } -/* Called under dev_lock, tgt_dev_lock and BH off */ +/* Called under tgt_dev_lock and BH off */ void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, int sense_len, int head) { @@ -2515,7 +2508,7 @@ return; } -/* No locks, but the activity must not get suspended while inside this function */ +/* Called under dev_lock and BH off */ void scst_dev_check_set_local_UA(struct scst_device *dev, struct scst_cmd *exclude, const uint8_t *sense, int sense_len) { @@ -2676,11 +2669,6 @@ TRACE_ENTRY(); - /* - * This is read-only function for dev->dev_tgt_dev_list, so - * suspending the activity isn't necessary. - */ - mutex_lock(&scst_mutex); list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, Modified: trunk/scst/src/scst_main.c =================================================================== --- trunk/scst/src/scst_main.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_main.c 2007-12-14 16:51:36 UTC (rev 236) @@ -920,7 +920,7 @@ return; } -/* Called under scst_mutex and suspended activity */ +/* Called under scst_mutex */ int scst_add_dev_threads(struct scst_device *dev, int num) { int i, res = 0; @@ -992,7 +992,7 @@ return res; } -/* Called under scst_mutex and suspended activity */ +/* Called under scst_mutex */ void scst_del_dev_threads(struct scst_device *dev, int num) { struct scst_cmd_thread_t *ct, *tmp; Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_priv.h 2007-12-14 16:51:36 UTC (rev 236) @@ -366,6 +366,7 @@ } void scst_dev_check_set_local_UA(struct scst_device *dev, struct scst_cmd *exclude, const uint8_t *sense, int sense_len); + void scst_check_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, int sense_len, int head); void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_targ.c 2007-12-14 16:51:36 UTC (rev 236) @@ -1368,8 +1368,7 @@ } list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { if (cmd->tgt_dev != tgt_dev_tmp) set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev_tmp->tgt_dev_flags); @@ -2140,17 +2139,22 @@ if (!test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { struct scst_tgt_dev *tgt_dev_tmp; + struct scst_device *dev = cmd->dev; + TRACE(TRACE_SCSI, "Real RESERVE failed lun=%Ld, status=%x", (uint64_t)cmd->lun, cmd->status); TRACE_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense_buffer, sizeof(cmd->sense_buffer)); + /* Clearing the reservation */ - list_for_each_entry(tgt_dev_tmp, &cmd->dev->dev_tgt_dev_list, + spin_lock_bh(&dev->dev_lock); + list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { clear_bit(SCST_TGT_DEV_RESERVED, &tgt_dev_tmp->tgt_dev_flags); } - cmd->dev->dev_reserved = 0; + dev->dev_reserved = 0; + spin_unlock_bh(&dev->dev_lock); } } @@ -2203,7 +2207,8 @@ if (unlikely((cmd->cdb[0] == MODE_SELECT) || (cmd->cdb[0] == MODE_SELECT_10) || (cmd->cdb[0] == LOG_SELECT))) { - if (atomic && (cmd->dev->scsi_dev != NULL)) { + struct scst_device *dev = cmd->dev; + if (atomic && (dev->scsi_dev != NULL)) { TRACE_DBG("%s", "MODE/LOG SELECT: thread " "context required"); res = SCST_CMD_STATE_RES_NEED_THREAD; @@ -2214,7 +2219,8 @@ "setting the SELECT UA (lun=%Ld)", (uint64_t)cmd->lun); - spin_lock_bh(&scst_temp_UA_lock); + spin_lock_bh(&dev->dev_lock); + spin_lock(&scst_temp_UA_lock); if (cmd->cdb[0] == LOG_SELECT) { scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA), @@ -2224,12 +2230,13 @@ sizeof(scst_temp_UA), UNIT_ATTENTION, 0x2a, 0x01); } - scst_dev_check_set_local_UA(cmd->dev, cmd, scst_temp_UA, + scst_dev_check_set_local_UA(dev, cmd, scst_temp_UA, sizeof(scst_temp_UA)); - spin_unlock_bh(&scst_temp_UA_lock); + spin_unlock(&scst_temp_UA_lock); + spin_unlock_bh(&dev->dev_lock); - if (cmd->dev->scsi_dev != NULL) - scst_obtain_device_parameters(cmd->dev); + if (dev->scsi_dev != NULL) + scst_obtain_device_parameters(dev); } } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) && SCST_SENSE_VALID(cmd->sense_buffer) && @@ -3499,9 +3506,10 @@ __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev, 0, 0); + mutex_lock(&scst_mutex); + list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { struct scst_session *sess = tgt_dev->sess; struct scst_cmd *cmd; int aborted = 0; @@ -3528,6 +3536,8 @@ &UA_tgt_devs); } + mutex_unlock(&scst_mutex); + scst_unblock_aborted_cmds(0); if (!dev->tas) { @@ -3686,8 +3696,7 @@ cont = 0; c = 0; list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { cont = 1; rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); if (rc == SCST_DEV_TM_NOT_COMPLETED) @@ -4378,7 +4387,6 @@ TRACE_ENTRY(); - scst_suspend_activity(); mutex_lock(&scst_mutex); if (sess->initiator_name) @@ -4401,7 +4409,6 @@ res = scst_sess_alloc_tgt_devs(sess); mutex_unlock(&scst_mutex); - scst_resume_activity(); if (sess->init_result_fn) { TRACE_DBG("Calling init_result_fn(%p)", sess); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2008-03-10 10:59:59
|
Revision: 299 http://scst.svn.sourceforge.net/scst/?rev=299&view=rev Author: vlnb Date: 2008-03-10 03:59:56 -0700 (Mon, 10 Mar 2008) Log Message: ----------- - Fixed READ POSITION command handling - Fixed race in TM handling Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_cdbprobe.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2008-03-05 18:22:01 UTC (rev 298) +++ trunk/scst/include/scsi_tgt.h 2008-03-10 10:59:56 UTC (rev 299) @@ -1284,7 +1284,6 @@ int fn; unsigned int completed:1; /* set, if the mcmd is completed */ - unsigned int active:1; /* set, if the mcmd is active */ /* Set if device(s) should be unblocked after mcmd's finish */ unsigned int needs_unblocking:1; unsigned int lun_set:1; /* set, if lun field is valid */ @@ -1884,11 +1883,9 @@ * cdb_p - pointer to CDB * dev_type - SCSI device type * op_flags, direction, transfer_len, cdb_len, op_name - the result (output) - * Returns 0 on success, -1 otherwise + * Returns: 0 on success, <0 if command is unknown, >0 if command is invalid. */ -int scst_get_cdb_info(const uint8_t *cdb_p, int dev_type, - enum scst_cdb_flags *op_flags, scst_data_direction *direction, - unsigned int *transfer_len, int *cdb_len, const char **op_name); +int scst_get_cdb_info(struct scst_cmd *cmd); /* * Set error SCSI status in the command and prepares it for returning it Modified: trunk/scst/src/scst_cdbprobe.h =================================================================== --- trunk/scst/src/scst_cdbprobe.h 2008-03-05 18:22:01 UTC (rev 298) +++ trunk/scst/src/scst_cdbprobe.h 2008-03-10 10:59:56 UTC (rev 299) @@ -21,16 +21,17 @@ #define __SCST_CDBPROBE_H /* get_trans_len_x extract x bytes from cdb as length starting from off */ -static uint32_t get_trans_len_1(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_2(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_3(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_4(const uint8_t *cdb, uint8_t off); +static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off); /* for special commands */ -static uint32_t get_trans_len_block_limit(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_read_capacity(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_single(const uint8_t *cdb, uint8_t off); -static uint32_t get_trans_len_none(const uint8_t *cdb, uint8_t off); +static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off); /* +=====================================-============-======- @@ -80,7 +81,7 @@ */ uint8_t flags; /* opcode -- various flags */ uint8_t off; /* length offset in cdb */ - uint32_t (*get_trans_len)(const uint8_t *cdb, uint8_t off) __attribute__ ((aligned)); + int (*get_trans_len)(struct scst_cmd *cmd, uint8_t off) __attribute__ ((aligned)); } __attribute__((packed)); static int scst_scsi_op_list[256]; @@ -252,7 +253,7 @@ {0x33, "O OO O ", "SET LIMITS(10)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x34, " O ", "READ POSITION", - SCST_DATA_READ, SCST_SMALL_TIMEOUT, 7, get_trans_len_2}, + SCST_DATA_READ, SCST_SMALL_TIMEOUT, 7, get_trans_len_read_pos}, {0x34, " O ", "GET DATA BUFFER STATUS", SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, {0x34, "O OO O ", "PRE-FETCH", Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2008-03-05 18:22:01 UTC (rev 298) +++ trunk/scst/src/scst_lib.c 2008-03-10 10:59:56 UTC (rev 299) @@ -1650,79 +1650,132 @@ /* get_trans_len_x extract x bytes from cdb as length starting from off */ -static uint32_t get_trans_len_1(const uint8_t *cdb, uint8_t off) +/* for special commands */ +static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off) { - u32 len; + cmd->bufflen = 6; + return 0; +} - len = (u32)cdb[off]; - return len; +static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off) +{ + cmd->bufflen = READ_CAP_LEN; + return 0; } -static uint32_t get_trans_len_2(const uint8_t *cdb, uint8_t off) +static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off) { - const uint8_t *p = cdb + off; - u32 len = 0; - - len |= ((u32)p[0]) << 8; - len |= ((u32)p[1]); - return len; + cmd->bufflen = 1; + return 0; } -static uint32_t get_trans_len_3(const uint8_t *cdb, uint8_t off) +static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off) { - const uint8_t *p = cdb + off; - u32 len = 0; + uint8_t *p = (uint8_t *)cmd->cdb + off; + int res = 0; - len |= ((u32)p[0]) << 16; - len |= ((u32)p[1]) << 8; - len |= ((u32)p[2]); - return len; + cmd->bufflen = 0; + cmd->bufflen |= ((u32)p[0]) << 8; + cmd->bufflen |= ((u32)p[1]); + + switch (cmd->cdb[1] & 0x1f) { + case 0: + case 1: + case 6: + if (cmd->bufflen != 0) { + PRINT_ERROR("READ POSITION: Invalid non-zero (%d) " + "allocation length for service action %x", + cmd->bufflen, cmd->cdb[1] & 0x1f); + goto out_inval; + } + break; + } + + switch (cmd->cdb[1] & 0x1f) { + case 0: + case 1: + cmd->bufflen = 20; + break; + case 6: + cmd->bufflen = 32; + break; + case 8: + cmd->bufflen = max(28, cmd->bufflen); + break; + default: + PRINT_ERROR("READ POSITION: Invalid service action %x", + cmd->cdb[1] & 0x1f); + goto out_inval; + } + +out: + return res; + +out_inval: + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); + res = 1; + goto out; } -static uint32_t get_trans_len_4(const uint8_t *cdb, uint8_t off) +static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off) { - const uint8_t *p = cdb + off; - u32 len = 0; - - len |= ((u32)p[0]) << 24; - len |= ((u32)p[1]) << 16; - len |= ((u32)p[2]) << 8; - len |= ((u32)p[3]); - return len; + cmd->bufflen = (u32)cmd->cdb[off]; + return 0; } -/* for special commands */ -static uint32_t get_trans_len_block_limit(const uint8_t *cdb, uint8_t off) +static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off) { - return 6; + const uint8_t *p = cmd->cdb + off; + + cmd->bufflen = 0; + cmd->bufflen |= ((u32)p[0]) << 8; + cmd->bufflen |= ((u32)p[1]); + + return 0; } -static uint32_t get_trans_len_read_capacity(const uint8_t *cdb, uint8_t off) +static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off) { - return READ_CAP_LEN; + const uint8_t *p = cmd->cdb + off; + + cmd->bufflen = 0; + cmd->bufflen |= ((u32)p[0]) << 16; + cmd->bufflen |= ((u32)p[1]) << 8; + cmd->bufflen |= ((u32)p[2]); + + return 0; } -static uint32_t get_trans_len_single(const uint8_t *cdb, uint8_t off) +static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off) { - return 1; + const uint8_t *p = cmd->cdb + off; + + cmd->bufflen = 0; + cmd->bufflen |= ((u32)p[0]) << 24; + cmd->bufflen |= ((u32)p[1]) << 16; + cmd->bufflen |= ((u32)p[2]) << 8; + cmd->bufflen |= ((u32)p[3]); + + return 0; } -static uint32_t get_trans_len_none(const uint8_t *cdb, uint8_t off) +static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off) { + cmd->bufflen = 0; return 0; } -int scst_get_cdb_info(const uint8_t *cdb_p, int dev_type, - enum scst_cdb_flags *op_flags, scst_data_direction *direction, - unsigned int *transfer_len, int *cdb_len, const char **op_name) +int scst_get_cdb_info(struct scst_cmd *cmd) { + int dev_type = cmd->dev->handler->type; int i, res = 0; uint8_t op; const struct scst_sdbops *ptr = NULL; TRACE_ENTRY(); - op = *cdb_p; /* get clear opcode */ + op = cmd->cdb[0]; /* get clear opcode */ TRACE_DBG("opcode=%02x, cdblen=%d bytes, tblsize=%d, " "dev_type=%d", op, SCST_GET_CDB_LEN(op), SCST_CDB_TBL_SIZE, @@ -1758,15 +1811,15 @@ TRACE(TRACE_SCSI, "Unknown opcode 0x%x for type %d", op, dev_type); res = -1; - *op_flags = SCST_INFO_INVALID; + cmd->op_flags = SCST_INFO_INVALID; goto out; } - *cdb_len = SCST_GET_CDB_LEN(op); - *op_name = ptr->op_name; - *direction = ptr->direction; - *op_flags = ptr->flags; - *transfer_len = (*ptr->get_trans_len)(cdb_p, ptr->off); + cmd->cdb_len = SCST_GET_CDB_LEN(op); + cmd->op_name = ptr->op_name; + cmd->data_direction = ptr->direction; + cmd->op_flags = ptr->flags; + res = (*ptr->get_trans_len)(cmd, ptr->off); out: TRACE_EXIT(); @@ -1788,7 +1841,7 @@ TRACE_BUFF_FLAG(TRACE_DEBUG, "Raw LUN", lun, len); - if (len < 2) { + if (unlikely(len < 2)) { PRINT_ERROR("Illegal lun length %d, expected 2 bytes or " "more", len); goto out; @@ -1797,12 +1850,10 @@ if (len > 2) { switch(len) { case 8: - { if ((*((uint64_t*)lun) & __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0) goto out_err; break; - } case 4: if (*((uint16_t*)&lun[2]) != 0) goto out_err; Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2008-03-05 18:22:01 UTC (rev 298) +++ trunk/scst/src/scst_targ.c 2008-03-10 10:59:56 UTC (rev 299) @@ -316,6 +316,7 @@ { int res = SCST_CMD_STATE_RES_CONT_SAME; struct scst_device *dev = cmd->dev; + int rc; TRACE_ENTRY(); @@ -333,12 +334,16 @@ * transfer data. */ - if (unlikely(scst_get_cdb_info(cmd->cdb, dev->handler->type, - &cmd->op_flags, &cmd->data_direction, - &cmd->bufflen, &cmd->cdb_len, &cmd->op_name) != 0)) { + rc = scst_get_cdb_info(cmd); + if (unlikely(rc != 0)) { + if (rc > 0) { + PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); + goto out_xmit; + } PRINT_ERROR("Unknown opcode 0x%02x for %s. " "Should you update scst_scsi_op_table?", cmd->cdb[0], dev->handler->name); + PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len); #ifdef USE_EXPECTED_VALUES if (scst_cmd_is_expected_set(cmd)) { TRACE(TRACE_SCSI, "Using initiator supplied values: " @@ -3615,7 +3620,6 @@ res = -1; } - mcmd->nexus_loss_check_active = 0; mcmd->completed = 1; out_unlock: @@ -4349,9 +4353,8 @@ sess->unreg_cmds_done_fn = NULL; } - spin_lock_irq(&scst_mcmd_lock); mcmd->nexus_loss_check_done = 1; - spin_unlock_irq(&scst_mcmd_lock); + mcmd->nexus_loss_check_active = 0; res = scst_set_mcmd_next_state(mcmd); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2008-04-10 11:57:31
|
Revision: 333 http://scst.svn.sourceforge.net/scst/?rev=333&view=rev Author: vlnb Date: 2008-04-10 03:57:30 -0700 (Thu, 10 Apr 2008) Log Message: ----------- Critical fix: - Fixes hang on HEAD OF QUEUE commands under high load Modified Paths: -------------- trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2008-04-08 09:11:10 UTC (rev 332) +++ trunk/scst/include/scsi_tgt.h 2008-04-10 10:57:30 UTC (rev 333) @@ -1082,9 +1082,12 @@ */ unsigned int preprocessing_only:1; - /* Set if scst_cmd_set_sn() was called */ + /* Set if cmd's SN was set */ unsigned int sn_set:1; + /* Set if hq_cmd_count was incremented */ + unsigned int hq_cmd_inced:1; + /* * Set if scst_cmd_init_stage1_done() called and the target wants * that the SN for the cmd won't be assigned until scst_restart_cmd() Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2008-04-08 09:11:10 UTC (rev 332) +++ trunk/scst/src/scst_lib.c 2008-04-10 10:57:30 UTC (rev 333) @@ -3045,6 +3045,9 @@ TRACE_ENTRY(); + if (!cmd->hq_cmd_inced) + goto out; + spin_lock_irq(&tgt_dev->sn_lock); tgt_dev->hq_cmd_count--; spin_unlock_irq(&tgt_dev->sn_lock); @@ -3059,6 +3062,7 @@ if (tgt_dev->hq_cmd_count == 0) scst_make_deferred_commands_active(tgt_dev, cmd); +out: TRACE_EXIT(); return; } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2008-04-08 09:11:10 UTC (rev 332) +++ trunk/scst/src/scst_targ.c 2008-04-10 10:57:30 UTC (rev 333) @@ -2725,11 +2725,15 @@ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; unsigned long flags; + TRACE_ENTRY(); + if (scst_is_implicit_hq(cmd)) { TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "Implicit HQ cmd %p", cmd); cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE; } + EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced); + /* Optimized for lockless fast path */ scst_check_debug_sn(cmd); @@ -2817,6 +2821,7 @@ spin_lock_irqsave(&tgt_dev->sn_lock, flags); tgt_dev->hq_cmd_count++; spin_unlock_irqrestore(&tgt_dev->sn_lock, flags); + cmd->hq_cmd_inced = 1; goto out; default: @@ -2833,6 +2838,7 @@ cmd->sn_set = 1; out: + TRACE_EXIT(); return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2008-04-21 15:04:21
|
Revision: 346 http://scst.svn.sourceforge.net/scst/?rev=346&view=rev Author: vlnb Date: 2008-04-21 08:04:10 -0700 (Mon, 21 Apr 2008) Log Message: ----------- Added possibility to create virtual removable devices Modified Paths: -------------- trunk/scst/README trunk/scst/src/dev_handlers/scst_vdisk.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2008-04-21 10:45:22 UTC (rev 345) +++ trunk/scst/README 2008-04-21 15:04:10 UTC (rev 346) @@ -466,7 +466,10 @@ This mode works ideally with high-end storage HBAs and for applications that either do not need caching between application and disk or need the large block throughput. See also below. - + + - REMOVABLE - with this flag set the device is reported to remote + initiators as removable. + * "close NAME" - closes device "NAME". * "change NAME [PATH]" - changes a virtual CD in the VDISK CDROM. Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2008-04-21 10:45:22 UTC (rev 345) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2008-04-21 15:04:10 UTC (rev 346) @@ -188,6 +188,7 @@ unsigned int nullio:1; unsigned int blockio:1; unsigned int cdrom_empty:1; + unsigned int removable:1; int virt_id; char name[16+1]; /* Name of virtual device, must be <= SCSI Model + 1 */ @@ -1094,7 +1095,7 @@ memset(buf, 0, sizeof(buf)); buf[0] = cmd->dev->handler->type; /* type dev */ - if (buf[0] == TYPE_ROM) + if ((buf[0] == TYPE_ROM) || virt_dev->removable) buf[1] = 0x80; /* removable */ /* Vital Product */ if (cmd->cdb[1] & EVPD) { @@ -2559,6 +2560,10 @@ seq_printf(seq, "BIO "); c += 4; } + if (virt_dev->removable) { + seq_printf(seq, "RM "); + c += 4; + } while (c < 16) { seq_printf(seq, " "); c++; @@ -2577,7 +2582,7 @@ char buf[128]; int i, j; - i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s", + i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s ", type, virt_dev->name); j = i; @@ -2600,6 +2605,14 @@ i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO", (j == i) ? "(" : ", "); + if (virt_dev->blockio) + i += snprintf(&buf[i], sizeof(buf) - i, "%sBLOCKIO", + (j == i) ? "(" : ", "); + + if (virt_dev->removable) + i += snprintf(&buf[i], sizeof(buf) - i, "%sREMOVABLE", + (j == i) ? "(" : ", "); + if (j == i) PRINT_INFO("%s", buf); else @@ -2759,6 +2772,10 @@ p += 7; virt_dev->blockio = 1; TRACE_DBG("%s", "BLOCKIO"); + } else if (!strncmp("REMOVABLE", p, 9)) { + p += 9; + virt_dev->removable = 1; + TRACE_DBG("%s", "REMOVABLE"); } else { PRINT_ERROR("Unknown flag \"%s\"", p); res = -EINVAL; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2008-07-09 17:19:26
|
Revision: 444 http://scst.svn.sourceforge.net/scst/?rev=444&view=rev Author: vlnb Date: 2008-07-09 10:19:24 -0700 (Wed, 09 Jul 2008) Log Message: ----------- The patch below contains the following changes: - Substituted lun_t by uint64_t and removed typedef lun_t. - Fixed the following class of checkpatch errors (two instances): ERROR: space required before the open parenthesis '(' This patch has been verified as follows: - Checked that the following command still works and did not produce any new compiler warnings: make -s clean && make -C srpt -s clean && make -s scst iscsi-scst && make -C srpt -s - Checked that the patch generated by generate-kernel-patch still applies cleanly to the 2.6.25.6 kernel, and that the patched kernel tree still compiles, installs and boots fine, and that the iscsi-scst, ib_srpt, scst_disk and scst_vdisk modules still load. - Verified that checkpatch does not report any new warnings or errors. Signed-off-by: Bart Van Assche <bar...@gm...> Modified Paths: -------------- trunk/scst/include/scst.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/include/scst.h =================================================================== --- trunk/scst/include/scst.h 2008-07-09 16:58:56 UTC (rev 443) +++ trunk/scst/include/scst.h 2008-07-09 17:19:24 UTC (rev 444) @@ -403,7 +403,11 @@ struct scst_acg_dev; struct scst_acn; -typedef uint64_t lun_t; +/* + * SCST uses 64-bit numbers to represent LUN's internally. The value + * NO_SUCH_LUN is guaranteed to be different of every valid LUN. + */ +#define NO_SUCH_LUN ((uint64_t)-1) typedef enum dma_data_direction scst_data_direction; @@ -1122,7 +1126,7 @@ struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */ - lun_t lun; /* LUN for this cmd */ + uint64_t lun; /* LUN for this cmd */ unsigned long start_time; @@ -1282,7 +1286,7 @@ /* Number of completed commands, protected by scst_mcmd_lock */ int completed_cmd_count; - lun_t lun; /* LUN for this mgmt cmd */ + uint64_t lun; /* LUN for this mgmt cmd */ /* or (and for iSCSI) */ uint64_t tag; /* tag of the corresponding cmd */ @@ -1446,7 +1450,7 @@ struct list_head sess_tgt_dev_list_entry; struct scst_device *dev; /* to save extra dereferences */ - lun_t lun; /* to save extra dereferences */ + uint64_t lun; /* to save extra dereferences */ /* How many cmds alive on this dev in this session */ atomic_t tgt_dev_cmd_count; @@ -1510,7 +1514,7 @@ */ struct scst_acg_dev { struct scst_device *dev; /* corresponding device */ - lun_t lun; /* device's LUN in this acg */ + uint64_t lun; /* device's LUN in this acg */ unsigned int rd_only_flag:1; /* if != 0, then read only */ struct scst_acg *acg; /* parent acg */ Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2008-07-09 16:58:56 UTC (rev 443) +++ trunk/scst/src/scst_lib.c 2008-07-09 17:19:24 UTC (rev 444) @@ -192,7 +192,7 @@ TRACE_ENTRY(); - switch(cmd->state) { + switch (cmd->state) { case SCST_CMD_STATE_INIT_WAIT: case SCST_CMD_STATE_INIT: case SCST_CMD_STATE_PRE_PARSE: @@ -215,7 +215,7 @@ TRACE_ENTRY(); #ifdef EXTRACHECKS - switch(cmd->state) { + switch (cmd->state) { case SCST_CMD_STATE_PRE_XMIT_RESP: case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: @@ -347,7 +347,7 @@ EXPORT_SYMBOL(scst_init_mem_lim); struct scst_acg_dev *scst_alloc_acg_dev(struct scst_acg *acg, - struct scst_device *dev, lun_t lun) + struct scst_device *dev, uint64_t lun) { struct scst_acg_dev *res; @@ -746,8 +746,8 @@ } /* The activity supposed to be suspended and scst_mutex held */ -int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, lun_t lun, - int read_only) +int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, + uint64_t lun, int read_only) { int res = 0; struct scst_acg_dev *acg_dev; @@ -1922,9 +1922,9 @@ * (see SAM-2, Section 4.12.3 page 40) * Supports 2 types of lun unpacking: peripheral and logical unit. */ -lun_t scst_unpack_lun(const uint8_t *lun, int len) +uint64_t scst_unpack_lun(const uint8_t *lun, int len) { - lun_t res = (lun_t)-1; + uint64_t res = NO_SUCH_LUN; int address_method; TRACE_ENTRY(); Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2008-07-09 16:58:56 UTC (rev 443) +++ trunk/scst/src/scst_priv.h 2008-07-09 17:19:24 UTC (rev 444) @@ -286,8 +286,8 @@ void scst_sess_free_tgt_devs(struct scst_session *sess); void scst_nexus_loss(struct scst_tgt_dev *tgt_dev); -int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, lun_t lun, - int read_only); +int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, + uint64_t lun, int read_only); int scst_acg_remove_dev(struct scst_acg *acg, struct scst_device *dev); int scst_acg_add_name(struct scst_acg *acg, const char *name); @@ -359,7 +359,7 @@ void scst_release_space(struct scst_cmd *cmd); void scst_scsi_op_list_init(void); -lun_t scst_unpack_lun(const uint8_t *lun, int len); +uint64_t scst_unpack_lun(const uint8_t *lun, int len); struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag); Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2008-07-09 16:58:56 UTC (rev 443) +++ trunk/scst/src/scst_targ.c 2008-07-09 17:19:24 UTC (rev 444) @@ -249,7 +249,7 @@ spin_unlock_irqrestore(&sess->sess_list_lock, flags); - if (unlikely(cmd->lun == (lun_t)-1)) { + if (unlikely(cmd->lun == NO_SUCH_LUN)) { PRINT_ERROR("Wrong LUN %d, finishing cmd", -1); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_lun_not_supported)); @@ -4821,7 +4821,7 @@ if (params->lun_set) { mcmd->lun = scst_unpack_lun(params->lun, params->lun_len); - if (mcmd->lun == (lun_t)-1) + if (mcmd->lun == NO_SUCH_LUN) goto out_free; mcmd->lun_set = 1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <vl...@us...> - 2008-07-15 18:00:40
|
Revision: 463 http://scst.svn.sourceforge.net/scst/?rev=463&view=rev Author: vlnb Date: 2008-07-15 11:00:19 -0700 (Tue, 15 Jul 2008) Log Message: ----------- Fix the following sparse warnings in several locations: /scst/trunk/scst/src/dev_handlers/scst_dev_handler.h:54:40: warning: incorrect type in argument 2 (different address spaces) /scst/trunk/scst/src/dev_handlers/scst_dev_handler.h:54:40: expected char const *buf /scst/trunk/scst/src/dev_handlers/scst_dev_handler.h:54:40: got char const [noderef] <asn:1>*buf Signed-off-by: Dotan Barak <do...@gm...> Modified Paths: -------------- trunk/scst/include/scst.h trunk/scst/src/scst_proc.c Modified: trunk/scst/include/scst.h =================================================================== --- trunk/scst/include/scst.h 2008-07-15 17:55:02 UTC (rev 462) +++ trunk/scst/include/scst.h 2008-07-15 18:00:19 UTC (rev 463) @@ -2548,7 +2548,7 @@ int scst_proc_log_entry_read(struct seq_file *seq, unsigned long log_level, const struct scst_proc_log *tbl); -int scst_proc_log_entry_write(struct file *file, const char *buf, +int scst_proc_log_entry_write(struct file *file, const char __user *buf, unsigned long length, unsigned long *log_level, unsigned long default_level, const struct scst_proc_log *tbl); Modified: trunk/scst/src/scst_proc.c =================================================================== --- trunk/scst/src/scst_proc.c 2008-07-15 17:55:02 UTC (rev 462) +++ trunk/scst/src/scst_proc.c 2008-07-15 18:00:19 UTC (rev 463) @@ -206,7 +206,7 @@ static DEFINE_MUTEX(scst_log_mutex); -int scst_proc_log_entry_write(struct file *file, const char *buf, +int scst_proc_log_entry_write(struct file *file, const char __user *buf, unsigned long length, unsigned long *log_level, unsigned long default_level, const struct scst_proc_log *tbl) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |