diff --git a/scst/include/scst_user.h b/scst/include/scst_user.h index 40e23c170..f89630d95 100644 --- a/scst/include/scst_user.h +++ b/scst/include/scst_user.h @@ -185,10 +185,10 @@ struct scst_user_tm { }; struct scst_user_get_cmd { - aligned_u64 preply; uint32_t cmd_h; uint32_t subcode; union { + aligned_u64 preply; struct scst_user_sess sess; struct scst_user_scsi_cmd_parse parse_cmd; struct scst_user_scsi_cmd_alloc_mem alloc_cmd; diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index df9b6bddf..2ceabdf72 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -923,7 +923,6 @@ static void dev_user_on_free_cmd(struct scst_cmd *cmd) if (unlikely(!ucmd->seen_by_user)) { TRACE_MGMT_DBG("Not seen by user ucmd %p", ucmd); - sBUG_ON((ucmd->sgv != NULL) || (ucmd->data_pages != NULL)); goto out_reply; } @@ -1683,7 +1682,10 @@ static int dev_user_reply_get_cmd(struct file *file, void __user *arg) down_read(&dev->dev_rwsem); mutex_unlock(&dev_priv_mutex); - res = copy_from_user(&ureply, arg, sizeof(ureply)); + /* get_user() can't be used with 64-bit values on x86_32 */ + res = copy_from_user(&ureply, (uint64_t __user *) + &((struct scst_user_get_cmd *)arg)->preply, + sizeof(ureply)); if (res < 0) goto out_up; diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 69ecede93..681078ef8 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -420,8 +420,19 @@ void scst_unregister(struct scst_tgt *tgt) TRACE_DBG("%s", "Target driver's release() returned"); mutex_lock(&scst_mutex); +again: list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { - sBUG_ON(sess->shut_phase == SCST_SESS_SPH_READY); + if (sess->shut_phase == SCST_SESS_SPH_READY) { + /* + * Sometimes it's hard for target driver to track all + * its sessions (see scst_local, for example), so let's + * help it. + */ + mutex_unlock(&scst_mutex); + scst_unregister_session(sess, 0, NULL); + mutex_lock(&scst_mutex); + goto again; + } } mutex_unlock(&scst_mutex);