diff --git a/scst/include/scst.h b/scst/include/scst.h index 31ac605ee..47162e3ff 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2501,6 +2501,9 @@ struct scst_device { /* List of blocked commands, protected by dev_lock. */ struct list_head blocked_cmd_list; + /* MAXIMUM WRITE SAME LENGTH in bytes */ + uint64_t max_write_same_len; + /* A list entry used during TM */ struct list_head tm_dev_list_entry; diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index be0372a20..20fcba6d5 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2558,8 +2558,9 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p) } } - /* MAXIMUM WRITE SAME LENGTH (512MB) */ - put_unaligned_be64((512*1024*1024) >> dev->block_shift, &buf[36]); + /* MAXIMUM WRITE SAME LENGTH (measured in blocks) */ + put_unaligned_be64(dev->max_write_same_len >> + dev->block_shift, &buf[36]); resp_len = buf[3] + 4; } else if ((0xB1 == cmd->cdb[2]) && (dev->type == TYPE_DISK)) { diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 5a9bce286..4a698bd5f 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4870,7 +4870,7 @@ void scst_write_same(struct scst_cmd *cmd) } if (cmd->sg_cnt != 1) { - PRINT_ERROR("WRITE SAME must contain only single block of data " + PRINT_WARNING("WRITE SAME must contain only single block of data " "in a single SG (cmd %p)", cmd); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_parameter_value_invalid)); goto out_done; @@ -4881,6 +4881,14 @@ void scst_write_same(struct scst_cmd *cmd) goto out_done; } + if (unlikely((uint64_t)cmd->data_len > cmd->dev->max_write_same_len)) { + PRINT_WARNING("Invalid WRITE SAME data len %lld (max allowed " + "%lld)", (long long)cmd->data_len, + (long long)cmd->dev->max_write_same_len); + scst_set_invalid_field_in_cdb(cmd, cmd->len_off, 0); + goto out_done; + } + wsp = kzalloc(sizeof(*wsp), GFP_KERNEL); if (wsp == NULL) { PRINT_ERROR("Unable to allocate ws_priv (size %zd, cmd %p)", diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index bdd27987e..a6bf13269 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -2080,6 +2080,7 @@ assign: dev->threads_num = handler->threads_num; dev->threads_pool_type = handler->threads_pool_type; + dev->max_write_same_len = 512 * 1024 * 1024; /* 512 MB */ if (handler->attach) { TRACE_DBG("Calling new dev handler's attach(%p)", dev);