diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index d09b55ce1..e280cea16 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -1308,13 +1308,17 @@ next: res = scst_pr_set_cluster_mode(dev, dev->cluster_mode, virt_dev->t10_dev_id); + if (res) + goto out; + + percpu_ref_get(&dev->refcnt); out: TRACE_EXIT(); return res; } -/* scst_mutex supposed to be held */ +/* Detach a virtual device from a device. scst_mutex is supposed to be held. */ static void vdisk_detach(struct scst_device *dev) { struct scst_vdisk_dev *virt_dev = dev->dh_priv; @@ -1332,6 +1336,8 @@ static void vdisk_detach(struct scst_device *dev) /* virt_dev will be freed by the caller */ dev->dh_priv = NULL; + virt_dev->dev = NULL; + percpu_ref_put(&dev->refcnt); TRACE_EXIT(); return; diff --git a/scst/src/scst_copy_mgr.c b/scst/src/scst_copy_mgr.c index 90eb25a7a..44a750126 100644 --- a/scst/src/scst_copy_mgr.c +++ b/scst/src/scst_copy_mgr.c @@ -2441,6 +2441,7 @@ out_put: scst_put_buf_full(cmd, buf); out: + percpu_ref_put(&dev->refcnt); TRACE_EXIT(); return; } @@ -2464,6 +2465,7 @@ static int scst_cm_send_init_inquiry(struct scst_device *dev, } priv->cm_init_inq_finish_fn = scst_cm_init_inq_finish; priv->dev = dev; + percpu_ref_get(&dev->refcnt); } lun = scst_pack_lun(unpacked_lun, scst_cm_sess->acg->addr_method); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 28d1967e7..612946eb6 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4344,6 +4344,8 @@ static struct scst_acg_dev *scst_alloc_acg_dev(struct scst_acg *acg, res->acg = acg; res->lun = lun; + percpu_ref_get(&dev->refcnt); + out: TRACE_EXIT_HRES(res); return res; @@ -4374,6 +4376,7 @@ static void scst_del_acg_dev(struct scst_acg_dev *acg_dev, */ static void scst_free_acg_dev(struct scst_acg_dev *acg_dev) { + percpu_ref_put(&acg_dev->dev->refcnt); kmem_cache_free(scst_acgd_cachep, acg_dev); } @@ -5467,6 +5470,8 @@ static int scst_alloc_add_tgt_dev(struct scst_session *sess, *out_tgt_dev = tgt_dev; + percpu_ref_get(&dev->refcnt); + out: TRACE_EXIT_RES(res); return res; @@ -5569,6 +5574,8 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev) kmem_cache_free(scst_tgtd_cachep, tgt_dev); + percpu_ref_put(&dev->refcnt); + TRACE_EXIT(); return; } @@ -5770,8 +5777,7 @@ struct scst_cmd *__scst_create_prepare_internal_cmd(const uint8_t *cdb, } scst_sess_get(res->sess); - if (res->tgt_dev != NULL) - res->cpu_cmd_counter = scst_get(); + res->cpu_cmd_counter = scst_get(); TRACE(TRACE_SCSI, "New internal cmd %p (op %s)", res, scst_get_opcode_name(res)); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 5ca787b74..282e56724 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -558,6 +558,8 @@ static void __scst_rx_cmd(struct scst_cmd *cmd, struct scst_session *sess, { TRACE_ENTRY(); + WARN_ON_ONCE(cmd->cpu_cmd_counter); + cmd->sess = sess; scst_sess_get(sess);