From 8619defedcd21adfc4a8c53c40c9707f46d2e580 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 7 Apr 2011 19:45:38 +0000 Subject: [PATCH] Partially merged r3194 and r3203 from the trunk. git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.0.0.x@3366 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst_local/scst_local.c | 50 +++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index bba18c8f2..b6f682536 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -86,9 +86,6 @@ static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS; #define scsi_bufflen(cmd) ((cmd)->request_bufflen) #endif -#define TRUE 1 -#define FALSE 0 - #define SCST_LOCAL_VERSION "1.0.0" static const char *scst_local_version_date = "20100910"; @@ -781,7 +778,7 @@ static int scst_local_abort(struct scsi_cmnd *SCpnt) sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host)); ret = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, SCpnt->tag, - FALSE, &dev_reset_completion); + false, &dev_reset_completion); /* Now wait for the completion ... */ wait_for_completion_interruptible(&dev_reset_completion); @@ -810,7 +807,7 @@ static int scst_local_device_reset(struct scsi_cmnd *SCpnt) lun = cpu_to_be16(lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET, - (const uint8_t *)&lun, sizeof(lun), FALSE, + (const uint8_t *)&lun, sizeof(lun), false, &dev_reset_completion); /* Now wait for the completion ... */ @@ -841,7 +838,7 @@ static int scst_local_target_reset(struct scsi_cmnd *SCpnt) lun = cpu_to_be16(lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET, - (const uint8_t *)&lun, sizeof(lun), FALSE, + (const uint8_t *)&lun, sizeof(lun), false, &dev_reset_completion); /* Now wait for the completion ... */ @@ -908,8 +905,8 @@ static int scst_local_send_resp(struct scsi_cmnd *cmnd, * This does the heavy lifting ... we pass all the commands on to the * target driver and have it do its magic ... */ -static int scst_local_queuecommand(struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) +static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) __acquires(&h->host_lock) __releases(&h->host_lock) { @@ -940,11 +937,11 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt, if (!tgt_specific) { PRINT_ERROR("Unable to create tgt_specific (size %zu)", sizeof(*tgt_specific)); - return -ENOMEM; + return SCSI_MLQUEUE_HOST_BUSY; } tgt_specific->cmnd = SCpnt; tgt_specific->done = done; -#else +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) /* * We save a pointer to the done routine in SCpnt->scsi_done and * we save that as tgt specific stuff below. @@ -955,14 +952,18 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt, /* * Tell the target that we have a command ... but first we need * to get the LUN into a format that SCST understand + * + * NOTE! We need to call it with atomic parameter true to not + * get into mem alloc deadlock when mounting file systems over + * our devices. */ lun = SCpnt->device->lun; lun = cpu_to_be16(lun); scst_cmd = scst_rx_cmd(sess->scst_sess, (const uint8_t *)&lun, - sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, TRUE); + sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, true); if (!scst_cmd) { PRINT_ERROR("%s", "scst_rx_cmd() failed"); - return -ENOMEM; + return SCSI_MLQUEUE_HOST_BUSY; } scst_cmd_set_tag(scst_cmd, SCpnt->tag); @@ -1054,6 +1055,15 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt, scst_cmd_set_tgt_priv(scst_cmd, SCpnt); #endif +/* + * Although starting from 2.6.37 queuecommand() called with no host_lock + * held, in reality without DEF_SCSI_QCMD() this doesn't work and leading + * to various problems like commands lost under highload. So, until that fixed + * we have to go ahead under host_lock, although absolutely don't need it. + * + * NOTE! At the moment in scst_estimate_context*() returning DIRECT contexts + * disabled, so this option doesn't have any real effect. + */ #ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING { struct Scsi_Host *h = SCpnt->device->host; @@ -1073,6 +1083,14 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt, return 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +/* + * See comment in scst_local_queuecommand_lck() near + * CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING + */ +static DEF_SCSI_QCMD(scst_local_queuecommand) +#endif + static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd) { int res = SCST_PREPROCESS_STATUS_SUCCESS; @@ -1372,7 +1390,11 @@ static struct scsi_host_template scst_lcl_ini_driver_template = { .info = scst_local_info, #endif .name = SCST_LOCAL_NAME, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + .queuecommand = scst_local_queuecommand_lck, +#else .queuecommand = scst_local_queuecommand, +#endif .eh_abort_handler = scst_local_abort, .eh_device_reset_handler = scst_local_device_reset, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)) @@ -1534,7 +1556,7 @@ static void scst_local_release_adapter(struct device *dev) cancel_work_sync(&sess->aen_work); #endif - scst_unregister_session(sess->scst_sess, TRUE, NULL); + scst_unregister_session(sess->scst_sess, true, NULL); kfree(sess); @@ -1635,7 +1657,7 @@ unregister_dev: #endif unregister_session: - scst_unregister_session(sess->scst_sess, TRUE, NULL); + scst_unregister_session(sess->scst_sess, true, NULL); out_free: kfree(sess);