mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-20 06:52:18 +00:00
Sysfs cleanups and fixes, part 1
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1962 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+116
-85
@@ -121,28 +121,20 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
|
||||
|
||||
#else /* CONFIG_SCST_PROC */
|
||||
|
||||
static int conn_free(struct iscsi_conn *conn);
|
||||
|
||||
static void iscsi_conn_release(struct kobject *kobj)
|
||||
{
|
||||
struct iscsi_conn *conn;
|
||||
struct iscsi_target *target;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
|
||||
target = conn->target;
|
||||
|
||||
mutex_lock(&target->target_mutex);
|
||||
conn_free(conn);
|
||||
mutex_unlock(&target->target_mutex);
|
||||
conn = container_of(kobj, struct iscsi_conn, conn_kobj);
|
||||
complete_all(&conn->conn_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static struct kobj_type iscsi_conn_ktype = {
|
||||
.sysfs_ops = &scst_sysfs_ops,
|
||||
struct kobj_type iscsi_conn_ktype = {
|
||||
.release = iscsi_conn_release,
|
||||
};
|
||||
|
||||
@@ -192,7 +184,7 @@ static ssize_t iscsi_conn_ip_show(struct kobject *kobj,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
|
||||
conn = container_of(kobj, struct iscsi_conn, conn_kobj);
|
||||
|
||||
pos = iscsi_get_initiator_ip(conn, buf, SCST_SYSFS_BLOCK_SIZE);
|
||||
|
||||
@@ -211,7 +203,7 @@ static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
|
||||
conn = container_of(kobj, struct iscsi_conn, conn_kobj);
|
||||
|
||||
pos = sprintf(buf, "%u", conn->cid);
|
||||
|
||||
@@ -230,7 +222,7 @@ static ssize_t iscsi_conn_state_show(struct kobject *kobj,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
|
||||
conn = container_of(kobj, struct iscsi_conn, conn_kobj);
|
||||
|
||||
pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
|
||||
|
||||
@@ -241,6 +233,102 @@ static ssize_t iscsi_conn_state_show(struct kobject *kobj,
|
||||
static struct kobj_attribute iscsi_conn_state_attr =
|
||||
__ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
|
||||
|
||||
static void conn_sysfs_del(struct iscsi_conn *conn)
|
||||
{
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
kobject_del(&conn->conn_kobj);
|
||||
kobject_put(&conn->conn_kobj);
|
||||
|
||||
rc = wait_for_completion_timeout(&conn->conn_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for conn %p (%d refs)...", conn,
|
||||
atomic_read(&conn->conn_kobj.kref.refcount));
|
||||
wait_for_completion(&conn->conn_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs "
|
||||
"entry for conn %p", conn);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static int conn_sysfs_add(struct iscsi_conn *conn)
|
||||
{
|
||||
int res;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_conn *c;
|
||||
int n = 1;
|
||||
char addr[64];
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
iscsi_get_initiator_ip(conn, addr, sizeof(addr));
|
||||
|
||||
restart:
|
||||
list_for_each_entry(c, &session->conn_list, conn_list_entry) {
|
||||
if (strcmp(addr, kobject_name(&conn->conn_kobj)) == 0) {
|
||||
char c_addr[64];
|
||||
|
||||
iscsi_get_initiator_ip(conn, c_addr, sizeof(c_addr));
|
||||
|
||||
TRACE_DBG("Duplicated conn from the same initiator "
|
||||
"%s found", c_addr);
|
||||
|
||||
snprintf(addr, sizeof(addr), "%s_%d", c_addr, n);
|
||||
n++;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
init_completion(&conn->conn_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&conn->conn_kobj, &iscsi_conn_ktype,
|
||||
scst_sysfs_get_sess_kobj(session->scst_sess), addr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs entries for conn %s",
|
||||
addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
TRACE_DBG("conn %p, conn_kobj %p", conn, &conn->conn_kobj);
|
||||
|
||||
res = sysfs_create_file(&conn->conn_kobj,
|
||||
&iscsi_conn_state_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_state_attr.attr.name, addr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&conn->conn_kobj,
|
||||
&iscsi_conn_cid_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_cid_attr.attr.name, addr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&conn->conn_kobj,
|
||||
&iscsi_conn_ip_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_ip_attr.attr.name, addr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_err:
|
||||
conn_sysfs_del(conn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
/* target_mutex supposed to be locked */
|
||||
@@ -665,19 +753,21 @@ out:
|
||||
}
|
||||
|
||||
/* target_mutex supposed to be locked */
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
int conn_free(struct iscsi_conn *conn)
|
||||
#else
|
||||
static int conn_free(struct iscsi_conn *conn)
|
||||
#endif
|
||||
{
|
||||
struct iscsi_session *session = conn->session;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
|
||||
session, (long long unsigned int)session->sid, conn->cid);
|
||||
|
||||
del_timer_sync(&conn->rsp_timer);
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
conn_sysfs_del(conn);
|
||||
#endif
|
||||
|
||||
sBUG_ON(atomic_read(&conn->conn_ref_cnt) != 0);
|
||||
sBUG_ON(!list_empty(&conn->cmd_list));
|
||||
sBUG_ON(!list_empty(&conn->write_list));
|
||||
@@ -722,11 +812,6 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
|
||||
{
|
||||
struct iscsi_conn *conn;
|
||||
int res = 0;
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
struct iscsi_conn *c;
|
||||
int n = 1;
|
||||
char addr[64];
|
||||
#endif
|
||||
|
||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||
if (!conn) {
|
||||
@@ -758,7 +843,7 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
|
||||
conn->ddigest_type = session->sess_params.data_digest;
|
||||
res = digest_init(conn);
|
||||
if (res != 0)
|
||||
goto out_err_free1;
|
||||
goto out_free_iov;
|
||||
|
||||
conn->target = session->target;
|
||||
spin_lock_init(&conn->cmd_list_lock);
|
||||
@@ -794,61 +879,13 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
|
||||
|
||||
res = conn_setup_sock(conn);
|
||||
if (res != 0)
|
||||
goto out_err_free2;
|
||||
goto out_fput;
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
iscsi_get_initiator_ip(conn, addr, sizeof(addr));
|
||||
|
||||
restart:
|
||||
list_for_each_entry(c, &session->conn_list, conn_list_entry) {
|
||||
if (strcmp(addr, kobject_name(&conn->iscsi_conn_kobj)) == 0) {
|
||||
char c_addr[64];
|
||||
|
||||
iscsi_get_initiator_ip(conn, c_addr, sizeof(c_addr));
|
||||
|
||||
TRACE_DBG("Duplicated conn from the same initiator "
|
||||
"%s found", c_addr);
|
||||
|
||||
snprintf(addr, sizeof(addr), "%s_%d", c_addr, n);
|
||||
n++;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
res = kobject_init_and_add(&conn->iscsi_conn_kobj, &iscsi_conn_ktype,
|
||||
scst_sysfs_get_sess_kobj(session->scst_sess), addr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs entries for conn %s",
|
||||
addr);
|
||||
goto out_err_free2;
|
||||
}
|
||||
|
||||
TRACE_DBG("conn %p, iscsi_conn_kobj %p", conn, &conn->iscsi_conn_kobj);
|
||||
|
||||
res = sysfs_create_file(&conn->iscsi_conn_kobj,
|
||||
&iscsi_conn_state_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_state_attr.attr.name, addr);
|
||||
goto out_err_free3;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&conn->iscsi_conn_kobj,
|
||||
&iscsi_conn_cid_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_cid_attr.attr.name, addr);
|
||||
goto out_err_free3;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&conn->iscsi_conn_kobj,
|
||||
&iscsi_conn_ip_attr.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
|
||||
iscsi_conn_ip_attr.attr.name, addr);
|
||||
goto out_err_free3;
|
||||
}
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
res = conn_sysfs_add(conn);
|
||||
if (res != 0)
|
||||
goto out_fput;
|
||||
#endif
|
||||
|
||||
list_add_tail(&conn->conn_list_entry, &session->conn_list);
|
||||
|
||||
@@ -857,16 +894,10 @@ restart:
|
||||
out:
|
||||
return res;
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
out_err_free3:
|
||||
kobject_put(&conn->iscsi_conn_kobj);
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
out_err_free2:
|
||||
out_fput:
|
||||
fput(conn->file);
|
||||
|
||||
out_err_free1:
|
||||
out_free_iov:
|
||||
free_page((unsigned long)conn->read_iov);
|
||||
|
||||
out_err_free_conn:
|
||||
|
||||
@@ -3881,6 +3881,8 @@ static int __init iscsi_init(void)
|
||||
err = iscsi_procfs_init();
|
||||
if (err < 0)
|
||||
goto out_reg_tmpl;
|
||||
#else
|
||||
iscsi_conn_ktype.sysfs_ops = scst_sysfs_get_sysfs_ops();
|
||||
#endif
|
||||
|
||||
num = max((int)num_online_cpus(), 2);
|
||||
|
||||
@@ -88,7 +88,6 @@ struct iscsi_target {
|
||||
struct list_head target_list_entry;
|
||||
u32 tid;
|
||||
|
||||
/* Protected by iscsi_sysfs_mutex */
|
||||
unsigned int tgt_enabled:1;
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
@@ -281,8 +280,9 @@ struct iscsi_conn {
|
||||
u32 nop_in_ttt;
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
/* Doesn't need any protection */
|
||||
struct kobject iscsi_conn_kobj;
|
||||
/* Don't need any protection */
|
||||
struct kobject conn_kobj;
|
||||
struct completion conn_kobj_release_cmpl;
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
};
|
||||
|
||||
@@ -504,13 +504,14 @@ extern int set_scst_preliminary_status_rsp(struct iscsi_cmnd *req,
|
||||
bool get_data, int key, int asc, int ascq);
|
||||
|
||||
/* conn.c */
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
extern struct kobj_type iscsi_conn_ktype;
|
||||
#endif
|
||||
extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
|
||||
extern void conn_reinst_finished(struct iscsi_conn *);
|
||||
extern int __add_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
|
||||
extern int __del_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
extern int conn_free(struct iscsi_conn *);
|
||||
#endif
|
||||
extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn);
|
||||
#define ISCSI_CONN_ACTIVE_CLOSE 1
|
||||
#define ISCSI_CONN_DELETING 2
|
||||
|
||||
@@ -562,13 +562,9 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
sid = session->sid;
|
||||
cid = conn->cid;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
mutex_lock(&target->target_mutex);
|
||||
conn_free(conn);
|
||||
mutex_unlock(&target->target_mutex);
|
||||
#else
|
||||
kobject_put(&conn->iscsi_conn_kobj);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We can't send E_CONN_CLOSE earlier, because otherwise we would have
|
||||
|
||||
@@ -283,7 +283,7 @@ static inline int q2t_issue_marker(scsi_qla_host_t *ha, int ha_locked)
|
||||
*/
|
||||
static int q2t_target_detect(struct scst_tgt_template *tgtt)
|
||||
{
|
||||
int res;
|
||||
int res, rc;
|
||||
struct qla_tgt_data t = {
|
||||
.magic = QLA2X_TARGET_MAGIC,
|
||||
.tgt24_atio_pkt = q24_atio_pkt,
|
||||
@@ -297,21 +297,23 @@ static int q2t_target_detect(struct scst_tgt_template *tgtt)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
res = qla2xxx_tgt_register_driver(&t);
|
||||
if (res < 0) {
|
||||
rc = qla2xxx_tgt_register_driver(&t);
|
||||
if (rc < 0) {
|
||||
res = rc;
|
||||
PRINT_ERROR("Unable to register driver: %d", res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (res != QLA2X_INITIATOR_MAGIC) {
|
||||
PRINT_ERROR("Wrong version of the initiator part: %d",
|
||||
res);
|
||||
if (rc != QLA2X_INITIATOR_MAGIC) {
|
||||
PRINT_ERROR("Wrong version of the initiator part: %d", rc);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
qla2xxx_add_targets();
|
||||
|
||||
res = 0;
|
||||
|
||||
PRINT_INFO("%s", "Target mode driver for QLogic 2x00 controller "
|
||||
"registered successfully");
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@ To be done
|
||||
|
||||
- See http://scst.sourceforge.net/contributing.html
|
||||
|
||||
- Add choosing default number of threads for BLOCKIO based on "rotational"
|
||||
sysfs attribute of the device.
|
||||
|
||||
- Allow to set via sysfs of what returned for "rotational" attribute to
|
||||
remote initiators.
|
||||
|
||||
- Remove cmd->data_len
|
||||
|
||||
- Reimplement VDISK handler with usage of async. read/write operations
|
||||
|
||||
+28
-49
@@ -953,11 +953,9 @@ struct scst_tgt_template {
|
||||
struct proc_dir_entry *proc_tgt_root;
|
||||
#endif
|
||||
|
||||
/* Set if tgtt_kobj was initialized */
|
||||
unsigned int tgtt_kobj_initialized:1;
|
||||
|
||||
struct kobject tgtt_kobj; /* kobject for this struct */
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion tgtt_kobj_release_cmpl;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -1261,8 +1259,6 @@ struct scst_dev_type {
|
||||
struct proc_dir_entry *proc_dev_type_root;
|
||||
#endif
|
||||
|
||||
unsigned int devt_kobj_initialized:1;
|
||||
|
||||
struct kobject devt_kobj; /* main handlers/driver */
|
||||
|
||||
/* To wait until devt_kobj released */
|
||||
@@ -1281,12 +1277,11 @@ struct scst_tgt {
|
||||
|
||||
struct scst_tgt_template *tgtt; /* corresponding target template */
|
||||
|
||||
struct scst_acg *default_acg; /* The default acg for this target. */
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
struct scst_acg *default_acg; /* default acg for this target */
|
||||
|
||||
/*
|
||||
* Device ACG groups
|
||||
*/
|
||||
struct list_head tgt_acg_list;
|
||||
struct list_head tgt_acg_list; /* target ACG groups */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum SG table size. Needed here, since different cards on the
|
||||
@@ -1328,17 +1323,8 @@ struct scst_tgt {
|
||||
char *default_group_name;
|
||||
#endif
|
||||
|
||||
/* Set if tgt_kobj was initialized */
|
||||
unsigned int tgt_kobj_initialized:1;
|
||||
|
||||
/* Set if scst_tgt_sysfs_prepare_put() was called for tgt_kobj */
|
||||
unsigned int tgt_kobj_put_prepared:1;
|
||||
|
||||
/*
|
||||
* Used to protect sysfs attributes to be called after this
|
||||
* object was unregistered.
|
||||
*/
|
||||
struct rw_semaphore tgt_attr_rwsem;
|
||||
/* sysfs release completion */
|
||||
struct completion tgt_kobj_release_cmpl;
|
||||
|
||||
struct kobject tgt_kobj; /* main targets/target kobject */
|
||||
struct kobject *tgt_sess_kobj; /* target/sessions/ */
|
||||
@@ -1469,14 +1455,10 @@ struct scst_session {
|
||||
/* Used if scst_unregister_session() called in wait mode */
|
||||
struct completion *shutdown_compl;
|
||||
|
||||
/* Set if sess_kobj was initialized */
|
||||
unsigned int sess_kobj_initialized:1;
|
||||
/* sysfs release completion */
|
||||
struct completion sess_kobj_release_cmpl;
|
||||
|
||||
/*
|
||||
* Used to protect sysfs attributes to be called after this
|
||||
* object was unregistered.
|
||||
*/
|
||||
struct rw_semaphore sess_attr_rwsem;
|
||||
unsigned int sess_kobj_ready:1;
|
||||
|
||||
struct kobject sess_kobj; /* kobject for this struct */
|
||||
|
||||
@@ -2012,9 +1994,6 @@ struct scst_device {
|
||||
/* If set, dev is read only */
|
||||
unsigned short rd_only:1;
|
||||
|
||||
/* Set if tgt_kobj was initialized */
|
||||
unsigned short dev_kobj_initialized:1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/*************************************************************
|
||||
@@ -2162,11 +2141,8 @@ struct scst_device {
|
||||
/* Threads pool type of the device. Valid only if threads_num > 0. */
|
||||
enum scst_dev_type_threads_pool_type threads_pool_type;
|
||||
|
||||
/*
|
||||
* Used to protect sysfs attributes to be called after this
|
||||
* object was unregistered.
|
||||
*/
|
||||
struct rw_semaphore dev_attr_rwsem;
|
||||
/* sysfs release completion */
|
||||
struct completion dev_kobj_release_cmpl;
|
||||
|
||||
struct kobject dev_kobj; /* kobject for this struct */
|
||||
struct kobject *dev_exp_kobj; /* exported groups */
|
||||
@@ -2318,9 +2294,6 @@ struct scst_acg_dev {
|
||||
/* If set, the corresponding LU is read only */
|
||||
unsigned int rd_only:1;
|
||||
|
||||
/* Set if acg_dev_kobj was initialized */
|
||||
unsigned int acg_dev_kobj_initialized:1;
|
||||
|
||||
struct scst_acg *acg; /* parent acg */
|
||||
|
||||
/* List entry in dev->dev_acg_dev_list */
|
||||
@@ -2331,6 +2304,12 @@ struct scst_acg_dev {
|
||||
|
||||
/* kobject for this structure */
|
||||
struct kobject acg_dev_kobj;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion acg_dev_kobj_release_cmpl;
|
||||
|
||||
/* Name of the link to the corresponding LUN */
|
||||
char acg_dev_link_name[20];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2361,8 +2340,10 @@ struct scst_acg {
|
||||
/* Type of I/O initiators groupping */
|
||||
int acg_io_grouping_type;
|
||||
|
||||
unsigned int acg_kobj_initialized:1;
|
||||
unsigned int in_tgt_acg_list:1;
|
||||
unsigned int tgt_acg:1;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion acg_kobj_release_cmpl;
|
||||
|
||||
/* kobject for this structure */
|
||||
struct kobject acg_kobj;
|
||||
@@ -2378,8 +2359,10 @@ struct scst_acg {
|
||||
* incoming sessions will be assigned to appropriate ACG.
|
||||
*/
|
||||
struct scst_acn {
|
||||
/* Initiator's name */
|
||||
const char *name;
|
||||
struct scst_acg *acg; /* owner ACG */
|
||||
|
||||
const char *name; /* initiator's name */
|
||||
|
||||
/* List entry in acg->acn_list */
|
||||
struct list_head acn_list_entry;
|
||||
|
||||
@@ -2430,8 +2413,6 @@ struct scst_aen {
|
||||
/*
|
||||
* Registers target template.
|
||||
* Returns 0 on success or appropriate error code otherwise.
|
||||
*
|
||||
* Note: *vtt must be static!
|
||||
*/
|
||||
int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
const char *version);
|
||||
@@ -2465,8 +2446,6 @@ int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
|
||||
/*
|
||||
* Registers dev handler driver for virtual devices (eg VDISK).
|
||||
* Returns 0 on success or appropriate error code otherwise.
|
||||
*
|
||||
* Note: *dev_type must be static!
|
||||
*/
|
||||
static inline int scst_register_virtual_dev_driver(
|
||||
struct scst_dev_type *dev_type)
|
||||
@@ -3508,9 +3487,9 @@ struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root,
|
||||
#else /* CONFIG_SCST_PROC */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
|
||||
extern const struct sysfs_ops scst_sysfs_ops;
|
||||
const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void);
|
||||
#else
|
||||
extern struct sysfs_ops scst_sysfs_ops;
|
||||
struct sysfs_ops *scst_sysfs_get_sysfs_ops(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -2525,7 +2525,7 @@ static int dev_user_attach(struct scst_device *sdev)
|
||||
|
||||
dev->sdev = sdev;
|
||||
|
||||
PRINT_INFO("Attached user space SCSI target virtual device \"%s\"",
|
||||
PRINT_INFO("Attached user space virtual device \"%s\"",
|
||||
dev->name);
|
||||
|
||||
out:
|
||||
@@ -2541,7 +2541,7 @@ static void dev_user_detach(struct scst_device *sdev)
|
||||
|
||||
TRACE_DBG("virt_id %d", sdev->virt_id);
|
||||
|
||||
PRINT_INFO("Detached user space SCSI target virtual device \"%s\"",
|
||||
PRINT_INFO("Detached user space virtual device \"%s\"",
|
||||
dev->name);
|
||||
|
||||
/* dev will be freed by the caller */
|
||||
|
||||
@@ -788,7 +788,7 @@ static void vdisk_detach(struct scst_device *dev)
|
||||
|
||||
TRACE_DBG("virt_id %d", dev->virt_id);
|
||||
|
||||
PRINT_INFO("Detached SCSI target virtual device %s (\"%s\")",
|
||||
PRINT_INFO("Detached virtual device %s (\"%s\")",
|
||||
virt_dev->name, vdev_get_filename(virt_dev));
|
||||
|
||||
/* virt_dev will be freed by the caller */
|
||||
|
||||
+251
-236
@@ -1800,8 +1800,10 @@ next:
|
||||
old_acg->acg_name, acg->acg_name);
|
||||
list_move_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
scst_recreate_sess_luns_link(sess);
|
||||
/* Ignore possible error, since we can't do anything on it */
|
||||
#endif
|
||||
|
||||
if (luns_changed) {
|
||||
scst_report_luns_changed_sess(sess);
|
||||
@@ -2400,7 +2402,7 @@ restart:
|
||||
return;
|
||||
}
|
||||
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
static bool __scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
const struct scst_tgt *t)
|
||||
{
|
||||
bool res = true;
|
||||
@@ -2408,7 +2410,6 @@ bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
list_for_each_entry(tgtt, &scst_template_list,
|
||||
scst_template_list_entry) {
|
||||
struct scst_tgt *tgt;
|
||||
@@ -2424,6 +2425,21 @@ bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be locked */
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
const struct scst_tgt *t)
|
||||
{
|
||||
bool res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
res = __scst_is_relative_target_port_id_unique(id, t);
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -2437,12 +2453,17 @@ int gen_relative_target_port_id(uint16_t *id)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (mutex_lock_interruptible(&scst_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rti_prev = rti;
|
||||
do {
|
||||
if (scst_is_relative_target_port_id_unique(rti, NULL)) {
|
||||
if (__scst_is_relative_target_port_id_unique(rti, NULL)) {
|
||||
*id = (uint16_t)rti++;
|
||||
res = 0;
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
}
|
||||
rti++;
|
||||
if (rti > SCST_MAX_REL_TGT_ID)
|
||||
@@ -2451,11 +2472,15 @@ int gen_relative_target_port_id(uint16_t *id)
|
||||
|
||||
PRINT_ERROR("%s", "Unable to create unique relative target port id");
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
|
||||
{
|
||||
struct scst_tgt *t;
|
||||
@@ -2487,6 +2512,8 @@ int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
|
||||
scst_free_tgt(t);
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
INIT_LIST_HEAD(&t->tgt_acg_list);
|
||||
#endif
|
||||
|
||||
*tgt = t;
|
||||
@@ -2496,13 +2523,11 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void scst_free_tgt(struct scst_tgt *tgt)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (tgt->default_acg != NULL)
|
||||
scst_free_acg(tgt->default_acg);
|
||||
|
||||
kfree(tgt->tgt_name);
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
kfree(tgt->default_group_name);
|
||||
@@ -2628,23 +2653,11 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void scst_acg_dev_destroy(struct scst_acg_dev *acg_dev)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
if ((acg_dev->dev != NULL) && acg_dev->dev->dev_kobj_initialized)
|
||||
kobject_put(&acg_dev->dev->dev_kobj);
|
||||
#endif
|
||||
|
||||
kmem_cache_free(scst_acgd_cachep, acg_dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
static void scst_free_acg_dev(struct scst_acg_dev *acg_dev)
|
||||
/*
|
||||
* The activity supposed to be suspended and scst_mutex held or the
|
||||
* corresponding target supposed to be stopped.
|
||||
*/
|
||||
static void scst_del_free_acg_dev(struct scst_acg_dev *acg_dev, bool del_sysfs)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2653,16 +2666,124 @@ static void scst_free_acg_dev(struct scst_acg_dev *acg_dev)
|
||||
list_del(&acg_dev->acg_dev_list_entry);
|
||||
list_del(&acg_dev->dev_acg_dev_list_entry);
|
||||
|
||||
if (acg_dev->acg_dev_kobj_initialized) {
|
||||
kobject_del(&acg_dev->acg_dev_kobj);
|
||||
kobject_put(&acg_dev->acg_dev_kobj);
|
||||
} else
|
||||
scst_acg_dev_destroy(acg_dev);
|
||||
if (del_sysfs)
|
||||
scst_acg_dev_sysfs_del(acg_dev);
|
||||
|
||||
kmem_cache_free(scst_acgd_cachep, acg_dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
struct scst_device *dev, uint64_t lun, int read_only,
|
||||
bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_session *sess;
|
||||
LIST_HEAD(tmp_tgt_dev_list);
|
||||
bool del_sysfs = true;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
INIT_LIST_HEAD(&tmp_tgt_dev_list);
|
||||
|
||||
acg_dev = scst_alloc_acg_dev(acg, dev, lun);
|
||||
if (acg_dev == NULL) {
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
acg_dev->rd_only = read_only;
|
||||
|
||||
TRACE_DBG("Adding acg_dev %p to acg_dev_list and dev_acg_dev_list",
|
||||
acg_dev);
|
||||
list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list);
|
||||
list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
|
||||
|
||||
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
|
||||
res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
|
||||
if (res == -EPERM)
|
||||
continue;
|
||||
else if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
|
||||
&tmp_tgt_dev_list);
|
||||
}
|
||||
|
||||
res = scst_acg_dev_sysfs_create(acg_dev, parent);
|
||||
if (res != 0) {
|
||||
del_sysfs = false;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
PRINT_INFO("Added device %s to group %s (LUN %lld, "
|
||||
"rd_only %d)", dev->virt_name, acg->acg_name,
|
||||
(long long unsigned int)lun, read_only);
|
||||
|
||||
if (out_acg_dev != NULL)
|
||||
*out_acg_dev = acg_dev;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_free:
|
||||
list_for_each_entry(tgt_dev, &tmp_tgt_dev_list,
|
||||
extra_tgt_dev_list_entry) {
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_del_free_acg_dev(acg_dev, del_sysfs);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
bool gen_scst_report_luns_changed)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acg_dev *acg_dev = NULL, *a;
|
||||
struct scst_tgt_dev *tgt_dev, *tt;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
if (a->lun == lun) {
|
||||
acg_dev = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (acg_dev == NULL) {
|
||||
PRINT_ERROR("Device is not found in group %s", acg->acg_name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if (tgt_dev->acg_dev == acg_dev)
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
|
||||
scst_del_free_acg_dev(acg_dev, true);
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
PRINT_INFO("Removed LUN %lld from group %s", (unsigned long long)lun,
|
||||
acg->acg_name);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
const char *acg_name)
|
||||
@@ -2695,10 +2816,17 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
scst_check_reassign_sessions();
|
||||
#else
|
||||
if (tgt != NULL) {
|
||||
int rc;
|
||||
|
||||
TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
|
||||
tgt->tgt_name);
|
||||
|
||||
list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
|
||||
acg->in_tgt_acg_list = 1;
|
||||
acg->tgt_acg = 1;
|
||||
|
||||
rc = scst_acg_sysfs_create(tgt, acg);
|
||||
if (rc != 0)
|
||||
goto out_del;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2706,16 +2834,60 @@ out:
|
||||
TRACE_EXIT_HRES(acg);
|
||||
return acg;
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
out_del:
|
||||
list_del(&acg->acg_list_entry);
|
||||
#endif
|
||||
|
||||
out_free:
|
||||
kfree(acg);
|
||||
acg = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
void scst_free_acg(struct scst_acg *acg)
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
void scst_del_free_acg(struct scst_acg *acg)
|
||||
{
|
||||
struct scst_acn *acn, *acnt;
|
||||
struct scst_acg_dev *acg_dev, *acg_dev_tmp;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Clearing acg %s from list", acg->acg_name);
|
||||
|
||||
sBUG_ON(!list_empty(&acg->acg_sess_list));
|
||||
|
||||
/* Freeing acg_devs */
|
||||
list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list,
|
||||
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,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if (tgt_dev->acg_dev == acg_dev)
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_del_free_acg_dev(acg_dev, true);
|
||||
}
|
||||
|
||||
/* Freeing names */
|
||||
list_for_each_entry_safe(acn, acnt, &acg->acn_list, acn_list_entry) {
|
||||
scst_del_free_acn(acn,
|
||||
list_is_last(&acn->acn_list_entry, &acg->acn_list));
|
||||
}
|
||||
INIT_LIST_HEAD(&acg->acn_list);
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
list_del(&acg->acg_list_entry);
|
||||
#else
|
||||
if (acg->tgt_acg) {
|
||||
TRACE_DBG("Removing acg %s from list", acg->acg_name);
|
||||
list_del(&acg->acg_list_entry);
|
||||
|
||||
scst_acg_sysfs_del(acg);
|
||||
}
|
||||
#endif
|
||||
|
||||
sBUG_ON(!list_empty(&acg->acg_sess_list));
|
||||
sBUG_ON(!list_empty(&acg->acg_dev_list));
|
||||
sBUG_ON(!list_empty(&acg->acn_list));
|
||||
@@ -2727,68 +2899,7 @@ void scst_free_acg(struct scst_acg *acg)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
void scst_clear_acg(struct scst_acg *acg)
|
||||
{
|
||||
struct scst_acn *n, *nn;
|
||||
struct scst_acg_dev *acg_dev, *acg_dev_tmp;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Clearing acg %s from list", acg->acg_name);
|
||||
|
||||
sBUG_ON(!list_empty(&acg->acg_sess_list));
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
list_del(&acg->acg_list_entry);
|
||||
#else
|
||||
if (acg->in_tgt_acg_list) {
|
||||
TRACE_DBG("Removing acg %s from list", acg->acg_name);
|
||||
list_del(&acg->acg_list_entry);
|
||||
acg->in_tgt_acg_list = 0;
|
||||
}
|
||||
#endif
|
||||
/* Freeing acg_devs */
|
||||
list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list,
|
||||
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,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if (tgt_dev->acg_dev == acg_dev)
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_free_acg_dev(acg_dev);
|
||||
}
|
||||
|
||||
/* Freeing names */
|
||||
list_for_each_entry_safe(n, nn, &acg->acn_list,
|
||||
acn_list_entry) {
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
scst_acg_remove_acn(n);
|
||||
if (list_is_last(&n->acn_list_entry, &acg->acn_list))
|
||||
scst_check_reassign_sessions();
|
||||
#else
|
||||
scst_acn_sysfs_del(acg, n,
|
||||
list_is_last(&n->acn_list_entry, &acg->acn_list));
|
||||
#endif
|
||||
}
|
||||
INIT_LIST_HEAD(&acg->acn_list);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
void scst_destroy_acg(struct scst_acg *acg)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_clear_acg(acg);
|
||||
scst_free_acg(acg);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name)
|
||||
@@ -2808,6 +2919,8 @@ struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name)
|
||||
return acg_ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
static struct scst_tgt_dev *scst_find_shared_io_tgt_dev(
|
||||
struct scst_tgt_dev *tgt_dev)
|
||||
@@ -3462,115 +3575,17 @@ void scst_sess_free_tgt_devs(struct scst_session *sess)
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
uint64_t lun, int read_only, bool gen_scst_report_luns_changed)
|
||||
int scst_acg_add_acn(struct scst_acg *acg, const char *name)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_session *sess;
|
||||
LIST_HEAD(tmp_tgt_dev_list);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
INIT_LIST_HEAD(&tmp_tgt_dev_list);
|
||||
|
||||
acg_dev = scst_alloc_acg_dev(acg, dev, lun);
|
||||
if (acg_dev == NULL) {
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
acg_dev->rd_only = read_only;
|
||||
|
||||
TRACE_DBG("Adding acg_dev %p to acg_dev_list and dev_acg_dev_list",
|
||||
acg_dev);
|
||||
list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list);
|
||||
list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
|
||||
|
||||
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
|
||||
res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
|
||||
if (res == -EPERM)
|
||||
continue;
|
||||
else if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
|
||||
&tmp_tgt_dev_list);
|
||||
}
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
PRINT_INFO("Added device %s to group %s (LUN %lld, "
|
||||
"rd_only %d)", dev->virt_name, acg->acg_name,
|
||||
(long long unsigned int)lun, read_only);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_free:
|
||||
list_for_each_entry(tgt_dev, &tmp_tgt_dev_list,
|
||||
extra_tgt_dev_list_entry) {
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_free_acg_dev(acg_dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
int scst_acg_remove_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
bool gen_scst_report_luns_changed)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acg_dev *acg_dev = NULL, *a;
|
||||
struct scst_tgt_dev *tgt_dev, *tt;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
if (a->dev == dev) {
|
||||
acg_dev = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (acg_dev == NULL) {
|
||||
PRINT_ERROR("Device is not found in group %s", acg->acg_name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tgt_dev, tt, &dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if (tgt_dev->acg_dev == acg_dev)
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_free_acg_dev(acg_dev);
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
PRINT_INFO("Removed device %s from group %s", dev->virt_name,
|
||||
acg->acg_name);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
int scst_acg_add_name(struct scst_acg *acg, const char *name)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acn *n;
|
||||
struct scst_acn *acn;
|
||||
int len;
|
||||
char *nm;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(n->name, name) == 0) {
|
||||
list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(acn->name, name) == 0) {
|
||||
PRINT_ERROR("Name %s already exists in group %s",
|
||||
name, acg->acg_name);
|
||||
res = -EEXIST;
|
||||
@@ -3578,13 +3593,15 @@ int scst_acg_add_name(struct scst_acg *acg, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
n = kmalloc(sizeof(*n), GFP_KERNEL);
|
||||
if (n == NULL) {
|
||||
acn = kzalloc(sizeof(*acn), GFP_KERNEL);
|
||||
if (acn == NULL) {
|
||||
PRINT_ERROR("%s", "Unable to allocate scst_acn");
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acn->acg = acg;
|
||||
|
||||
len = strlen(name);
|
||||
nm = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (nm == NULL) {
|
||||
@@ -3594,17 +3611,17 @@ int scst_acg_add_name(struct scst_acg *acg, const char *name)
|
||||
}
|
||||
|
||||
strcpy(nm, name);
|
||||
n->name = nm;
|
||||
acn->name = nm;
|
||||
|
||||
res = scst_create_acn_sysfs(acg, n);
|
||||
res = scst_acn_sysfs_create(acn);
|
||||
if (res != 0)
|
||||
goto out_free_nm;
|
||||
|
||||
list_add_tail(&n->acn_list_entry, &acg->acn_list);
|
||||
list_add_tail(&acn->acn_list_entry, &acg->acn_list);
|
||||
|
||||
out:
|
||||
if (res == 0) {
|
||||
PRINT_INFO("Added name '%s' to group '%s'", name, acg->acg_name);
|
||||
PRINT_INFO("Added name %s to group %s", name, acg->acg_name);
|
||||
scst_check_reassign_sessions();
|
||||
}
|
||||
|
||||
@@ -3615,42 +3632,48 @@ out_free_nm:
|
||||
kfree(nm);
|
||||
|
||||
out_free:
|
||||
kfree(n);
|
||||
kfree(acn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
struct scst_acn *scst_acg_find_name(struct scst_acg *acg, const char *name)
|
||||
void scst_del_free_acn(struct scst_acn *acn, bool reassign)
|
||||
{
|
||||
struct scst_acn *n;
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_del(&acn->acn_list_entry);
|
||||
|
||||
scst_acn_sysfs_del(acn);
|
||||
|
||||
kfree(acn->name);
|
||||
kfree(acn);
|
||||
|
||||
if (reassign)
|
||||
scst_check_reassign_sessions();
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name)
|
||||
{
|
||||
struct scst_acn *acn;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Trying to find name '%s'", name);
|
||||
|
||||
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(n->name, name) == 0) {
|
||||
list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(acn->name, name) == 0) {
|
||||
TRACE_DBG("%s", "Found");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
n = NULL;
|
||||
acn = NULL;
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return n;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
void scst_acg_remove_acn(struct scst_acn *acn)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_del(&acn->acn_list_entry);
|
||||
kfree(acn->name);
|
||||
kfree(acn);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
return acn;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -3658,13 +3681,13 @@ void scst_acg_remove_acn(struct scst_acn *acn)
|
||||
int scst_acg_remove_name(struct scst_acg *acg, const char *name, bool reassign)
|
||||
{
|
||||
int res = -EINVAL;
|
||||
struct scst_acn *n;
|
||||
struct scst_acn *acn;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(n->name, name) == 0) {
|
||||
scst_acg_remove_acn(n);
|
||||
list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
|
||||
if (strcmp(acn->name, name) == 0) {
|
||||
scst_del_free_acn(acn, false);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
@@ -4032,6 +4055,8 @@ void scst_free_session(struct scst_session *sess)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_sess_sysfs_del(sess);
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
TRACE_DBG("Removing sess %p from the list", sess);
|
||||
@@ -4048,16 +4073,6 @@ void scst_free_session(struct scst_session *sess)
|
||||
|
||||
kfree(sess->transport_id);
|
||||
|
||||
scst_sess_sysfs_put(sess); /* must not be called under scst_mutex */
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
void scst_release_session(struct scst_session *sess)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
kfree(sess->initiator_name);
|
||||
kmem_cache_free(scst_sess_cachep, sess);
|
||||
|
||||
@@ -5910,7 +5925,7 @@ EXPORT_SYMBOL(scst_to_dma_dir);
|
||||
* scst_to_tgt_dma_dir() - translate SCST data direction to DMA direction
|
||||
*
|
||||
* Translates SCST data direction to DMA data direction from the perspective
|
||||
* of the target device.
|
||||
* of a target.
|
||||
*/
|
||||
enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir)
|
||||
{
|
||||
|
||||
+218
-267
File diff suppressed because it is too large
Load Diff
+32
-43
@@ -1452,12 +1452,21 @@ static int sgv_pool_init(struct sgv_pool *pool, const char *name,
|
||||
list_add_tail(&pool->sgv_pools_list_entry, &sgv_pools_list);
|
||||
spin_unlock_bh(&sgv_pools_lock);
|
||||
|
||||
res = scst_sgv_sysfs_create(pool);
|
||||
if (res != 0)
|
||||
goto out_del;
|
||||
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_del:
|
||||
spin_lock_bh(&sgv_pools_lock);
|
||||
list_del(&pool->sgv_pools_list_entry);
|
||||
spin_unlock_bh(&sgv_pools_lock);
|
||||
|
||||
out_free:
|
||||
for (i = 0; i < pool->max_caches; i++) {
|
||||
if (pool->caches[i]) {
|
||||
@@ -1520,8 +1529,10 @@ void sgv_pool_flush(struct sgv_pool *pool)
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_flush);
|
||||
|
||||
static void sgv_pool_deinit_put(struct sgv_pool *pool)
|
||||
static void sgv_pool_destroy(struct sgv_pool *pool)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cancel_delayed_work_sync(&pool->sgv_purge_work);
|
||||
@@ -1534,9 +1545,15 @@ static void sgv_pool_deinit_put(struct sgv_pool *pool)
|
||||
spin_unlock_bh(&sgv_pools_lock);
|
||||
mutex_unlock(&sgv_pools_mutex);
|
||||
|
||||
scst_sgv_sysfs_put(pool);
|
||||
scst_sgv_sysfs_del(pool);
|
||||
|
||||
/* pool can be dead here */
|
||||
for (i = 0; i < pool->max_caches; i++) {
|
||||
if (pool->caches[i])
|
||||
kmem_cache_destroy(pool->caches[i]);
|
||||
pool->caches[i] = NULL;
|
||||
}
|
||||
|
||||
kfree(pool);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1596,6 +1613,7 @@ struct sgv_pool *sgv_pool_create(const char *name,
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&sgv_pools_mutex);
|
||||
|
||||
list_for_each_entry(pool, &sgv_pools_list, sgv_pools_list_entry) {
|
||||
if (strcmp(pool->name, name) == 0) {
|
||||
if (shared) {
|
||||
@@ -1603,13 +1621,14 @@ struct sgv_pool *sgv_pool_create(const char *name,
|
||||
PRINT_ERROR("Attempt of a shared use "
|
||||
"of SGV pool %s with "
|
||||
"different MM", name);
|
||||
goto out_err_unlock;
|
||||
goto out_unlock;
|
||||
}
|
||||
sgv_pool_get(pool);
|
||||
goto out_unlock;
|
||||
} else {
|
||||
PRINT_ERROR("SGV pool %s already exists", name);
|
||||
goto out_err_unlock;
|
||||
pool = NULL;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1623,11 +1642,7 @@ struct sgv_pool *sgv_pool_create(const char *name,
|
||||
rc = sgv_pool_init(pool, name, clustering_type, single_alloc_pages,
|
||||
purge_interval);
|
||||
if (rc != 0)
|
||||
goto out_free_unlock;
|
||||
|
||||
rc = scst_create_sgv_sysfs(pool);
|
||||
if (rc != 0)
|
||||
goto out_err_unlock_put;
|
||||
goto out_free;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&sgv_pools_mutex);
|
||||
@@ -1635,38 +1650,12 @@ out_unlock:
|
||||
TRACE_EXIT_RES(pool != NULL);
|
||||
return pool;
|
||||
|
||||
out_free_unlock:
|
||||
out_free:
|
||||
kfree(pool);
|
||||
|
||||
out_err_unlock:
|
||||
pool = NULL;
|
||||
goto out_unlock;
|
||||
|
||||
out_err_unlock_put:
|
||||
mutex_unlock(&sgv_pools_mutex);
|
||||
sgv_pool_deinit_put(pool);
|
||||
goto out_err_unlock;
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_create);
|
||||
|
||||
void sgv_pool_destroy(struct sgv_pool *pool)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
for (i = 0; i < pool->max_caches; i++) {
|
||||
if (pool->caches[i])
|
||||
kmem_cache_destroy(pool->caches[i]);
|
||||
pool->caches[i] = NULL;
|
||||
}
|
||||
|
||||
kfree(pool);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sgv_pool_get - increase ref counter for the corresponding SGV pool
|
||||
*
|
||||
@@ -1692,7 +1681,7 @@ void sgv_pool_put(struct sgv_pool *pool)
|
||||
TRACE_MEM("Decrementing sgv pool %p ref (new value %d)",
|
||||
pool, atomic_read(&pool->sgv_pool_ref)-1);
|
||||
if (atomic_dec_and_test(&pool->sgv_pool_ref))
|
||||
sgv_pool_deinit_put(pool);
|
||||
sgv_pool_destroy(pool);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(sgv_pool_put);
|
||||
@@ -1755,10 +1744,10 @@ out:
|
||||
return res;
|
||||
|
||||
out_free_clust:
|
||||
sgv_pool_deinit_put(sgv_norm_clust_pool);
|
||||
sgv_pool_destroy(sgv_norm_clust_pool);
|
||||
|
||||
out_free_norm:
|
||||
sgv_pool_deinit_put(sgv_norm_pool);
|
||||
sgv_pool_destroy(sgv_norm_pool);
|
||||
|
||||
out_err:
|
||||
res = -ENOMEM;
|
||||
@@ -1775,9 +1764,9 @@ void scst_sgv_pools_deinit(void)
|
||||
unregister_shrinker(&sgv_shrinker);
|
||||
#endif
|
||||
|
||||
sgv_pool_deinit_put(sgv_dma_pool);
|
||||
sgv_pool_deinit_put(sgv_norm_pool);
|
||||
sgv_pool_deinit_put(sgv_norm_clust_pool);
|
||||
sgv_pool_destroy(sgv_dma_pool);
|
||||
sgv_pool_destroy(sgv_norm_pool);
|
||||
sgv_pool_destroy(sgv_norm_clust_pool);
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
|
||||
+3
-3
@@ -90,7 +90,6 @@ struct sgv_pool {
|
||||
|
||||
/* Protected by sgv_pool_lock, if necessary */
|
||||
unsigned int purge_work_scheduled:1;
|
||||
unsigned int sgv_kobj_initialized:1;
|
||||
|
||||
/* Protected by sgv_pool_lock */
|
||||
struct list_head sorted_recycling_list;
|
||||
@@ -128,6 +127,9 @@ struct sgv_pool {
|
||||
struct list_head sgv_pools_list_entry;
|
||||
|
||||
struct kobject sgv_kobj;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion sgv_kobj_release_cmpl;
|
||||
};
|
||||
|
||||
static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
|
||||
@@ -138,8 +140,6 @@ static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
|
||||
int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark);
|
||||
void scst_sgv_pools_deinit(void);
|
||||
|
||||
void sgv_pool_destroy(struct sgv_pool *pool);
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
int sgv_procinfo_show(struct seq_file *seq, void *v);
|
||||
#else
|
||||
|
||||
+47
-92
@@ -35,10 +35,6 @@
|
||||
|
||||
#include "scst_debug.h"
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
void sgv_pool_destroy(struct sgv_pool *pool);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
#define SCST_MAJOR 177
|
||||
#endif
|
||||
@@ -302,9 +298,6 @@ void scst_adjust_resp_data_len(struct scst_cmd *cmd);
|
||||
|
||||
int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds);
|
||||
|
||||
static inline void scst_tgtt_cleanup(struct scst_tgt_template *tgtt) { }
|
||||
static inline void scst_devt_cleanup(struct scst_dev_type *devt) { }
|
||||
|
||||
int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt);
|
||||
void scst_free_tgt(struct scst_tgt *tgt);
|
||||
|
||||
@@ -313,12 +306,9 @@ void scst_free_device(struct scst_device *dev);
|
||||
|
||||
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
const char *acg_name);
|
||||
void scst_clear_acg(struct scst_acg *acg);
|
||||
void scst_destroy_acg(struct scst_acg *acg);
|
||||
void scst_free_acg(struct scst_acg *acg);
|
||||
void scst_del_free_acg(struct scst_acg *acg);
|
||||
|
||||
struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name);
|
||||
|
||||
struct scst_acg *scst_find_acg(const struct scst_session *sess);
|
||||
|
||||
void scst_check_reassign_sessions(void);
|
||||
@@ -327,19 +317,18 @@ int scst_sess_alloc_tgt_devs(struct scst_session *sess);
|
||||
void scst_sess_free_tgt_devs(struct scst_session *sess);
|
||||
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
|
||||
|
||||
int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
uint64_t lun, int read_only, bool gen_scst_report_luns_changed);
|
||||
int scst_acg_remove_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
struct scst_device *dev, uint64_t lun, int read_only,
|
||||
bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev);
|
||||
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
bool gen_scst_report_luns_changed);
|
||||
|
||||
void scst_acg_dev_destroy(struct scst_acg_dev *acg_dev);
|
||||
|
||||
int scst_acg_add_name(struct scst_acg *acg, const char *name);
|
||||
int scst_acg_add_acn(struct scst_acg *acg, const char *name);
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
int scst_acg_remove_name(struct scst_acg *acg, const char *name, bool reassign);
|
||||
#endif
|
||||
void scst_acg_remove_acn(struct scst_acn *acn);
|
||||
struct scst_acn *scst_acg_find_name(struct scst_acg *acg, const char *name);
|
||||
void scst_del_free_acn(struct scst_acn *acn, bool reassign);
|
||||
struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name);
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
static inline bool scst_acg_sess_is_empty(struct scst_acg *acg)
|
||||
@@ -358,7 +347,6 @@ int scst_assign_dev_handler(struct scst_device *dev,
|
||||
struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
|
||||
const char *initiator_name);
|
||||
void scst_free_session(struct scst_session *sess);
|
||||
void scst_release_session(struct scst_session *sess);
|
||||
void scst_free_session_callback(struct scst_session *sess);
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask);
|
||||
@@ -434,6 +422,8 @@ struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask);
|
||||
void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd);
|
||||
void scst_done_cmd_mgmt(struct scst_cmd *cmd);
|
||||
|
||||
static inline void scst_devt_cleanup(struct scst_dev_type *devt) { }
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
|
||||
int scst_proc_init_module(void);
|
||||
@@ -451,107 +441,72 @@ static inline int scst_sysfs_init(void)
|
||||
}
|
||||
static inline void scst_sysfs_cleanup(void) { }
|
||||
|
||||
static inline int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt)
|
||||
static inline int scst_devt_dev_sysfs_create(struct scst_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt)
|
||||
{
|
||||
scst_tgtt_cleanup(tgtt);
|
||||
}
|
||||
static inline void scst_devt_dev_sysfs_del(struct scst_device *dev) { }
|
||||
|
||||
static inline int scst_create_tgt_sysfs(struct scst_tgt *tgt)
|
||||
static inline int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt) { }
|
||||
static inline void scst_tgt_sysfs_put(struct scst_tgt *tgt)
|
||||
{
|
||||
scst_free_tgt(tgt);
|
||||
}
|
||||
static inline void scst_dev_sysfs_del(struct scst_device *dev) { }
|
||||
|
||||
static inline int scst_create_sess_sysfs(struct scst_session *sess)
|
||||
static inline int scst_sess_sysfs_create(struct scst_session *sess)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_sess_sysfs_put(struct scst_session *sess)
|
||||
{
|
||||
scst_release_session(sess);
|
||||
}
|
||||
static inline int scst_recreate_sess_luns_link(struct scst_session *sess)
|
||||
static inline void scst_sess_sysfs_del(struct scst_session *sess) { }
|
||||
|
||||
static inline int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
struct kobject *parent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int scst_create_sgv_sysfs(struct sgv_pool *pool)
|
||||
static inline void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev) { }
|
||||
|
||||
static inline int scst_acn_sysfs_create(struct scst_acn *acn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_sgv_sysfs_put(struct sgv_pool *pool)
|
||||
{
|
||||
sgv_pool_destroy(pool);
|
||||
}
|
||||
static inline void scst_acn_sysfs_del(struct scst_acn *acn) { }
|
||||
|
||||
static inline int scst_create_devt_sysfs(struct scst_dev_type *devt)
|
||||
static inline int scst_sgv_sysfs_create(struct sgv_pool *pool)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_devt_sysfs_put(struct scst_dev_type *devt)
|
||||
{
|
||||
scst_devt_cleanup(devt);
|
||||
}
|
||||
|
||||
static inline int scst_create_device_sysfs(struct scst_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_device_sysfs_put(struct scst_device *dev)
|
||||
{
|
||||
scst_free_device(dev);
|
||||
}
|
||||
|
||||
static inline int scst_create_devt_dev_sysfs(struct scst_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_devt_dev_sysfs_put(struct scst_device *dev) { }
|
||||
|
||||
static inline int scst_create_acn_sysfs(struct scst_acg *acg,
|
||||
struct scst_acn *acn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void scst_acn_sysfs_del(struct scst_acg *acg,
|
||||
struct scst_acn *acn, bool reassign) { }
|
||||
|
||||
static inline void scst_acg_sysfs_put(struct scst_acg *acg) { }
|
||||
static inline void scst_sgv_sysfs_del(struct sgv_pool *pool) { }
|
||||
|
||||
#else /* CONFIG_SCST_PROC */
|
||||
|
||||
int scst_sysfs_init(void);
|
||||
void scst_sysfs_cleanup(void);
|
||||
int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt);
|
||||
void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt);
|
||||
int scst_create_tgt_sysfs(struct scst_tgt *tgt);
|
||||
int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt);
|
||||
void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt);
|
||||
int scst_tgt_sysfs_create(struct scst_tgt *tgt);
|
||||
void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt);
|
||||
void scst_tgt_sysfs_put(struct scst_tgt *tgt);
|
||||
int scst_create_sess_sysfs(struct scst_session *sess);
|
||||
void scst_sess_sysfs_put(struct scst_session *sess);
|
||||
void scst_tgt_sysfs_del(struct scst_tgt *tgt);
|
||||
int scst_sess_sysfs_create(struct scst_session *sess);
|
||||
void scst_sess_sysfs_del(struct scst_session *sess);
|
||||
int scst_recreate_sess_luns_link(struct scst_session *sess);
|
||||
int scst_create_sgv_sysfs(struct sgv_pool *pool);
|
||||
void scst_sgv_sysfs_put(struct sgv_pool *pool);
|
||||
int scst_create_devt_sysfs(struct scst_dev_type *devt);
|
||||
void scst_devt_sysfs_put(struct scst_dev_type *devt);
|
||||
int scst_create_device_sysfs(struct scst_device *dev);
|
||||
void scst_device_sysfs_put(struct scst_device *dev);
|
||||
int scst_create_devt_dev_sysfs(struct scst_device *dev);
|
||||
void scst_devt_dev_sysfs_put(struct scst_device *dev);
|
||||
int scst_create_acn_sysfs(struct scst_acg *acg, struct scst_acn *acn);
|
||||
void scst_acn_sysfs_del(struct scst_acg *acg, struct scst_acn *acn,
|
||||
bool reassign);
|
||||
|
||||
void scst_acg_sysfs_put(struct scst_acg *acg);
|
||||
int scst_sgv_sysfs_create(struct sgv_pool *pool);
|
||||
void scst_sgv_sysfs_del(struct sgv_pool *pool);
|
||||
int scst_devt_sysfs_create(struct scst_dev_type *devt);
|
||||
void scst_devt_sysfs_del(struct scst_dev_type *devt);
|
||||
int scst_dev_sysfs_create(struct scst_device *dev);
|
||||
void scst_dev_sysfs_del(struct scst_device *dev);
|
||||
int scst_devt_dev_sysfs_create(struct scst_device *dev);
|
||||
void scst_devt_dev_sysfs_del(struct scst_device *dev);
|
||||
int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
struct scst_acg *acg);
|
||||
void scst_acg_sysfs_del(struct scst_acg *acg);
|
||||
int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
struct kobject *parent);
|
||||
void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev);
|
||||
int scst_acn_sysfs_create(struct scst_acn *acn);
|
||||
void scst_acn_sysfs_del(struct scst_acn *acn);
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
|
||||
+31
-13
@@ -977,7 +977,7 @@ static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc)
|
||||
}
|
||||
if (remove_proc)
|
||||
scst_proc_del_acg_tree(acg_proc_root, acg->acg_name);
|
||||
scst_destroy_acg(acg);
|
||||
scst_del_free_acg(acg);
|
||||
}
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -2066,7 +2066,7 @@ static ssize_t scst_proc_groups_devices_write(struct file *file,
|
||||
goto out_free_up;
|
||||
} else {
|
||||
/* Replace */
|
||||
rc = scst_acg_remove_dev(acg, acg_dev->dev,
|
||||
rc = scst_acg_del_lun(acg, acg_dev->lun,
|
||||
false);
|
||||
if (rc) {
|
||||
res = rc;
|
||||
@@ -2076,13 +2076,16 @@ static ssize_t scst_proc_groups_devices_write(struct file *file,
|
||||
}
|
||||
}
|
||||
|
||||
rc = scst_acg_add_dev(acg, dev, virt_lun, read_only,
|
||||
action == SCST_PROC_ACTION_ADD);
|
||||
rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, read_only,
|
||||
false, NULL);
|
||||
if (rc) {
|
||||
res = rc;
|
||||
goto out_free_up;
|
||||
}
|
||||
|
||||
if (action == SCST_PROC_ACTION_ADD)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
if (dev_replaced) {
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
|
||||
@@ -2100,17 +2103,32 @@ static ssize_t scst_proc_groups_devices_write(struct file *file,
|
||||
break;
|
||||
}
|
||||
case SCST_PROC_ACTION_DEL:
|
||||
rc = scst_acg_remove_dev(acg, dev, true);
|
||||
if (rc) {
|
||||
res = rc;
|
||||
goto out_free_up;
|
||||
{
|
||||
/*
|
||||
* This code doesn't handle if there are >1 LUNs for the same
|
||||
* device in the group. Instead, it always deletes the first
|
||||
* entry. It wasn't fixed for compatibility reasons, because
|
||||
* procfs is now obsoleted.
|
||||
*/
|
||||
struct scst_acg_dev *a;
|
||||
list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
if (a->dev == dev) {
|
||||
rc = scst_acg_del_lun(acg, a->lun, true);
|
||||
if (rc) {
|
||||
res = rc;
|
||||
goto out_free_up;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRINT_ERROR("Device is not found in group %s", acg->acg_name);
|
||||
break;
|
||||
}
|
||||
case SCST_PROC_ACTION_CLEAR:
|
||||
list_for_each_entry_safe(acg_dev, acg_dev_tmp,
|
||||
&acg->acg_dev_list,
|
||||
acg_dev_list_entry) {
|
||||
rc = scst_acg_remove_dev(acg, acg_dev->dev,
|
||||
rc = scst_acg_del_lun(acg, acg_dev->lun,
|
||||
list_is_last(&acg_dev->acg_dev_list_entry,
|
||||
&acg->acg_dev_list));
|
||||
if (rc) {
|
||||
@@ -2235,7 +2253,7 @@ static ssize_t scst_proc_groups_names_write(struct file *file,
|
||||
|
||||
switch (action) {
|
||||
case SCST_PROC_ACTION_ADD:
|
||||
rc = scst_acg_add_name(acg, p);
|
||||
rc = scst_acg_add_acn(acg, p);
|
||||
break;
|
||||
case SCST_PROC_ACTION_DEL:
|
||||
rc = scst_acg_remove_name(acg, p, true);
|
||||
@@ -2274,15 +2292,15 @@ static ssize_t scst_proc_groups_names_write(struct file *file,
|
||||
rc = scst_acg_remove_name(acg, name, false);
|
||||
if (rc != 0)
|
||||
goto out_free_unlock;
|
||||
rc = scst_acg_add_name(new_acg, name);
|
||||
rc = scst_acg_add_acn(new_acg, name);
|
||||
if (rc != 0)
|
||||
scst_acg_add_name(acg, name);
|
||||
scst_acg_add_acn(acg, name);
|
||||
break;
|
||||
}
|
||||
case SCST_PROC_ACTION_CLEAR:
|
||||
list_for_each_entry_safe(n, nn, &acg->acn_list,
|
||||
acn_list_entry) {
|
||||
scst_acg_remove_acn(n);
|
||||
scst_del_free_acn(n, false);
|
||||
}
|
||||
scst_check_reassign_sessions();
|
||||
break;
|
||||
|
||||
+404
-568
File diff suppressed because it is too large
Load Diff
@@ -6286,15 +6286,14 @@ static int scst_init_session(struct scst_session *sess)
|
||||
|
||||
res = scst_sess_alloc_tgt_devs(sess);
|
||||
|
||||
/* Let's always create session's sysfs to simplify error recovery */
|
||||
|
||||
rc = scst_create_sess_sysfs(sess);
|
||||
if (res == 0)
|
||||
res = rc;
|
||||
|
||||
failed:
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
/* Let's always create sysfs to simplify code */
|
||||
rc = scst_sess_sysfs_create(sess);
|
||||
if (res == 0)
|
||||
res = rc;
|
||||
|
||||
if (sess->init_result_fn) {
|
||||
TRACE_DBG("Calling init_result_fn(%p)", sess);
|
||||
sess->init_result_fn(sess, sess->reg_sess_data, res);
|
||||
|
||||
Reference in New Issue
Block a user