mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
Revert r2446 as wrong
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2461 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1431,10 +1431,8 @@ struct scst_tgt {
|
||||
char *default_group_name;
|
||||
#endif
|
||||
|
||||
unsigned int tgt_kobj_initialized:1;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *tgt_kobj_release_cmpl;
|
||||
struct completion tgt_kobj_release_cmpl;
|
||||
|
||||
struct kobject tgt_kobj; /* main targets/target kobject */
|
||||
struct kobject *tgt_sess_kobj; /* target/sessions/ */
|
||||
@@ -2079,9 +2077,6 @@ struct scst_device {
|
||||
/* If set, dev is read only */
|
||||
unsigned short rd_only:1;
|
||||
|
||||
/* If set, dev_kobj was initialized */
|
||||
unsigned short dev_kobj_initialized:1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/*************************************************************
|
||||
@@ -2222,7 +2217,7 @@ struct scst_device {
|
||||
enum scst_dev_type_threads_pool_type threads_pool_type;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *dev_kobj_release_cmpl;
|
||||
struct completion dev_kobj_release_cmpl;
|
||||
|
||||
struct kobject dev_kobj; /* kobject for this struct */
|
||||
struct kobject *dev_exp_kobj; /* exported groups */
|
||||
@@ -2347,9 +2342,6 @@ struct scst_tgt_dev {
|
||||
/* Set if INQUIRY DATA HAS CHANGED UA is needed */
|
||||
unsigned int inq_changed_ua_needed:1;
|
||||
|
||||
/* Set if tgt_dev_kobj was initialized */
|
||||
unsigned int tgt_dev_kobj_initialized:1;
|
||||
|
||||
/*
|
||||
* Stored Unit Attention sense and its length for possible
|
||||
* subsequent REQUEST SENSE. Both protected by tgt_dev_lock.
|
||||
@@ -2358,7 +2350,7 @@ struct scst_tgt_dev {
|
||||
uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE];
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *tgt_dev_kobj_release_cmpl;
|
||||
struct completion tgt_dev_kobj_release_cmpl;
|
||||
|
||||
struct kobject tgt_dev_kobj; /* kobject for this struct */
|
||||
|
||||
@@ -2386,9 +2378,6 @@ struct scst_acg_dev {
|
||||
/* If set, the corresponding LU is read only */
|
||||
unsigned int rd_only:1;
|
||||
|
||||
/* If set 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 */
|
||||
@@ -2401,7 +2390,7 @@ struct scst_acg_dev {
|
||||
struct kobject acg_dev_kobj;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *acg_dev_kobj_release_cmpl;
|
||||
struct completion acg_dev_kobj_release_cmpl;
|
||||
|
||||
/* Name of the link to the corresponding LUN */
|
||||
char acg_dev_link_name[20];
|
||||
@@ -2442,10 +2431,9 @@ struct scst_acg {
|
||||
cpumask_t acg_cpu_mask;
|
||||
|
||||
unsigned int tgt_acg:1;
|
||||
unsigned int acg_kobj_initialized:1;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *acg_kobj_release_cmpl;
|
||||
struct completion acg_kobj_release_cmpl;
|
||||
|
||||
/* kobject for this structure */
|
||||
struct kobject acg_kobj;
|
||||
|
||||
@@ -2536,7 +2536,7 @@ out:
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void __scst_free_tgt(struct scst_tgt *tgt)
|
||||
void scst_free_tgt(struct scst_tgt *tgt)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2551,22 +2551,8 @@ void __scst_free_tgt(struct scst_tgt *tgt)
|
||||
return;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void scst_free_tgt(struct scst_tgt *tgt)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (tgt->tgt_kobj_initialized)
|
||||
scst_tgt_sysfs_del_free(tgt);
|
||||
else
|
||||
__scst_free_tgt(tgt);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Called under scst_mutex and suspended activity */
|
||||
int scst_alloc_dev(gfp_t gfp_mask, struct scst_device **out_dev)
|
||||
int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
int res = 0;
|
||||
@@ -2610,20 +2596,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void __scst_free_dev(struct scst_device *dev)
|
||||
{
|
||||
TRACE_MEM("Freeing dev %p", dev);
|
||||
|
||||
kfree(dev->virt_name);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must not be called under scst_mutex, due to possible deadlock with
|
||||
* sysfs ref counting in sysfs works (it is waiting for the last put, but
|
||||
* the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_free_dev(struct scst_device *dev)
|
||||
void scst_free_device(struct scst_device *dev)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2638,10 +2611,8 @@ void scst_free_dev(struct scst_device *dev)
|
||||
|
||||
scst_deinit_threads(&dev->dev_cmd_threads);
|
||||
|
||||
if (dev->dev_kobj_initialized)
|
||||
scst_dev_sysfs_del_free(dev);
|
||||
else
|
||||
__scst_free_dev(dev);
|
||||
kfree(dev->virt_name);
|
||||
kfree(dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2685,17 +2656,11 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void scst_free_acg_dev(struct scst_acg_dev *acg_dev)
|
||||
{
|
||||
TRACE_MEM("Freeing acg_dev %p", acg_dev);
|
||||
kmem_cache_free(scst_acgd_cachep, 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)
|
||||
static void scst_del_free_acg_dev(struct scst_acg_dev *acg_dev, bool del_sysfs)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2704,10 +2669,10 @@ static void scst_del_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)
|
||||
scst_acg_dev_sysfs_del_free(acg_dev);
|
||||
else
|
||||
scst_free_acg_dev(acg_dev);
|
||||
if (del_sysfs)
|
||||
scst_acg_dev_sysfs_del(acg_dev);
|
||||
|
||||
kmem_cache_free(scst_acgd_cachep, acg_dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2723,6 +2688,7 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_session *sess;
|
||||
LIST_HEAD(tmp_tgt_dev_list);
|
||||
bool del_sysfs = true;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2752,8 +2718,10 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
}
|
||||
|
||||
res = scst_acg_dev_sysfs_create(acg_dev, parent);
|
||||
if (res != 0)
|
||||
if (res != 0) {
|
||||
del_sysfs = false;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
@@ -2774,7 +2742,7 @@ out_free:
|
||||
extra_tgt_dev_list_entry) {
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_del_free_acg_dev(acg_dev);
|
||||
scst_del_free_acg_dev(acg_dev, del_sysfs);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2806,7 +2774,7 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
|
||||
scst_del_free_acg_dev(acg_dev);
|
||||
scst_del_free_acg_dev(acg_dev, true);
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
@@ -2819,22 +2787,6 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void __scst_free_acg(struct scst_acg *acg)
|
||||
{
|
||||
TRACE_MEM("Freeing acg %p", acg);
|
||||
|
||||
kfree(acg->acg_name);
|
||||
kfree(acg);
|
||||
}
|
||||
|
||||
static void scst_free_acg(struct scst_acg *acg)
|
||||
{
|
||||
if (acg->acg_kobj_initialized)
|
||||
scst_acg_sysfs_del_free(acg);
|
||||
else
|
||||
__scst_free_acg(acg);
|
||||
}
|
||||
|
||||
/* 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, bool tgt_acg)
|
||||
@@ -2892,7 +2844,7 @@ out_del:
|
||||
#endif
|
||||
|
||||
out_free:
|
||||
scst_free_acg(acg);
|
||||
kfree(acg);
|
||||
acg = NULL;
|
||||
goto out;
|
||||
}
|
||||
@@ -2919,7 +2871,7 @@ void scst_del_free_acg(struct scst_acg *acg)
|
||||
if (tgt_dev->acg_dev == acg_dev)
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_del_free_acg_dev(acg_dev);
|
||||
scst_del_free_acg_dev(acg_dev, true);
|
||||
}
|
||||
|
||||
/* Freeing names */
|
||||
@@ -2935,6 +2887,8 @@ void scst_del_free_acg(struct scst_acg *acg)
|
||||
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);
|
||||
} else
|
||||
acg->tgt->default_acg = NULL;
|
||||
#endif
|
||||
@@ -2943,7 +2897,8 @@ void scst_del_free_acg(struct scst_acg *acg)
|
||||
sBUG_ON(!list_empty(&acg->acg_dev_list));
|
||||
sBUG_ON(!list_empty(&acg->acn_list));
|
||||
|
||||
scst_free_acg(acg);
|
||||
kfree(acg->acg_name);
|
||||
kfree(acg);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -3485,12 +3440,6 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
|
||||
return;
|
||||
}
|
||||
|
||||
void __scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
TRACE_MEM("Freeing tgt_dev %p", tgt_dev);
|
||||
kmem_cache_free(scst_tgtd_cachep, tgt_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* scst_mutex supposed to be held, there must not be parallel activity in this
|
||||
* session.
|
||||
@@ -3507,6 +3456,8 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
list_del(&tgt_dev->sess_tgt_dev_list_entry);
|
||||
|
||||
scst_tgt_dev_sysfs_del(tgt_dev);
|
||||
|
||||
if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
|
||||
dev->not_pr_supporting_tgt_devs_num--;
|
||||
|
||||
@@ -3525,10 +3476,7 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
sBUG_ON(!list_empty(&tgt_dev->thr_data_list));
|
||||
|
||||
if (tgt_dev->tgt_dev_kobj_initialized)
|
||||
scst_tgt_dev_sysfs_del_free(tgt_dev);
|
||||
else
|
||||
__scst_free_tgt_dev(tgt_dev);
|
||||
kmem_cache_free(scst_tgtd_cachep, tgt_dev);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
|
||||
@@ -553,6 +553,7 @@ out:
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
out_sysfs_del:
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_tgt_sysfs_del(tgt);
|
||||
goto out_free_tgt;
|
||||
#endif
|
||||
|
||||
@@ -639,6 +640,10 @@ again:
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_resume_activity();
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
scst_tgt_sysfs_del(tgt);
|
||||
#endif
|
||||
|
||||
PRINT_INFO("Target %s for template %s unregistered successfully",
|
||||
tgt->tgt_name, vtt->name);
|
||||
|
||||
@@ -857,7 +862,7 @@ static int scst_register_device(struct scsi_device *scsidp)
|
||||
#endif
|
||||
}
|
||||
|
||||
res = scst_alloc_dev(GFP_KERNEL, &dev);
|
||||
res = scst_alloc_device(GFP_KERNEL, &dev);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -920,7 +925,7 @@ out_del:
|
||||
list_del(&dev->dev_list_entry);
|
||||
|
||||
out_free_dev:
|
||||
scst_free_dev(dev);
|
||||
scst_free_device(dev);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_mutex);
|
||||
@@ -968,11 +973,13 @@ static void scst_unregister_device(struct scsi_device *scsidp)
|
||||
|
||||
scst_resume_activity();
|
||||
|
||||
scst_dev_sysfs_del(dev);
|
||||
|
||||
PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %d, type %d",
|
||||
scsidp->host->host_no, scsidp->channel, scsidp->id,
|
||||
scsidp->lun, scsidp->type);
|
||||
|
||||
scst_free_dev(dev);
|
||||
scst_free_device(dev);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
@@ -1047,6 +1054,7 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
{
|
||||
int res, rc;
|
||||
struct scst_device *dev, *d;
|
||||
bool sysfs_del = false;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -1080,7 +1088,7 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
goto out_resume;
|
||||
}
|
||||
|
||||
res = scst_alloc_dev(GFP_KERNEL, &dev);
|
||||
res = scst_alloc_device(GFP_KERNEL, &dev);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -1127,6 +1135,7 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
if (strcmp(d->virt_name, dev_name) == 0) {
|
||||
PRINT_ERROR("Device %s already exists", dev_name);
|
||||
res = -EEXIST;
|
||||
sysfs_del = true;
|
||||
goto out_pr_clear_dev;
|
||||
}
|
||||
}
|
||||
@@ -1134,6 +1143,7 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
rc = scst_assign_dev_handler(dev, dev_handler);
|
||||
if (rc != 0) {
|
||||
res = rc;
|
||||
sysfs_del = true;
|
||||
goto out_pr_clear_dev;
|
||||
}
|
||||
|
||||
@@ -1161,7 +1171,9 @@ out_pr_clear_dev:
|
||||
|
||||
out_free_dev:
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_free_dev(dev);
|
||||
if (sysfs_del)
|
||||
scst_dev_sysfs_del(dev);
|
||||
scst_free_device(dev);
|
||||
goto out_resume;
|
||||
|
||||
out_unlock:
|
||||
@@ -1213,10 +1225,12 @@ void scst_unregister_virtual_device(int id)
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_resume_activity();
|
||||
|
||||
scst_dev_sysfs_del(dev);
|
||||
|
||||
PRINT_INFO("Detached from virtual device %s (id %d)",
|
||||
dev->virt_name, dev->virt_id);
|
||||
|
||||
scst_free_dev(dev);
|
||||
scst_free_device(dev);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
|
||||
@@ -306,16 +306,13 @@ int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds);
|
||||
|
||||
int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt);
|
||||
void scst_free_tgt(struct scst_tgt *tgt);
|
||||
void __scst_free_tgt(struct scst_tgt *tgt);
|
||||
|
||||
int scst_alloc_dev(gfp_t gfp_mask, struct scst_device **out_dev);
|
||||
void scst_free_dev(struct scst_device *dev);
|
||||
void __scst_free_dev(struct scst_device *dev);
|
||||
int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
|
||||
void scst_free_device(struct scst_device *dev);
|
||||
|
||||
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
const char *acg_name, bool tgt_acg);
|
||||
void scst_del_free_acg(struct scst_acg *acg);
|
||||
void __scst_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);
|
||||
@@ -326,8 +323,6 @@ 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);
|
||||
|
||||
void __scst_free_tgt_dev(struct scst_tgt_dev *tgt_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);
|
||||
@@ -341,8 +336,6 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name, bool reassign);
|
||||
void scst_del_free_acn(struct scst_acn *acn, bool reassign);
|
||||
struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name);
|
||||
|
||||
void scst_free_acg_dev(struct scst_acg_dev *acg_dev);
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
static inline bool scst_acg_sess_is_empty(struct scst_acg *acg)
|
||||
{
|
||||
@@ -433,24 +426,19 @@ static inline int scst_sysfs_init(void)
|
||||
}
|
||||
static inline void scst_sysfs_cleanup(void) { }
|
||||
|
||||
static inline void scst_tgt_sysfs_del_free(struct scst_tgt *tgt) { BUG(); }
|
||||
|
||||
static inline int scst_devt_dev_sysfs_create(struct scst_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_devt_dev_sysfs_del(struct scst_device *dev) { }
|
||||
|
||||
static inline void scst_dev_sysfs_del_free(struct scst_device *dev) { BUG(); }
|
||||
static inline void scst_dev_sysfs_del(struct scst_device *dev) { }
|
||||
|
||||
static inline int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void scst_tgt_dev_sysfs_del_free(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
static inline void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev) { }
|
||||
|
||||
static inline int scst_sess_sysfs_create(struct scst_session *sess)
|
||||
{
|
||||
@@ -463,12 +451,7 @@ static inline int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void scst_acg_dev_sysfs_del_free(struct scst_acg_dev *acg_dev)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void scst_acg_sysfs_del_free(struct scst_acg *acg) { BUG(); }
|
||||
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)
|
||||
{
|
||||
@@ -490,7 +473,7 @@ 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_del_free(struct scst_tgt *tgt);
|
||||
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);
|
||||
@@ -499,17 +482,17 @@ 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_free(struct scst_device *dev);
|
||||
void scst_dev_sysfs_del(struct scst_device *dev);
|
||||
int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev);
|
||||
void scst_tgt_dev_sysfs_del_free(struct scst_tgt_dev *tgt_dev);
|
||||
void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_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_free(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_free(struct scst_acg_dev *acg_dev);
|
||||
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);
|
||||
|
||||
|
||||
@@ -922,9 +922,7 @@ static void scst_tgt_release(struct kobject *kobj)
|
||||
TRACE_ENTRY();
|
||||
|
||||
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
complete_all(tgt->tgt_kobj_release_cmpl);
|
||||
|
||||
__scst_free_tgt(tgt);
|
||||
complete_all(&tgt->tgt_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -942,9 +940,7 @@ static void scst_acg_release(struct kobject *kobj)
|
||||
TRACE_ENTRY();
|
||||
|
||||
acg = container_of(kobj, struct scst_acg, acg_kobj);
|
||||
complete_all(acg->acg_kobj_release_cmpl);
|
||||
|
||||
__scst_free_acg(acg);
|
||||
complete_all(&acg->acg_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1120,11 +1116,8 @@ static struct kobj_attribute tgt_enable_attr =
|
||||
scst_tgt_enable_show, scst_tgt_enable_store);
|
||||
|
||||
/*
|
||||
* Supposed to be called under scst_mutex.
|
||||
*
|
||||
* Upon return, including with an error, if tgt_kobj_initialized set
|
||||
* scst_tgt_sysfs_del_free() must be called to free tgt instead of
|
||||
* __scst_free_tgt()!
|
||||
* Supposed to be called under scst_mutex. In case of error will drop,
|
||||
* then reacquire it.
|
||||
*/
|
||||
int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
{
|
||||
@@ -1133,6 +1126,8 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
init_completion(&tgt->tgt_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
|
||||
&tgt->tgtt->tgtt_kobj, tgt->tgt_name);
|
||||
if (res != 0) {
|
||||
@@ -1140,8 +1135,6 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
tgt->tgt_kobj_initialized = 1;
|
||||
|
||||
if ((tgt->tgtt->enable_target != NULL) &&
|
||||
(tgt->tgtt->is_target_enabled != NULL)) {
|
||||
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||
@@ -1149,7 +1142,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attr %s to sysfs",
|
||||
tgt_enable_attr.attr.name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,7 +1162,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_luns_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_groups",
|
||||
@@ -1185,7 +1178,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_ini_group_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||
@@ -1193,7 +1186,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_rel_tgt_id.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||
@@ -1201,7 +1194,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_tgt_addr_method.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||
@@ -1209,14 +1202,14 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_tgt_io_grouping_type.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&tgt->tgt_kobj, &scst_tgt_cpu_mask.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_tgt_cpu_mask.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
pattr = tgt->tgtt->tgt_attrs;
|
||||
@@ -1228,7 +1221,7 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
(*pattr)->name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
pattr++;
|
||||
}
|
||||
@@ -1240,24 +1233,25 @@ out:
|
||||
|
||||
out_nomem:
|
||||
res = -ENOMEM;
|
||||
|
||||
out_err:
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_tgt_sysfs_del(tgt);
|
||||
mutex_lock(&scst_mutex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes tgt from sysfs and frees it in the tgt_kobj release()
|
||||
*
|
||||
* Must not be called under scst_mutex, due to possible deadlock with
|
||||
* sysfs ref counting in sysfs works (it is waiting for the last put, but
|
||||
* the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_tgt_sysfs_del_free(struct scst_tgt *tgt)
|
||||
void scst_tgt_sysfs_del(struct scst_tgt *tgt)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(cmpl);
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
tgt->tgt_kobj_release_cmpl = &cmpl;
|
||||
|
||||
kobject_del(tgt->tgt_sess_kobj);
|
||||
kobject_put(tgt->tgt_sess_kobj);
|
||||
|
||||
@@ -1267,17 +1261,18 @@ void scst_tgt_sysfs_del_free(struct scst_tgt *tgt)
|
||||
kobject_del(tgt->tgt_ini_grp_kobj);
|
||||
kobject_put(tgt->tgt_ini_grp_kobj);
|
||||
|
||||
if (atomic_read(&tgt->tgt_kobj.kref.refcount) > 1)
|
||||
TRACE_MGMT_DBG("Waiting for releasing sysfs entry "
|
||||
"for tgt %s (%d refs)...", tgt->tgt_name,
|
||||
atomic_read(&tgt->tgt_kobj.kref.refcount));
|
||||
|
||||
kobject_del(&tgt->tgt_kobj);
|
||||
kobject_put(&tgt->tgt_kobj);
|
||||
|
||||
/* tgt can be dead here! */
|
||||
|
||||
wait_for_completion(&cmpl);
|
||||
rc = wait_for_completion_timeout(&tgt->tgt_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for target %s (%d refs)...", tgt->tgt_name,
|
||||
atomic_read(&tgt->tgt_kobj.kref.refcount));
|
||||
wait_for_completion(&tgt->tgt_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs "
|
||||
"entry for target %s", tgt->tgt_name);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1583,9 +1578,7 @@ static void scst_sysfs_dev_release(struct kobject *kobj)
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
complete_all(dev->dev_kobj_release_cmpl);
|
||||
|
||||
__scst_free_dev(dev);
|
||||
complete_all(&dev->dev_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1697,9 +1690,8 @@ static struct kobj_type scst_dev_ktype = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Upon return, including with an error, if dev_kobj_initialized set
|
||||
* scst_dev_sysfs_del_free() must be called to free dev instead of
|
||||
* __scst_free_dev()!
|
||||
* Must not be called under scst_mutex, because it can call
|
||||
* scst_dev_sysfs_del()
|
||||
*/
|
||||
int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
{
|
||||
@@ -1707,6 +1699,8 @@ int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
init_completion(&dev->dev_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&dev->dev_kobj, &scst_dev_ktype,
|
||||
scst_devices_kobj, dev->virt_name);
|
||||
if (res != 0) {
|
||||
@@ -1714,15 +1708,13 @@ int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->dev_kobj_initialized = 1;
|
||||
|
||||
dev->dev_exp_kobj = kobject_create_and_add("exported",
|
||||
&dev->dev_kobj);
|
||||
if (dev->dev_exp_kobj == NULL) {
|
||||
PRINT_ERROR("Can't create exported link for device %s",
|
||||
dev->virt_name);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
if (dev->scsi_dev != NULL) {
|
||||
@@ -1731,7 +1723,7 @@ int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't create scsi_device link for dev %s",
|
||||
dev->virt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1742,7 +1734,7 @@ int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't create attr %s for dev %s",
|
||||
dev_dump_prs_attr.attr.name, dev->virt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1750,37 +1742,38 @@ int scst_dev_sysfs_create(struct scst_device *dev)
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_del:
|
||||
scst_dev_sysfs_del(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes dev from sysfs and frees it in the dev_kobj release()
|
||||
*
|
||||
* Must not be called under scst_mutex, due to possible deadlock with
|
||||
* sysfs ref counting in sysfs works (it is waiting for the last put, but
|
||||
* the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_dev_sysfs_del_free(struct scst_device *dev)
|
||||
void scst_dev_sysfs_del(struct scst_device *dev)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(cmpl);
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev->dev_kobj_release_cmpl = &cmpl;
|
||||
|
||||
kobject_del(dev->dev_exp_kobj);
|
||||
kobject_put(dev->dev_exp_kobj);
|
||||
|
||||
if (atomic_read(&dev->dev_kobj.kref.refcount) > 1)
|
||||
TRACE_MGMT_DBG("Waiting for releasing sysfs entry "
|
||||
"for dev %s (%d refs)...", dev->virt_name,
|
||||
atomic_read(&dev->dev_kobj.kref.refcount));
|
||||
|
||||
kobject_del(&dev->dev_kobj);
|
||||
kobject_put(&dev->dev_kobj);
|
||||
|
||||
/* dev can be dead here! */
|
||||
|
||||
wait_for_completion(&cmpl);
|
||||
rc = wait_for_completion_timeout(&dev->dev_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for device %s (%d refs)...", dev->virt_name,
|
||||
atomic_read(&dev->dev_kobj.kref.refcount));
|
||||
wait_for_completion(&dev->dev_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs "
|
||||
"entry for device %s", dev->virt_name);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1937,9 +1930,7 @@ static void scst_sysfs_tgt_dev_release(struct kobject *kobj)
|
||||
TRACE_ENTRY();
|
||||
|
||||
tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
|
||||
complete_all(tgt_dev->tgt_dev_kobj_release_cmpl);
|
||||
|
||||
__scst_free_tgt_dev(tgt_dev);
|
||||
complete_all(&tgt_dev->tgt_dev_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -1957,6 +1948,8 @@ int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
init_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&tgt_dev->tgt_dev_kobj, &scst_tgt_dev_ktype,
|
||||
&tgt_dev->sess->sess_kobj, "lun%lld",
|
||||
(unsigned long long)tgt_dev->lun);
|
||||
@@ -1966,42 +1959,38 @@ int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
tgt_dev->tgt_dev_kobj_initialized = 1;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes tgt_dev from sysfs and frees it in the tgt_dev_kobj release()
|
||||
*
|
||||
* Called with scst_mutex held.
|
||||
*
|
||||
* !! No sysfs works must use kobject_get() to protect tgt_dev, due to possible
|
||||
* !! deadlock with scst_mutex (it is waiting for the last put, but
|
||||
* !! the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_tgt_dev_sysfs_del_free(struct scst_tgt_dev *tgt_dev)
|
||||
void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(cmpl);
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
tgt_dev->tgt_dev_kobj_release_cmpl = &cmpl;
|
||||
|
||||
if (atomic_read(&tgt_dev->tgt_dev_kobj.kref.refcount) > 1)
|
||||
TRACE_MGMT_DBG("Waiting for releasing sysfs entry "
|
||||
"for tgt_dev LUN %lld, (%d refs)...",
|
||||
(unsigned long long)tgt_dev->lun,
|
||||
atomic_read(&tgt_dev->tgt_dev_kobj.kref.refcount));
|
||||
|
||||
kobject_del(&tgt_dev->tgt_dev_kobj);
|
||||
kobject_put(&tgt_dev->tgt_dev_kobj);
|
||||
|
||||
/* tgt_dev can be dead here! */
|
||||
|
||||
wait_for_completion(&cmpl);
|
||||
rc = wait_for_completion_timeout(
|
||||
&tgt_dev->tgt_dev_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for tgt_dev %lld (%d refs)...",
|
||||
(unsigned long long)tgt_dev->lun,
|
||||
atomic_read(&tgt_dev->tgt_dev_kobj.kref.refcount));
|
||||
wait_for_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs entry for "
|
||||
"tgt_dev %lld", (unsigned long long)tgt_dev->lun);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2526,9 +2515,7 @@ static void scst_acg_dev_release(struct kobject *kobj)
|
||||
TRACE_ENTRY();
|
||||
|
||||
acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
|
||||
complete_all(acg_dev->acg_dev_kobj_release_cmpl);
|
||||
|
||||
scst_free_acg_dev(acg_dev);
|
||||
complete_all(&acg_dev->acg_dev_kobj_release_cmpl);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -2563,49 +2550,41 @@ static struct kobj_type acg_dev_ktype = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Deletes acg_dev from sysfs and frees it in the acg_dev_kobj release()
|
||||
*
|
||||
* Called with scst_mutex held.
|
||||
*
|
||||
* !! No sysfs works must use kobject_get() to protect acg_dev, due to possible
|
||||
* !! deadlock with scst_mutex (it is waiting for the last put, but
|
||||
* !! the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_acg_dev_sysfs_del_free(struct scst_acg_dev *acg_dev)
|
||||
void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(cmpl);
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
acg_dev->acg_dev_kobj_release_cmpl = &cmpl;
|
||||
|
||||
if (acg_dev->dev != NULL) {
|
||||
sysfs_remove_link(acg_dev->dev->dev_exp_kobj,
|
||||
acg_dev->acg_dev_link_name);
|
||||
kobject_put(&acg_dev->dev->dev_kobj);
|
||||
}
|
||||
|
||||
if (atomic_read(&acg_dev->acg_dev_kobj.kref.refcount) > 1)
|
||||
TRACE_MGMT_DBG("Waiting for releasing sysfs entry "
|
||||
"for acg_dev %p (%d refs)...", acg_dev,
|
||||
atomic_read(&acg_dev->acg_dev_kobj.kref.refcount));
|
||||
|
||||
kobject_del(&acg_dev->acg_dev_kobj);
|
||||
kobject_put(&acg_dev->acg_dev_kobj);
|
||||
|
||||
/* acg_dev can be dead here! */
|
||||
|
||||
wait_for_completion(&cmpl);
|
||||
rc = wait_for_completion_timeout(&acg_dev->acg_dev_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for acg_dev %p (%d refs)...", acg_dev,
|
||||
atomic_read(&acg_dev->acg_dev_kobj.kref.refcount));
|
||||
wait_for_completion(&acg_dev->acg_dev_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs "
|
||||
"entry for acg_dev %p", acg_dev);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon return, including with an error, if acg_dev_kobj_initialized set
|
||||
* scst_acg_dev_sysfs_del_free() must be called to free acg_dev instead of
|
||||
* scst_free_acg_dev()!
|
||||
*/
|
||||
int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
struct kobject *parent)
|
||||
{
|
||||
@@ -2613,6 +2592,8 @@ int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
init_completion(&acg_dev->acg_dev_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
|
||||
parent, "%u", acg_dev->lun);
|
||||
if (res != 0) {
|
||||
@@ -2620,8 +2601,6 @@ int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
acg_dev->acg_dev_kobj_initialized = 1;
|
||||
|
||||
kobject_get(&acg_dev->dev->dev_kobj);
|
||||
|
||||
snprintf(acg_dev->acg_dev_link_name, sizeof(acg_dev->acg_dev_link_name),
|
||||
@@ -2632,7 +2611,7 @@ int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't create acg %s LUN link",
|
||||
acg_dev->acg->acg_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_link(&acg_dev->acg_dev_kobj,
|
||||
@@ -2640,11 +2619,15 @@ int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't create acg %s device link",
|
||||
acg_dev->acg->acg_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
out_del:
|
||||
scst_acg_dev_sysfs_del(acg_dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int __scst_process_luns_mgmt_store(char *buffer,
|
||||
@@ -3357,49 +3340,41 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes acg from sysfs and frees it in the acg_kobj release()
|
||||
*
|
||||
* Called with scst_mutex held.
|
||||
*
|
||||
* !! No sysfs works must use kobject_get() to protect acg, due to possible
|
||||
* !! deadlock with scst_mutex (it is waiting for the last put, but
|
||||
* !! the last ref counter holder is waiting for scst_mutex)
|
||||
*/
|
||||
void scst_acg_sysfs_del_free(struct scst_acg *acg)
|
||||
void scst_acg_sysfs_del(struct scst_acg *acg)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(cmpl);
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
acg->acg_kobj_release_cmpl = &cmpl;
|
||||
|
||||
kobject_del(acg->luns_kobj);
|
||||
kobject_put(acg->luns_kobj);
|
||||
|
||||
kobject_del(acg->initiators_kobj);
|
||||
kobject_put(acg->initiators_kobj);
|
||||
|
||||
if (atomic_read(&acg->acg_kobj.kref.refcount) > 1)
|
||||
TRACE_MGMT_DBG("Waiting for releasing sysfs entry "
|
||||
"for acg %s (%d refs)...", acg->acg_name,
|
||||
atomic_read(&acg->acg_kobj.kref.refcount));
|
||||
|
||||
kobject_del(&acg->acg_kobj);
|
||||
kobject_put(&acg->acg_kobj);
|
||||
|
||||
/* acg can be dead here! */
|
||||
|
||||
wait_for_completion(&cmpl);
|
||||
rc = wait_for_completion_timeout(&acg->acg_kobj_release_cmpl, HZ);
|
||||
if (rc == 0) {
|
||||
PRINT_INFO("Waiting for releasing sysfs entry "
|
||||
"for acg %s (%d refs)...", acg->acg_name,
|
||||
atomic_read(&acg->acg_kobj.kref.refcount));
|
||||
wait_for_completion(&acg->acg_kobj_release_cmpl);
|
||||
PRINT_INFO("Done waiting for releasing sysfs "
|
||||
"entry for acg %s", acg->acg_name);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon return, including with an error, if acg_kobj_initialized set
|
||||
* scst_acg_sysfs_del_free() must be called to free acg instead of
|
||||
* __scst_free_acg()!
|
||||
*/
|
||||
int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
struct scst_acg *acg)
|
||||
{
|
||||
@@ -3407,6 +3382,8 @@ int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
init_completion(&acg->acg_kobj_release_cmpl);
|
||||
|
||||
res = kobject_init_and_add(&acg->acg_kobj, &acg_ktype,
|
||||
tgt->tgt_ini_grp_kobj, acg->acg_name);
|
||||
if (res != 0) {
|
||||
@@ -3414,21 +3391,19 @@ int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
acg->acg_kobj_initialized = 1;
|
||||
|
||||
acg->luns_kobj = kobject_create_and_add("luns", &acg->acg_kobj);
|
||||
if (acg->luns_kobj == NULL) {
|
||||
PRINT_ERROR("Can't create luns kobj for tgt %s",
|
||||
tgt->tgt_name);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(acg->luns_kobj, &scst_acg_luns_mgmt.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_luns_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
acg->initiators_kobj = kobject_create_and_add("initiators",
|
||||
@@ -3437,7 +3412,7 @@ int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
PRINT_ERROR("Can't create initiators kobj for tgt %s",
|
||||
tgt->tgt_name);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(acg->initiators_kobj,
|
||||
@@ -3445,33 +3420,37 @@ int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_ini_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&acg->acg_kobj, &scst_acg_addr_method.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_addr_method.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&acg->acg_kobj, &scst_acg_io_grouping_type.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_io_grouping_type.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&acg->acg_kobj, &scst_acg_cpu_mask.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_cpu_mask.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_del:
|
||||
scst_acg_sysfs_del(acg);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
|
||||
|
||||
Reference in New Issue
Block a user