mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-23 21:51:27 +00:00
More work on scst_local:
- Add sessions (SCSI hosts) creation/delete commands as well as fixes and cleanups - Docs updated git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2073 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -14,12 +14,10 @@ except the following: you can't mount file systems or put swap on them.
|
||||
This is a limitation of Linux memory/cache manager. See SCST README file
|
||||
for details.
|
||||
|
||||
To build, simply issue 'make' in the scst-local directory.
|
||||
To build, simply issue 'make' in the scst_local directory.
|
||||
|
||||
Try 'modinfo scst_local' for a listing of module parameters so far.
|
||||
|
||||
NOTE! This is now part of scst and supports being built in the scst tree.
|
||||
|
||||
Here is how I have used it so far:
|
||||
|
||||
1. Load up scst:
|
||||
@@ -30,16 +28,12 @@ Here is how I have used it so far:
|
||||
2. Create a virtual disk (or your own device handler):
|
||||
|
||||
dd if=/dev/zero of=/some/path/vdisk1.img bs=16384 count=1000000
|
||||
# dd if=/dev/zero of=/some/path/vdisk2.img bs=16384 count=1000000
|
||||
echo "open vm_disk1 /some/path/vdisk1.img" > /proc/scsi_tgt/vdisk/vdisk
|
||||
# echo "open vm_disk2 /some/path/vdisk2.img" > /proc/scsi_tgt/vdisk/vdisk
|
||||
echo "add vm_disk1 0" > /proc/scsi_tgt/groups/Default/devices
|
||||
# echo "add vm_disk2 1" > /proc/scsi_tgt/groups/Default/devices
|
||||
echo "add_device vm_disk1 filename=/some/path/vdisk1.img" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
|
||||
|
||||
3. Load the scst_local driver:
|
||||
|
||||
insmod scst_local
|
||||
# insmod scst_local max_luns=8
|
||||
insmod scst_local add_default_tgt=1
|
||||
echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
|
||||
|
||||
4. Check what you have
|
||||
|
||||
@@ -52,9 +46,41 @@ Here is how I have used it so far:
|
||||
Vendor: TSSTcorp Model: CD/DVDW TS-L632D Rev: TO04
|
||||
Type: CD-ROM ANSI SCSI revision: 05
|
||||
Host: scsi7 Channel: 00 Id: 00 Lun: 00
|
||||
Vendor: SCST_FIO Model: vm_disk1 Rev: 101
|
||||
Vendor: SCST_FIO Model: vm_disk1 Rev: 200
|
||||
Type: Direct-Access ANSI SCSI revision: 04
|
||||
|
||||
Or for (3) you can:
|
||||
|
||||
insmod scst_local
|
||||
echo "add_target scst_local_tgt session_name=scst_local_host" >/sys/kernel/scst_tgt/targets/scst_local//mgmt
|
||||
echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
|
||||
|
||||
Or instead of manually "add_device" in (2) and (3) write and scstadmin config
|
||||
(doesn't create the session at the moment due to bug in scstadmin):
|
||||
|
||||
HANDLER vdisk_fileio {
|
||||
DEVICE vm_disk1 {
|
||||
filename /some/path/vdisk1.img
|
||||
}
|
||||
}
|
||||
|
||||
TARGET_DRIVER scst_local {
|
||||
TARGET scst_local_tgt {
|
||||
session_name=scst_local_host
|
||||
|
||||
LUN 0 vm_disk1
|
||||
}
|
||||
}
|
||||
|
||||
then:
|
||||
|
||||
insmod scst_local
|
||||
scstadmin -config conf_file.cfg
|
||||
|
||||
There can be any number of targets and sessions created. Each SCST
|
||||
session corresponds to SCSI host. You can change which LUNs assigned to
|
||||
each session by using SCST access control.
|
||||
|
||||
5. Have fun.
|
||||
|
||||
Some of this was coded while in Santa Clara, some in Bangalore, and some in
|
||||
@@ -67,13 +93,57 @@ The code still has bugs, so if you encounter any, email me the fixes at:
|
||||
I am thinking of renaming this to something more interesting.
|
||||
|
||||
|
||||
Limitations
|
||||
===========
|
||||
Sysfs interface
|
||||
===============
|
||||
|
||||
Swapping on scst_local's devices and using a writable mmap over a file
|
||||
on them are not supported due to possible OOM deadlock in the Linux
|
||||
memory/cache manager. See SCST README for more details.
|
||||
See SCST's README for a common SCST sysfs description.
|
||||
|
||||
Root of this driver is /sys/kernel/scst_tgt/targets/scst_local. It has
|
||||
the following additional entry:
|
||||
|
||||
- stats - read-only attribute with some statistical information.
|
||||
|
||||
Each target subdirectory contains the following additional entries:
|
||||
|
||||
- phys_transport_version - contains and allows to change physical
|
||||
transport version descriptor. It determines by which phisical
|
||||
interface this target will look like. See SPC for more details. By
|
||||
default, it is not defined (0).
|
||||
|
||||
- scsi_transport_version - contains and allows to change SCSI
|
||||
transport version descriptor. It determines by which SCSI
|
||||
transport this target will look like. See SPC for more details. By
|
||||
default, it is SAS.
|
||||
|
||||
Each session subdirectory contains the following additional entries:
|
||||
|
||||
- transport_id - contains this host's TransportID. This TransportID
|
||||
used to identify initiator in Persisten Reservation commands. If you
|
||||
change scsi_transport_version for a target, make sure you set for all
|
||||
its sessions correct TransportID. See SPC for more details.
|
||||
|
||||
- host - links to the corresponding SCSI host. Using it you can find
|
||||
local sg/bsg/sd/etc. devices of this session. For instance, this
|
||||
links points out to host12, so you can find your sg devices by:
|
||||
|
||||
$ lsscsi -g|grep "\[12"
|
||||
[12:0:0:0] disk SCST_FIO rd1 200 /dev/sdc /dev/sg2
|
||||
[12:0:0:1] disk SCST_FIO nullio 200 /dev/sdd /dev/sg3
|
||||
|
||||
They are /dev/sg2 and /dev/sg3.
|
||||
|
||||
The following management commands available via /sys/kernel/scst_tgt/targets/scst_local/mgmt:
|
||||
|
||||
- add_target target_name [session_name=sess_name; [session_name=sess_name1;] [...]] -
|
||||
creates a target with optionally one or more sessions.
|
||||
|
||||
- del_target target_name - deletes a target.
|
||||
|
||||
- add_session target_name session_name - adds to target target_name
|
||||
session (SCSI host) with name session_name.
|
||||
|
||||
- del_session target_name session_name - deletes session session_name
|
||||
from target target_name.
|
||||
|
||||
Note on performance
|
||||
===================
|
||||
@@ -122,3 +192,6 @@ V0.7 11-Oct-2008 (Santa Clara) Moved into the scst tree. Cleaned up some
|
||||
V0.9 30-Nov-2008 (Mtn View) Cleaned up an additional problem with symbols not
|
||||
being defined in older version of the kernel. Also
|
||||
fixed some English and cleaned up this doc.
|
||||
|
||||
V1.0 10-Sep-2010 (Moscow) Sysfs management added. Reviewed and cleaned up.
|
||||
|
||||
|
||||
@@ -90,16 +90,11 @@ static atomic_t num_aborts = ATOMIC_INIT(0);
|
||||
static atomic_t num_dev_resets = ATOMIC_INIT(0);
|
||||
static atomic_t num_target_resets = ATOMIC_INIT(0);
|
||||
|
||||
bool scst_local_add_default_tgt = true;
|
||||
bool scst_local_add_default_tgt = false;
|
||||
module_param_named(add_default_tgt, scst_local_add_default_tgt, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(add_default_host, "add (default) or not default target with "
|
||||
"default session");
|
||||
MODULE_PARM_DESC(add_default_host, "add or not (default) on start default "
|
||||
"target scst_local_tgt with default session scst_local_host");
|
||||
|
||||
/*
|
||||
* We put AEN items on a list on the scst_local_host_info structure so they
|
||||
* can be processed via a work function. We do not actually need the LUN, since
|
||||
* the whole target must be rescanned anyway.
|
||||
*/
|
||||
struct scst_aen_work_item {
|
||||
struct list_head work_list_entry;
|
||||
struct scst_aen *aen;
|
||||
@@ -116,12 +111,14 @@ struct scst_local_tgt {
|
||||
};
|
||||
|
||||
struct scst_local_sess {
|
||||
struct scst_session *scst_sess;
|
||||
|
||||
unsigned int unregistering:1;
|
||||
|
||||
struct device dev;
|
||||
struct Scsi_Host *shost;
|
||||
struct scst_local_tgt *tgt;
|
||||
|
||||
struct scst_session *scst_sess;
|
||||
|
||||
int number;
|
||||
|
||||
struct mutex tr_id_mutex;
|
||||
@@ -133,13 +130,14 @@ struct scst_local_sess {
|
||||
struct list_head aen_work_list; /* protected by aen_lock */
|
||||
|
||||
struct list_head sessions_list_entry;
|
||||
|
||||
char *initiator_name;
|
||||
};
|
||||
|
||||
#define to_scst_lcl_sess(d) \
|
||||
container_of(d, struct scst_local_sess, dev)
|
||||
|
||||
static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
const char *initiator_name, struct scst_local_sess **out_sess,
|
||||
bool locked);
|
||||
static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
const char *initiator_name, struct scst_local_sess **out_sess);
|
||||
static void scst_local_remove_adapter(struct scst_local_sess *sess);
|
||||
@@ -684,6 +682,80 @@ out_up:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t scst_local_sysfs_mgmt_cmd(char *buf)
|
||||
{
|
||||
ssize_t res;
|
||||
char *command, *target_name, *session_name;
|
||||
struct scst_local_tgt *t, *tgt;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (down_read_trylock(&scst_local_exit_rwsem) == 0)
|
||||
return -ENOENT;
|
||||
|
||||
command = scst_get_next_lexem(&buf);
|
||||
|
||||
target_name = scst_get_next_lexem(&buf);
|
||||
if (*target_name == '\0') {
|
||||
PRINT_ERROR("%s", "Target name required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
mutex_lock(&scst_local_mutex);
|
||||
|
||||
tgt = NULL;
|
||||
list_for_each_entry(t, &scst_local_tgts_list, tgts_list_entry) {
|
||||
if (strcmp(t->scst_tgt->tgt_name, target_name) == 0) {
|
||||
tgt = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tgt == NULL) {
|
||||
PRINT_ERROR("Target %s not found", target_name);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
session_name = scst_get_next_lexem(&buf);
|
||||
if (*session_name == '\0') {
|
||||
PRINT_ERROR("%s", "Session name required");
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (strcasecmp("add_session", command) == 0) {
|
||||
res = __scst_local_add_adapter(tgt, session_name, NULL, true);
|
||||
} else if (strcasecmp("del_session", command) == 0) {
|
||||
struct scst_local_sess *s, *sess = NULL;
|
||||
list_for_each_entry(s, &tgt->sessions_list,
|
||||
sessions_list_entry) {
|
||||
if (strcmp(s->scst_sess->initiator_name, session_name) == 0) {
|
||||
sess = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sess == NULL) {
|
||||
PRINT_ERROR("Session %s not found (target %s)",
|
||||
session_name, target_name);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
scst_local_remove_adapter(sess);
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
|
||||
out_up:
|
||||
up_read(&scst_local_exit_rwsem);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
static int scst_local_abort(struct scsi_cmnd *SCpnt)
|
||||
@@ -847,6 +919,27 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
|
||||
|
||||
scsi_set_resid(SCpnt, 0);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
|
||||
/*
|
||||
* Allocate a tgt_specific_structure. We need this in case we need
|
||||
* to construct a single element SGL.
|
||||
*/
|
||||
tgt_specific = kmem_cache_alloc(tgt_specific_pool, GFP_ATOMIC);
|
||||
if (!tgt_specific) {
|
||||
PRINT_ERROR("Unable to create tgt_specific (size %d)",
|
||||
sizeof(*tgt_specific));
|
||||
return -ENOMEM;
|
||||
}
|
||||
tgt_specific->cmnd = SCpnt;
|
||||
tgt_specific->done = done;
|
||||
#else
|
||||
/*
|
||||
* We save a pointer to the done routine in SCpnt->scsi_done and
|
||||
* we save that as tgt specific stuff below.
|
||||
*/
|
||||
SCpnt->scsi_done = done;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Tell the target that we have a command ... but first we need
|
||||
* to get the LUN into a format that SCST understand
|
||||
@@ -877,27 +970,6 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
|
||||
break;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
|
||||
/*
|
||||
* Allocate a tgt_specific_structure. We need this in case we need
|
||||
* to construct a single element SGL.
|
||||
*/
|
||||
tgt_specific = kmem_cache_alloc(tgt_specific_pool, GFP_ATOMIC);
|
||||
if (!tgt_specific) {
|
||||
PRINT_ERROR("Unable to create tgt_specific (size %d)",
|
||||
sizeof(*tgt_specific));
|
||||
return -ENOMEM;
|
||||
}
|
||||
tgt_specific->cmnd = SCpnt;
|
||||
tgt_specific->done = done;
|
||||
#else
|
||||
/*
|
||||
* We save a pointer to the done routine in SCpnt->scsi_done and
|
||||
* we save that as tgt specific stuff below.
|
||||
*/
|
||||
SCpnt->scsi_done = done;
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
|
||||
/*
|
||||
* If the command has a request, not a scatterlist, then convert it
|
||||
@@ -1003,17 +1075,16 @@ static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void scst_aen_work_fn(struct work_struct *work)
|
||||
/* Must be called under sess->aen_lock. Drops then reacquires it inside. */
|
||||
static void scst_process_aens(struct scst_local_sess *sess,
|
||||
bool cleanup_only)
|
||||
{
|
||||
struct scst_local_sess *sess =
|
||||
container_of(work, struct scst_local_sess, aen_work);
|
||||
struct scst_aen_work_item *work_item = NULL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MGMT_DBG("Target work (sess %p)", sess);
|
||||
TRACE_DBG("Target work sess %p", sess);
|
||||
|
||||
spin_lock(&sess->aen_lock);
|
||||
while (!list_empty(&sess->aen_work_list)) {
|
||||
work_item = list_entry(sess->aen_work_list.next,
|
||||
struct scst_aen_work_item, work_list_entry);
|
||||
@@ -1021,14 +1092,37 @@ static void scst_aen_work_fn(struct work_struct *work)
|
||||
|
||||
spin_unlock(&sess->aen_lock);
|
||||
|
||||
if (cleanup_only)
|
||||
goto done;
|
||||
|
||||
sBUG_ON(work_item->aen->event_fn != SCST_AEN_SCSI);
|
||||
|
||||
/* Let's always rescan */
|
||||
scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
|
||||
SCAN_WILD_CARD, 1);
|
||||
|
||||
done:
|
||||
scst_aen_done(work_item->aen);
|
||||
kfree(work_item);
|
||||
|
||||
spin_lock(&sess->aen_lock);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static void scst_aen_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct scst_local_sess *sess =
|
||||
container_of(work, struct scst_local_sess, aen_work);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MGMT_DBG("Target work %p)", work);
|
||||
|
||||
spin_lock(&sess->aen_lock);
|
||||
scst_process_aens(sess, false);
|
||||
spin_unlock(&sess->aen_lock);
|
||||
|
||||
TRACE_EXIT();
|
||||
@@ -1059,8 +1153,17 @@ static int scst_local_report_aen(struct scst_aen *aen)
|
||||
}
|
||||
|
||||
spin_lock(&sess->aen_lock);
|
||||
|
||||
if (unlikely(sess->unregistering)) {
|
||||
spin_unlock(&sess->aen_lock);
|
||||
kfree(work_item);
|
||||
res = SCST_AEN_RES_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_add_tail(&work_item->work_list_entry, &sess->aen_work_list);
|
||||
work_item->aen = aen;
|
||||
|
||||
spin_unlock(&sess->aen_lock);
|
||||
|
||||
schedule_work(&sess->aen_work);
|
||||
@@ -1072,6 +1175,7 @@ static int scst_local_report_aen(struct scst_aen *aen)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -1209,12 +1313,15 @@ static struct scst_tgt_template scst_local_targ_tmpl = {
|
||||
.xmit_response_atomic = 1,
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
.enabled_attr_not_needed = 1,
|
||||
.tgtt_attrs = scst_local_tgtt_attrs,
|
||||
.tgt_attrs = scst_local_tgt_attrs,
|
||||
.sess_attrs = scst_local_sess_attrs,
|
||||
.add_target = scst_local_sysfs_add_target,
|
||||
.del_target = scst_local_sysfs_del_target,
|
||||
.add_target_parameters = "session_name",
|
||||
.tgtt_attrs = scst_local_tgtt_attrs,
|
||||
.tgt_attrs = scst_local_tgt_attrs,
|
||||
.sess_attrs = scst_local_sess_attrs,
|
||||
.add_target = scst_local_sysfs_add_target,
|
||||
.del_target = scst_local_sysfs_del_target,
|
||||
.mgmt_cmd = scst_local_sysfs_mgmt_cmd,
|
||||
.add_target_parameters = "session_name",
|
||||
.mgmt_cmd_help = " echo \"add_session target_name session_name\" >mgmt\n"
|
||||
" echo \"del_session target_name session_name\" >mgmt\n",
|
||||
#endif
|
||||
.detect = scst_local_targ_detect,
|
||||
.release = scst_local_targ_release,
|
||||
@@ -1383,6 +1490,11 @@ static void scst_local_release_adapter(struct device *dev)
|
||||
if (sess == NULL)
|
||||
goto out;
|
||||
|
||||
spin_lock(&sess->aen_lock);
|
||||
sess->unregistering = 1;
|
||||
scst_process_aens(sess, true);
|
||||
spin_unlock(&sess->aen_lock);
|
||||
|
||||
cancel_work_sync(&sess->aen_work);
|
||||
|
||||
scst_unregister_session(sess->scst_sess, TRUE, NULL);
|
||||
@@ -1394,8 +1506,9 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
const char *initiator_name, struct scst_local_sess **out_sess)
|
||||
static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
const char *initiator_name, struct scst_local_sess **out_sess,
|
||||
bool locked)
|
||||
{
|
||||
int res;
|
||||
struct scst_local_sess *sess;
|
||||
@@ -1426,7 +1539,7 @@ static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
if (sess->scst_sess == NULL) {
|
||||
PRINT_ERROR("%s", "scst_register_session failed");
|
||||
kfree(sess);
|
||||
res = -ENOMEM;
|
||||
res = -EFAULT;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@@ -1436,7 +1549,11 @@ static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
|
||||
snprintf(sess->dev.bus_id, sizeof(sess->dev.bus_id), initiator_name);
|
||||
#else
|
||||
# ifdef CONFIG_SCST_PROC
|
||||
sess->dev.init_name = sess->scst_sess->initiator_name;
|
||||
# else
|
||||
sess->dev.init_name = kobject_name(&sess->scst_sess->sess_kobj);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
res = device_register(&sess->dev);
|
||||
@@ -1453,9 +1570,13 @@ static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_lock(&scst_local_mutex);
|
||||
if (!locked)
|
||||
mutex_lock(&scst_local_mutex);
|
||||
list_add_tail(&sess->sessions_list_entry, &tgt->sessions_list);
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
if (!locked)
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
|
||||
scsi_scan_target(&sess->shost->shost_gendev, 0, 0, SCAN_WILD_CARD, 1);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -1474,6 +1595,12 @@ out_free:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int scst_local_add_adapter(struct scst_local_tgt *tgt,
|
||||
const char *initiator_name, struct scst_local_sess **out_sess)
|
||||
{
|
||||
return __scst_local_add_adapter(tgt, initiator_name, out_sess, false);
|
||||
}
|
||||
|
||||
/* Must be called under scst_local_mutex */
|
||||
static void scst_local_remove_adapter(struct scst_local_sess *sess)
|
||||
{
|
||||
@@ -1507,7 +1634,7 @@ static int scst_local_add_target(const char *target_name,
|
||||
tgt->scst_tgt = scst_register_target(&scst_local_targ_tmpl, target_name);
|
||||
if (tgt->scst_tgt == NULL) {
|
||||
PRINT_ERROR("%s", "scst_register_target() failed:");
|
||||
res = -ENOMEM;
|
||||
res = -EFAULT;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@@ -1547,6 +1674,8 @@ static void __scst_local_remove_target(struct scst_local_tgt *tgt)
|
||||
|
||||
scst_unregister_target(tgt->scst_tgt);
|
||||
|
||||
kfree(tgt);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
@@ -1631,11 +1760,11 @@ static int __init scst_local_init(void)
|
||||
if (!scst_local_add_default_tgt)
|
||||
goto out;
|
||||
|
||||
ret = scst_local_add_target("default_tgt", &tgt);
|
||||
ret = scst_local_add_target("scst_local_tgt", &tgt);
|
||||
if (ret != 0)
|
||||
goto tgt_templ_unreg;
|
||||
|
||||
ret = scst_local_add_adapter(tgt, "default_scst_local_sess", NULL);
|
||||
ret = scst_local_add_adapter(tgt, "scst_local_host", NULL);
|
||||
if (ret != 0)
|
||||
goto tgt_unreg;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user