summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-10-26 23:25:42 +0000
committermav <mav@FreeBSD.org>2014-10-26 23:25:42 +0000
commit6a4642451ed02bdd3f5f5f5f0a1c2cc4d4dd79ab (patch)
tree6e091cec36a74b50c7517d9720b7a960b2c03e09 /sys/cam/ctl
parenta98b0367069272b091a9a1a9ba22b4cc11436307 (diff)
downloadFreeBSD-src-6a4642451ed02bdd3f5f5f5f0a1c2cc4d4dd79ab.zip
FreeBSD-src-6a4642451ed02bdd3f5f5f5f0a1c2cc4d4dd79ab.tar.gz
Allocate buffer for READ BUFFER/WRITE BUFFER commands on demand.
These commands are rare, but consume additional 256KB RAM per LUN. MFC after: 1 week
Diffstat (limited to 'sys/cam/ctl')
-rw-r--r--sys/cam/ctl/ctl.c18
-rw-r--r--sys/cam/ctl/ctl_private.h4
2 files changed, 17 insertions, 5 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 2a7ed7f..0f34b75 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -4735,6 +4735,7 @@ ctl_free_lun(struct ctl_lun *lun)
ctl_tpc_lun_shutdown(lun);
mtx_destroy(&lun->lun_lock);
free(lun->lun_devid, M_CTL);
+ free(lun->write_buffer, M_CTL);
if (lun->flags & CTL_LUN_MALLOCED)
free(lun, M_CTL);
@@ -5726,7 +5727,7 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
len = scsi_3btoul(cdb->length);
buffer_offset = scsi_3btoul(cdb->offset);
- if (buffer_offset + len > sizeof(lun->write_buffer)) {
+ if (buffer_offset + len > CTL_WRITE_BUFFER_SIZE) {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
@@ -5739,14 +5740,19 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
if ((cdb->byte2 & RWB_MODE) == RWB_MODE_DESCR) {
descr[0] = 0;
- scsi_ulto3b(sizeof(lun->write_buffer), &descr[1]);
+ scsi_ulto3b(CTL_WRITE_BUFFER_SIZE, &descr[1]);
ctsio->kern_data_ptr = descr;
len = min(len, sizeof(descr));
} else if ((cdb->byte2 & RWB_MODE) == RWB_MODE_ECHO_DESCR) {
ctsio->kern_data_ptr = echo_descr;
len = min(len, sizeof(echo_descr));
- } else
+ } else {
+ if (lun->write_buffer == NULL) {
+ lun->write_buffer = malloc(CTL_WRITE_BUFFER_SIZE,
+ M_CTL, M_WAITOK);
+ }
ctsio->kern_data_ptr = lun->write_buffer + buffer_offset;
+ }
ctsio->kern_data_len = len;
ctsio->kern_total_len = len;
ctsio->kern_data_resid = 0;
@@ -5784,7 +5790,7 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
len = scsi_3btoul(cdb->length);
buffer_offset = scsi_3btoul(cdb->offset);
- if (buffer_offset + len > sizeof(lun->write_buffer)) {
+ if (buffer_offset + len > CTL_WRITE_BUFFER_SIZE) {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
@@ -5800,6 +5806,10 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
* malloc it and tell the caller the data buffer is here.
*/
if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
+ if (lun->write_buffer == NULL) {
+ lun->write_buffer = malloc(CTL_WRITE_BUFFER_SIZE,
+ M_CTL, M_WAITOK);
+ }
ctsio->kern_data_ptr = lun->write_buffer + buffer_offset;
ctsio->kern_data_len = len;
ctsio->kern_total_len = len;
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index c470345..bb9a32d 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -384,6 +384,8 @@ struct ctl_devid {
*/
#define NUM_TARGET_PORT_GROUPS 2
+#define CTL_WRITE_BUFFER_SIZE 262144
+
struct tpc_list;
struct ctl_lun {
struct mtx lun_lock;
@@ -417,7 +419,7 @@ struct ctl_lun {
int pr_key_count;
uint32_t pr_res_idx;
uint8_t res_type;
- uint8_t write_buffer[262144];
+ uint8_t *write_buffer;
struct ctl_devid *lun_devid;
TAILQ_HEAD(tpc_lists, tpc_list) tpc_lists;
};
OpenPOWER on IntegriCloud