Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH 1/2] SCSI tape: add option to use SILI in variable block reads
@ 2008-02-24 20:23 Kai Makisara
  2008-02-24 20:29 ` [PATCH 2/2] SCSI tape: show options currently set in sysfs Kai Makisara
  0 siblings, 1 reply; 3+ messages in thread
From: Kai Makisara @ 2008-02-24 20:23 UTC (permalink / raw)
  To: linux-scsi

[-- Attachment #1: Type: TEXT/PLAIN, Size: 9261 bytes --]

Add new option MT_ST_SILI to enable setting the SILI bit in reads in variable
block mode. If SILI is set, reading a block shorter than the byte count does
not result in CHECK CONDITION. The length of the block is determined using the
residual count from the HBA. Avoiding the REQUEST SENSE command for every
block speeds up some real applications considerably.

Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi>
---
The patch is against Feb 24 git version of 2.5.25-rc2. Candidate for
inclusion into 2.6.26.

 Documentation/scsi/st.txt |    7 ++++++-
 drivers/scsi/st.c         |   40 ++++++++++++++++++++++++++++++++++++----
 drivers/scsi/st.h         |    3 +++
 drivers/scsi/st_options.h |    6 +++++-
 include/linux/mtio.h      |    1 +
 5 files changed, 51 insertions(+), 6 deletions(-)

Index: linux-2.6.25-rc2-q/drivers/scsi/st.c
===================================================================
--- linux-2.6.25-rc2-q.orig/drivers/scsi/st.c
+++ linux-2.6.25-rc2-q/drivers/scsi/st.c
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20080221";
+static const char *verstr = "20080224";
 
 #include <linux/module.h>
 
@@ -183,6 +183,7 @@ static int modes_defined;
 
 static struct st_buffer *new_tape_buffer(int, int, int);
 static int enlarge_buffer(struct st_buffer *, int, int);
+static void clear_buffer(struct st_buffer *);
 static void normalize_buffer(struct st_buffer *);
 static int append_to_buffer(const char __user *, struct st_buffer *, int);
 static int from_buffer(struct st_buffer *, char __user *, int);
@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, ch
 
 	memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
 	(STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
+	(STp->buffer)->cmdstat.residual = resid;
 	DEB( STp->write_pending = 0; )
 
 	if (SRpnt->waiting)
@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, 
 		goto err_out;
 	}
 
+	(STp->buffer)->cleared = 0;
 	(STp->buffer)->writing = 0;
 	(STp->buffer)->syscall_result = 0;
 
@@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_t
 		if (STp->block_size)
 			bufsize = STp->block_size > st_fixed_buffer_size ?
 				STp->block_size : st_fixed_buffer_size;
-		else
+		else {
 			bufsize = count;
+			/* Make sure that data from previous user is not leaked even if
+			   HBA does not return correct residual */
+			if (is_read && STp->sili && !STbp->cleared)
+				clear_buffer(STbp);
+		}
+
 		if (bufsize > STbp->buffer_size &&
 		    !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
 			printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
@@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = READ_6;
 	cmd[1] = (STp->block_size != 0);
+	if (!cmd[1] && STp->sili)
+		cmd[1] |= 2;
 	cmd[2] = blks >> 16;
 	cmd[3] = blks >> 8;
 	cmd[4] = blks;
@@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *
 
 	}
 	/* End of error handling */ 
-	else			/* Read successful */
+	else {			/* Read successful */
 		STbp->buffer_bytes = bytes;
+		if (STp->sili) /* In fixed block mode residual is always zero here */
+			STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
+	}
 
 	if (STps->drv_block >= 0) {
 		if (STp->block_size == 0)
@@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_t
 		       name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
 		       STp->scsi2_logical);
 		printk(KERN_INFO
-		       "%s:    sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate);
+		       "%s:    sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
+			STp->sili);
 		printk(KERN_INFO "%s:    debugging: %d\n",
 		       name, debugging);
 	}
@@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_ta
 		STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
 		STp->immediate = (options & MT_ST_NOWAIT) != 0;
 		STm->sysv = (options & MT_ST_SYSV) != 0;
+		STp->sili = (options & MT_ST_SILI) != 0;
 		DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
 		     st_log_options(STp, STm, name); )
 	} else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
@@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_ta
 			STp->immediate = value;
 		if ((options & MT_ST_SYSV) != 0)
 			STm->sysv = value;
+		if ((options & MT_ST_SILI) != 0)
+			STp->sili = value;
                 DEB(
 		if ((options & MT_ST_DEBUGGING) != 0)
 			debugging = value;
@@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buff
 		STbuffer->frp_segs += 1;
 		got += b_size;
 		STbuffer->buffer_size = got;
+		if (STbuffer->cleared)
+			memset(page_address(STbuffer->frp[segs].page), 0, b_size);
 		segs++;
 	}
 	STbuffer->b_data = page_address(STbuffer->frp[0].page);
@@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buff
 }
 
 
+/* Make sure that no data from previous user is in the internal buffer */
+static void clear_buffer(struct st_buffer * st_bp)
+{
+	int i;
+
+	for (i=0; i < st_bp->frp_segs; i++)
+		memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
+	st_bp->cleared = 1;
+}
+
+
 /* Release the extra buffer */
 static void normalize_buffer(struct st_buffer * STbuffer)
 {
@@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev)
 	tpnt->two_fm = ST_TWO_FM;
 	tpnt->fast_mteom = ST_FAST_MTEOM;
 	tpnt->scsi2_logical = ST_SCSI2LOGICAL;
+	tpnt->sili = ST_SILI;
 	tpnt->immediate = ST_NOWAIT;
 	tpnt->default_drvbuffer = 0xff;		/* No forced buffering */
 	tpnt->partition = 0;
Index: linux-2.6.25-rc2-q/drivers/scsi/st.h
===================================================================
--- linux-2.6.25-rc2-q.orig/drivers/scsi/st.h
+++ linux-2.6.25-rc2-q/drivers/scsi/st.h
@@ -12,6 +12,7 @@ struct st_cmdstatus {
 	int midlevel_result;
 	struct scsi_sense_hdr sense_hdr;
 	int have_sense;
+	int residual;
 	u64 uremainder64;
 	u8 flags;
 	u8 remainder_valid;
@@ -34,6 +35,7 @@ struct st_request {
 struct st_buffer {
 	unsigned char dma;	/* DMA-able buffer */
 	unsigned char do_dio;   /* direct i/o set up? */
+	unsigned char cleared;  /* internal buffer cleared after open? */
 	int buffer_size;
 	int buffer_blocks;
 	int buffer_bytes;
@@ -122,6 +124,7 @@ struct scsi_tape {
 	unsigned char try_dio_now;		/* try direct i/o before next close? */
 	unsigned char c_algo;			/* compression algorithm */
 	unsigned char pos_unknown;			/* after reset position unknown */
+	unsigned char sili;			/* use SILI when reading in variable b mode */
 	int tape_type;
 	int long_timeout;	/* timeout for commands known to take long time */
 
Index: linux-2.6.25-rc2-q/drivers/scsi/st_options.h
===================================================================
--- linux-2.6.25-rc2-q.orig/drivers/scsi/st_options.h
+++ linux-2.6.25-rc2-q/drivers/scsi/st_options.h
@@ -3,7 +3,7 @@
 
    Copyright 1995-2003 Kai Makisara.
 
-   Last modified: Mon Apr  7 22:49:18 2003 by makisara
+   Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
 */
 
 #ifndef _ST_OPTIONS_H
@@ -94,6 +94,10 @@
    The default is BSD semantics. */
 #define ST_SYSV 0
 
+/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block
+   mode and the block size is determined using the residual returned by the HBA. */
+#define ST_SILI 0
+
 /* Time to wait for the drive to become ready if blocking open */
 #define ST_BLOCK_SECONDS     120
 
Index: linux-2.6.25-rc2-q/include/linux/mtio.h
===================================================================
--- linux-2.6.25-rc2-q.orig/include/linux/mtio.h
+++ linux-2.6.25-rc2-q/include/linux/mtio.h
@@ -192,6 +192,7 @@ struct	mtpos {
 #define MT_ST_SCSI2LOGICAL      0x800
 #define MT_ST_SYSV              0x1000
 #define MT_ST_NOWAIT            0x2000
+#define MT_ST_SILI		0x4000
 
 /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
 #define MT_ST_CLEAR_DEFAULT	0xfffff
Index: linux-2.6.25-rc2-q/Documentation/scsi/st.txt
===================================================================
--- linux-2.6.25-rc2-q.orig/Documentation/scsi/st.txt
+++ linux-2.6.25-rc2-q/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@ This file contains brief information abo
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Mon Mar  7 21:14:44 2005 by kai.makisara
+Last modified: Thu Feb 21 21:54:16 2008 by kai.makisara
 
 
 BASICS
@@ -372,6 +372,11 @@ MTSETDRVBUFFER
 	     MT_ST_SYSV sets the SYSV semantics (mode)
 	     MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
 	        the command to finish) for some commands (e.g., rewind)
+	     MT_ST_SILI enables setting the SILI bit in SCSI commands when
+		reading in variable block mode to enhance performance when
+		reading blocks shorter than the byte count; set this only
+		if you are sure that the drive supports SILI and the HBA
+		correctly returns transfer residuals
 	     MT_ST_DEBUGGING debugging (global; debugging must be
 		compiled into the driver)
 	MT_ST_SETBOOLEANS

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/2] SCSI tape: show options currently set in sysfs
  2008-02-24 20:23 [PATCH 1/2] SCSI tape: add option to use SILI in variable block reads Kai Makisara
@ 2008-02-24 20:29 ` Kai Makisara
  2008-02-24 22:23   ` Randy Dunlap
  0 siblings, 1 reply; 3+ messages in thread
From: Kai Makisara @ 2008-02-24 20:29 UTC (permalink / raw)
  To: linux-scsi

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4144 bytes --]

Show the current binary tape driver and mode options is sysfs. A file
(options) is created in each directory in /sys/class/scsi_tape. The files
contain masks showing the options. The mask bit definitions are the same as
used when setting the options using the MTSETDRVBUFFER function in the
MTIOCTOP ioctl (defined in include/linux/mtio.h). For example:
> cat /sys/class/scsi_tape/nst0/options 
0x00000d07

Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi>
---
The patch is against Feb 24 git version of 2.6.25-rc2. Candidate for
inclusion into 2.6.26.

 Documentation/scsi/st.txt |    7 ++++++-
 drivers/scsi/st.c         |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

Index: linux-2.6.25-rc2-q/drivers/scsi/st.c
===================================================================
--- linux-2.6.25-rc2-q.orig/drivers/scsi/st.c
+++ linux-2.6.25-rc2-q/drivers/scsi/st.c
@@ -4365,6 +4365,46 @@ static ssize_t st_defcompression_show(st
 
 CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
 
+static ssize_t st_options_show(struct class_device *class_dev, char *buf)
+{
+	struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
+	struct scsi_tape *STp;
+	int i, j, options;
+	ssize_t l = 0;
+
+	for (i=0; i < st_dev_max; i++) {
+		for (j=0; j < ST_NBR_MODES; j++)
+			if (&scsi_tapes[i]->modes[j] == STm)
+				break;
+		if (j < ST_NBR_MODES)
+			break;
+	}
+	if (i == st_dev_max)
+		return 0;  /* should never happen */
+
+	STp = scsi_tapes[i];
+
+	options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
+	options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
+	options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
+	DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
+	options |= STp->two_fm ? MT_ST_TWO_FM : 0;
+	options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
+	options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
+	options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
+	options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
+	options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
+	options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
+	options |= STm->sysv ? MT_ST_SYSV : 0;
+	options |= STp->immediate ? MT_ST_NOWAIT : 0;
+	options |= STp->sili ? MT_ST_SILI : 0;
+
+	l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
+
 static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
 {
 	int i, rew, error;
@@ -4402,6 +4442,9 @@ static int do_create_class_files(struct 
 		error = class_device_create_file(st_class_member,
 				        &class_device_attr_default_compression);
 		if (error) goto out;
+		error = class_device_create_file(st_class_member,
+				        &class_device_attr_options);
+		if (error) goto out;
 
 		if (mode == 0 && rew == 0) {
 			error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
Index: linux-2.6.25-rc2-q/Documentation/scsi/st.txt
===================================================================
--- linux-2.6.25-rc2-q.orig/Documentation/scsi/st.txt
+++ linux-2.6.25-rc2-q/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@ This file contains brief information abo
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Thu Feb 21 21:54:16 2008 by kai.makisara
+Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
 
 
 BASICS
@@ -133,6 +133,11 @@ the defaults set by the user. The value 
 file 'dev' contains the device numbers corresponding to this device. The links
 'device' and 'driver' point to the SCSI device and driver entries.
 
+Each directory acontains also the entry 'options' which shows the currently
+enabled driver and mode options. The value in the file is a bit mask where the
+bit definitions are the same as those used with MTSETDRVBUFFER in setting the
+options.
+
 A link named 'tape' is made from the SCSI device directory to the class
 directory corresponding to the mode 0 auto-rewind device (e.g., st0). 
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 2/2] SCSI tape: show options currently set in sysfs
  2008-02-24 20:29 ` [PATCH 2/2] SCSI tape: show options currently set in sysfs Kai Makisara
@ 2008-02-24 22:23   ` Randy Dunlap
  0 siblings, 0 replies; 3+ messages in thread
From: Randy Dunlap @ 2008-02-24 22:23 UTC (permalink / raw)
  To: Kai Makisara; +Cc: linux-scsi

On Sun, 24 Feb 2008 22:29:12 +0200 (EET) Kai Makisara wrote:

>  Documentation/scsi/st.txt |    7 ++++++-

> Index: linux-2.6.25-rc2-q/Documentation/scsi/st.txt
> ===================================================================
> --- linux-2.6.25-rc2-q.orig/Documentation/scsi/st.txt
> +++ linux-2.6.25-rc2-q/Documentation/scsi/st.txt
> @@ -133,6 +133,11 @@ the defaults set by the user. The value 
>  file 'dev' contains the device numbers corresponding to this device. The links
>  'device' and 'driver' point to the SCSI device and driver entries.
>  
> +Each directory acontains also the entry 'options' which shows the currently

                  also contains the entry 'options'

> +enabled driver and mode options. The value in the file is a bit mask where the
> +bit definitions are the same as those used with MTSETDRVBUFFER in setting the
> +options.
> +
>  A link named 'tape' is made from the SCSI device directory to the class
>  directory corresponding to the mode 0 auto-rewind device (e.g., st0). 


---
~Randy

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-02-24 22:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-24 20:23 [PATCH 1/2] SCSI tape: add option to use SILI in variable block reads Kai Makisara
2008-02-24 20:29 ` [PATCH 2/2] SCSI tape: show options currently set in sysfs Kai Makisara
2008-02-24 22:23   ` Randy Dunlap

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox