Re: onstream DI 30
patrice peretti wrote:
Bonjour a tous
Slt
J ai installer un seveur de fichier samba sous debian qui 'ailleur
fonctionne a merveille pour remplacer une station NT .
Je desirerai maintenant y ajoindre un lecteru onstream di 30 pour
effectuer les sauvegardes.
Le lecteur est reconnu par le systeme mais il est impossible d'y
acceder ( celui ci se trouve sur hdb)
Il faut utiliser utiliser ce lecteur avec le module ide-scsi et non pas
avec le module ide-tape.
Il faut que tu patches le noyau : télécharge la version officielle du
driver (http://www.linux1onstream.nl/test/onstream-20021231.tar.gz) ou
utilises le patch joint
Ensuite il faudra que tu crées les nodes dans /dev (tu trouveras un
script dans les pages ci-dessous)
Utilises /dev/nosst0 et /dev/osst0 pour accèder au lecteur.
Je l'utilise avec amanda et il marche très bien
Si quelqu'un savait ou je peut trouver un howto pour installer un
onstream sous debian, je lui serais infiniment reconnaissant ??
Site interessant : http://www.netaxs.com/~vossenjp/linux/linux.html
Site très interessant : http://www.linux1onstream.nl/test/ide-tape.html
Site très interessant : http://www.linux1onstream.nl/test/README.osst
Site très interessant :
http://www.e-smith.org/docs/howto/contrib/onstreamdi30-howto.htm
Document utile : http://www.linuxtapecert.org/di30_install.html
Merci encore de l'aide que vous pourriez m'apporter
Patrice
diff -Naur linux-2.4.20/drivers/scsi/osst.c linux-2.4.20-neo/drivers/scsi/osst.c
--- linux-2.4.20/drivers/scsi/osst.c 2001-12-21 18:41:55.000000000 +0100
+++ linux-2.4.20-neo/drivers/scsi/osst.c 2002-12-13 01:54:43.000000000 +0100
@@ -16,15 +16,15 @@
Copyright 1992 - 2000 Kai Makisara
email Kai.Makisara@metla.fi
- $Header: /home/cvsroot/Driver/osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $
+ $Header: /home/cvsroot/Driver/osst.c,v 1.67 2002/12/13 00:54:43 riede Exp $
Microscopic alterations - Rik Ling, 2000/12/21
Last modified: Wed Feb 2 22:04:05 2000 by makisara@kai.makisara.local
Some small formal changes - aeb, 950809
*/
-static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $";
-const char * osst_version = "0.9.10";
+static const char * cvsid = "$Id: osst.c,v 1.67 2002/12/13 00:54:43 riede Exp $";
+const char * osst_version = "0.9.12";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -36,6 +36,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
@@ -75,28 +76,27 @@
#include "constants.h"
-static int buffer_kbs = 0;
+static int max_dev = 0;
static int write_threshold_kbs = 0;
-static int max_buffers = 0;
static int max_sg_segs = 0;
#ifdef MODULE
MODULE_AUTHOR("Willem Riede");
MODULE_DESCRIPTION("OnStream SCSI Tape Driver");
+#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
+#endif
-MODULE_PARM(buffer_kbs, "i");
+MODULE_PARM(max_dev, "i");
MODULE_PARM(write_threshold_kbs, "i");
-MODULE_PARM(max_buffers, "i");
MODULE_PARM(max_sg_segs, "i");
#else
static struct osst_dev_parm {
char *name;
int *val;
} parms[] __initdata = {
- { "buffer_kbs", &buffer_kbs },
+ { "max_dev", &max_dev },
{ "write_threshold_kbs", &write_threshold_kbs },
- { "max_buffers", &max_buffers },
{ "max_sg_segs", &max_sg_segs }
};
#endif
@@ -117,11 +117,16 @@
// #define OSST_INJECT_ERRORS 1
#endif
-#define MAX_RETRIES 0
+#define MAX_RETRIES 2
+#define MAX_READ_RETRIES 0
#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 5
+#define MAX_READY_RETRIES 0
#define NO_TAPE NOT_READY
+#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
+#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
+#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
+
#define OSST_TIMEOUT (200 * HZ)
#define OSST_LONG_TIMEOUT (1800 * HZ)
@@ -137,6 +142,7 @@
static int osst_write_threshold = OSST_WRITE_THRESHOLD;
static int osst_max_buffers = OSST_MAX_BUFFERS;
static int osst_max_sg_segs = OSST_MAX_SG;
+static int osst_max_dev = OSST_MAX_TAPES;
static OS_Scsi_Tape **os_scsi_tapes = NULL;
static OSST_buffer **osst_buffers = NULL;
@@ -539,8 +545,6 @@
STp->first_frame_position);
goto err_out;
}
- STp->frame_in_buffer = 1;
-
if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
if (!quiet)
#if DEBUG
@@ -567,12 +571,14 @@
}
if (aux->frame_type == OS_FRAME_TYPE_EOD) {
STps->eof = ST_EOD_1;
+ STp->frame_in_buffer = 1;
}
if (aux->frame_type == OS_FRAME_TYPE_DATA) {
blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
STp->buffer->buffer_bytes = blk_cnt * blk_sz;
STp->buffer->read_pointer = 0;
+ STp->frame_in_buffer = 1;
/* See what block size was used to write file */
if (STp->block_size != blk_sz && blk_sz > 0) {
@@ -599,18 +605,23 @@
/*
* Wait for the unit to become Ready
*/
-static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
+static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
{
unsigned char cmd[MAX_COMMAND_SIZE];
Scsi_Request * SRpnt;
long startwait = jiffies;
#if DEBUG
int dbg = debugging;
- int dev = TAPE_NR(STp->devt);
+ int dev = TAPE_NR(STp->devt);
printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev);
#endif
+ if (initial_delay > 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(initial_delay);
+ }
+
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
@@ -722,10 +733,10 @@
{
int retval;
- osst_wait_ready(STp, aSRpnt, 15 * 60); /* TODO - can this catch a write error? */
+ osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
if (retval) return (retval);
- osst_wait_ready(STp, aSRpnt, 15 * 60);
+ osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
return (osst_get_frame_position(STp, aSRpnt));
}
@@ -738,6 +749,7 @@
Scsi_Request * SRpnt;
int result = 0;
+ int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG
int dev = TAPE_NR(STp->devt);
@@ -751,12 +763,17 @@
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
-
- if ((STp->buffer)->syscall_result)
- result = osst_write_error_recovery(STp, aSRpnt, 0);
-
- result |= osst_wait_ready(STp, aSRpnt, 5 * 60);
+ if (STp->buffer->syscall_result) {
+ if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
+ if (SRpnt->sr_sense_buffer[13] == 8) {
+ delay = OSST_WAIT_LONG_WRITE_COMPLETE;
+ }
+ } else
+ result = osst_write_error_recovery(STp, aSRpnt, 0);
+ }
+ result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
+
return (result);
}
@@ -847,7 +864,7 @@
printk(OSST_DEB_MSG "osst%d:D: Reading frame from OnStream tape\n", dev);
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_RETRIES, TRUE);
+ STp->timeout, MAX_READ_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt)
return (-EBUSY);
@@ -903,7 +920,8 @@
#endif
if (STps->rw != ST_READING) { /* Initialize read operation */
- if (STps->rw == ST_WRITING) {
+ if (STps->rw == ST_WRITING || STp->dirty) {
+ STp->write_type = OS_WRITE_DATA;
osst_flush_write_buffer(STp, aSRpnt);
osst_flush_drive_buffer(STp, aSRpnt);
}
@@ -921,7 +939,7 @@
#if DEBUG
printk(OSST_DEB_MSG "osst%d:D: Start Read Ahead on OnStream tape\n", dev);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
*aSRpnt = SRpnt;
retval = STp->buffer->syscall_result;
}
@@ -940,6 +958,15 @@
position;
/*
+ * If we want just any frame (-1) and there is a frame in the buffer, return it
+ */
+ if (frame_seq_number == -1 && STp->frame_in_buffer) {
+#if DEBUG
+ printk(OSST_DEB_MSG "osst%d:D: Frame %d still in buffer\n", dev, STp->frame_seq_number);
+#endif
+ return (STps->eof);
+ }
+ /*
* Search and wait for the next logical tape frame
*/
while (1) {
@@ -1092,6 +1119,7 @@
if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
move /= (OS_DATA_SIZE / STp->block_size);
}
+ if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
#if DEBUG
printk(OSST_DEB_MSG
"osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
@@ -1289,7 +1317,7 @@
cmd[8] = 32768 & 0xff;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_RETRIES, TRUE);
+ STp->timeout, MAX_READ_RETRIES, TRUE);
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev);
@@ -1329,7 +1357,7 @@
dev, new_frame+i, frame_seq_number+i);
#endif
osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
- osst_wait_ready(STp, aSRpnt, 60);
+ osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
osst_get_frame_position(STp, aSRpnt);
SRpnt = * aSRpnt;
@@ -1397,6 +1425,7 @@
if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
(SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
/* in the process of becoming ready */
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 10);
continue;
}
@@ -1469,6 +1498,8 @@
osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
flag = 0;
attempts--;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 10);
}
if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
#if DEBUG
@@ -1529,6 +1560,7 @@
debugging = 0;
}
#endif
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 10);
}
printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev);
@@ -1674,12 +1706,7 @@
dev, last_mark_ppos);
return (-EIO);
}
- if (mt_op == MTBSFM) {
- STp->frame_seq_number++;
- STp->frame_in_buffer = 0;
- STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
- }
- return 0;
+ goto found;
}
#if DEBUG
printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev);
@@ -1707,10 +1734,13 @@
return (-EIO);
}
}
+found:
if (mt_op == MTBSFM) {
STp->frame_seq_number++;
- STp->frame_in_buffer = 0;
- STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ STp->frame_in_buffer = 0;
+ STp->buffer->buffer_bytes = 0;
+ STp->buffer->read_pointer = 0;
+ STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
}
@@ -1763,8 +1793,10 @@
}
if (mt_op == MTFSF) {
STp->frame_seq_number++;
- STp->frame_in_buffer = 0;
- STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ STp->frame_in_buffer = 0;
+ STp->buffer->buffer_bytes = 0;
+ STp->buffer->read_pointer = 0;
+ STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
}
@@ -1910,8 +1942,10 @@
}
if (mt_op == MTFSF) {
STp->frame_seq_number++;
- STp->frame_in_buffer = 0;
- STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ STp->frame_in_buffer = 0;
+ STp->buffer->buffer_bytes = 0;
+ STp->buffer->read_pointer = 0;
+ STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
}
@@ -2011,7 +2045,7 @@
#if DEBUG
printk(OSST_DEB_MSG "osst%d:D: Reached onstream write filler group %d\n", dev, where);
#endif
- osst_wait_ready(STp, aSRpnt, 60 * 5);
+ osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
osst_set_frame_position(STp, aSRpnt, where, 0);
STp->write_type = OS_WRITE_FILLER;
while (count--) {
@@ -2037,7 +2071,7 @@
#if DEBUG
printk(OSST_DEB_MSG "osst%d:D: Reached onstream write header group %d\n", dev, where);
#endif
- osst_wait_ready(STp, aSRpnt, 60 * 5);
+ osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
osst_set_frame_position(STp, aSRpnt, where, 0);
STp->write_type = OS_WRITE_HEADER;
while (count--) {
@@ -2377,11 +2411,12 @@
static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
{
+ int write_pass = STp->wrt_pass_cntr;
int frame_position = STp->first_frame_position;
- int frame_seq_numbr = STp->frame_seq_number;
+ int frame_seq_numbr = STp->frame_seq_number;
int logical_blk_num = STp->logical_blk_num;
- int halfway_frame = STp->frame_in_buffer;
- int read_pointer = STp->buffer->read_pointer;
+ int halfway_frame = STp->frame_in_buffer;
+ int read_pointer = STp->buffer->read_pointer;
int prev_mark_ppos = -1;
int actual_mark_ppos, i, n;
#if DEBUG
@@ -2389,12 +2424,24 @@
printk(OSST_DEB_MSG "osst%d:D: Verify that the tape is really the one we think before writing\n", dev);
#endif
- osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
- if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
+ if (frame_position <= STp->first_data_ppos) {
+ /* check header match */
+ if (!osst_analyze_headers(STp, aSRpnt) ||
+ (write_pass != STp->wrt_pass_cntr)) {
#if DEBUG
- printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev);
+ printk(OSST_DEB_MSG "osst%d:D: Couldn't match header in verify_position\n", dev);
#endif
- return (-EIO);
+ return (-EIO);
+ }
+ } else {
+ /* find preceding data frame of current write pass */
+ osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
+ if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
+#if DEBUG
+ printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev);
+#endif
+ return (-EIO);
+ }
}
if (STp->linux_media_version >= 4) {
for (i=0; i<STp->filemark_cnt; i++)
@@ -2671,7 +2718,7 @@
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, SCSI_DATA_READ,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if (!SRpnt) {
STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
return (-EBUSY);
@@ -2692,7 +2739,7 @@
scmd[0] = READ_POSITION;
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if (!STp->buffer->syscall_result)
memcpy (SRpnt->sr_sense_buffer, mysense, 16);
}
@@ -2764,7 +2811,7 @@
scmd[9] = 0x80;
SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout,
- MAX_READY_RETRIES, TRUE);
+ MAX_RETRIES, TRUE);
if (!SRpnt)
return (-EBUSY);
*aSRpnt = SRpnt;
@@ -2777,7 +2824,7 @@
result = (-EIO);
}
if (pp != ppos)
- osst_wait_ready(STp, aSRpnt, 5 * 60);
+ osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
} while ((pp != ppos) && (pp = ppos));
STp->first_frame_position = STp->last_frame_position = ppos;
STps->eof = ST_NOEOF;
@@ -2941,9 +2988,10 @@
return 0;
STps = &(STp->ps[STp->partition]);
- if (STps->rw == ST_WRITING) /* Writing */
+ if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
+ STp->write_type = OS_WRITE_DATA;
return osst_flush_write_buffer(STp, aSRpnt);
-
+ }
if (STp->block_size == 0)
return 0;
@@ -3166,12 +3214,16 @@
if (STps->rw == ST_READING) {
+#if DEBUG
+ printk(OSST_DEB_MSG "osst%d:D: Switching from read to write at file %d, block %d\n", dev,
+ STps->drv_file, STps->drv_block);
+#endif
retval = osst_flush_buffer(STp, &SRpnt, 0);
if (retval)
goto out;
STps->rw = ST_IDLE;
}
- else if (STps->rw != ST_WRITING) {
+ if (STps->rw != ST_WRITING) {
/* Are we totally rewriting this tape? */
if (!STp->header_ok ||
(STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
@@ -3524,9 +3576,19 @@
printk(OSST_DEB_MSG "osst%d:D: EOF up (%d). Left %d, needed %d.\n", dev,
STps->eof, (STp->buffer)->buffer_bytes, count - total);
#endif
+ /* force multiple of block size, note block_size may have been adjusted */
transfer = (((STp->buffer)->buffer_bytes < count - total ?
(STp->buffer)->buffer_bytes : count - total)/
- STp->block_size) * STp->block_size; /* force multiple of block size */
+ STp->block_size) * STp->block_size;
+
+ if (transfer == 0) {
+ printk(KERN_WARNING
+ "osst%d:W: Nothing can be transfered, requested %d, tape block size (%d%c).\n",
+ dev, count, STp->block_size < 1024?
+ STp->block_size:STp->block_size/1024,
+ STp->block_size<1024?'b':'k');
+ break;
+ }
i = from_buffer(STp->buffer, buf, transfer);
if (i) {
retval = i;
@@ -3876,9 +3938,10 @@
}
break;
case MTWEOF:
- if ( STps->rw == ST_WRITING && !(STp->device)->was_reset)
+ if ((STps->rw == ST_WRITING || STp->dirty) && !(STp->device)->was_reset) {
+ STp->write_type = OS_WRITE_DATA;
ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
- else
+ } else
ioctl_result = 0;
#if DEBUG
if (debugging)
@@ -4083,6 +4146,14 @@
if (cmd_in == MTEOM)
STps->eof = ST_EOD;
+ else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
+ ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
+ STps->drv_block++;
+ STp->logical_blk_num++;
+ STp->frame_seq_number++;
+ STp->frame_in_buffer = 0;
+ STp->buffer->read_pointer = 0;
+ }
else if (cmd_in == MTFSF)
STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
else if (chg_eof)
@@ -4091,7 +4162,6 @@
if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
STp->rew_at_close = 0;
else if (cmd_in == MTLOAD) {
-/* STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0; FIXME */
for (i=0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
@@ -4140,10 +4210,15 @@
STp->door_locked = ST_LOCK_FAILS;
if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
- ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60);
+ ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
}
*aSRpnt = SRpnt;
+#if DEBUG
+ printk(OSST_DEB_MSG "osst%d:D: Ioctl %s, ppos %d fseq %d lblk %d bytes %d file %d blk %d\n", dev,
+ ioctl_result?"fail":"success", STp->first_frame_position, STp->frame_seq_number,
+ STp->logical_blk_num, STp->buffer->buffer_bytes, STps->drv_file, STps->drv_block);
+#endif
return ioctl_result;
}
@@ -4263,7 +4338,7 @@
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
STp->timeout, MAX_READY_RETRIES, TRUE);
}
- osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60);
+ osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
}
if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
(SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
@@ -4410,7 +4485,7 @@
}
}
- if (osst_wait_ready(STp, &SRpnt, 15 * 60)) /* FIXME - not allowed with NOBLOCK */
+ if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
printk(KERN_INFO "osst%i:I: Device did not become Ready in open\n",dev);
if ((STp->buffer)->syscall_result != 0) {
@@ -4551,7 +4626,8 @@
STm = &(STp->modes[STp->current_mode]);
STps = &(STp->ps[STp->partition]);
- if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) {
+ if ((STps->rw == ST_WRITING || STp->dirty) && !(STp->device)->was_reset) {
+ STp->write_type = OS_WRITE_DATA;
result = osst_flush_write_buffer(STp, &SRpnt);
if (result != 0 && result != (-ENOSPC))
goto out;
@@ -4816,12 +4892,6 @@
}
if (mtc.mt_op == MTSETPART) {
-/* if (!STp->can_partitions ||
- mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
- return (-EINVAL);
- if (mtc.mt_count >= STp->nbr_partitions &&
- (STp->nbr_partitions = nbr_partitions(inode)) < 0)
- return (-EIO);*/
if (mtc.mt_count >= STp->nbr_partitions)
retval = -EINVAL;
else {
@@ -4886,10 +4956,6 @@
goto out;
}
-/* if (STp->can_partitions &&
- (i = update_partition(inode)) < 0)
- {retval=i;goto out;}*/
-
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
struct mtget mt_status;
@@ -5024,7 +5090,11 @@
tb->sg[0].address =
(unsigned char *)__get_free_pages(priority, order);
if (tb->sg[0].address != NULL) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
tb->sg[0].page = NULL;
+#else
+ tb->sg[0].alt_address = NULL;
+#endif
tb->sg[0].length = b_size;
break;
}
@@ -5060,7 +5130,11 @@
tb = NULL;
break;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
tb->sg[segs].page = NULL;
+#else
+ tb->sg[segs].alt_address = NULL;
+#endif
tb->sg[segs].length = b_size;
got += b_size;
segs++;
@@ -5119,9 +5193,10 @@
for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
segs < max_segs && got < new_size; ) {
STbuffer->sg[segs].address =
- (unsigned char *)__get_free_pages(priority, order);
+ (unsigned char *)__get_free_pages(priority,
+ (new_size - got <= PAGE_SIZE) ? 0 : order);
if (STbuffer->sg[segs].address == NULL) {
- if (new_size - got <= (max_segs - segs) * b_size / 2) {
+ if (new_size - got <= (max_segs - segs) * b_size / 2 && order) {
b_size /= 2; /* Large enough for the rest of the buffers */
order--;
continue;
@@ -5134,10 +5209,14 @@
normalize_buffer(STbuffer);
return FALSE;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
STbuffer->sg[segs].page = NULL;
- STbuffer->sg[segs].length = b_size;
+#else
+ STbuffer->sg[segs].alt_address = NULL;
+#endif
+ STbuffer->sg[segs].length = (new_size - got <= PAGE_SIZE / 2) ? (new_size - got) : b_size;
STbuffer->sg_segs += 1;
- got += b_size;
+ got += STbuffer->sg[segs].length;
STbuffer->buffer_size = got;
segs++;
}
@@ -5320,28 +5399,26 @@
static void validate_options (void)
{
- if (buffer_kbs > 0)
- osst_buffer_size = buffer_kbs * ST_KILOBYTE;
+ if (max_dev > 0)
+ osst_max_dev = osst_max_buffers = max_dev;
if (write_threshold_kbs > 0)
osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
if (osst_write_threshold > osst_buffer_size)
osst_write_threshold = osst_buffer_size;
- if (max_buffers > 0)
- osst_max_buffers = max_buffers;
if (max_sg_segs >= OSST_FIRST_SG)
osst_max_sg_segs = max_sg_segs;
#if DEBUG
- printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n",
+ printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max devices %d, s/g segs %d.\n",
osst_buffer_size, osst_write_threshold, osst_max_buffers, osst_max_sg_segs);
-//printk(OSST_DEB_MSG "osst :D: sizeof(header) = %d (%s)\n",
-// sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error");
#endif
}
#ifndef MODULE
-/* Set the boot options. Syntax: osst=xxx,yyy,...
- where xxx is buffer size in 1024 byte blocks and yyy is write threshold
- in 1024 byte blocks. */
+/* Set the boot options. Syntax: osst=xxx,yyy,zzz
+ * where xxx is maximum nr of devices to attach,
+ * yyy is write threshold in 1024 byte blocks
+ * and zzz the maximum nr of s/g segments to handle.
+ */
static int __init osst_setup (char *str)
{
int i, ints[5];
@@ -5417,6 +5494,72 @@
return 0;
}
+/*
+ * /proc support for accessing ADR header information
+ */
+static struct proc_dir_entry * osst_proc_dir = NULL;
+static char osst_proc_dirname[] = "osst";
+
+static int osst_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int l = 0;
+ OS_Scsi_Tape * STp = (OS_Scsi_Tape *) data;
+
+ if (!osst_proc_dir) return 0;
+
+ if (STp->header_ok && STp->linux_media)
+ l = sprintf(page, "%d.%d LIN%d %8d %8d %8d \n",
+ STp->header_cache->major_rev,
+ STp->header_cache->minor_rev,
+ STp->linux_media_version,
+ STp->first_data_ppos,
+ STp->eod_frame_ppos,
+ STp->filemark_cnt );
+ return l;
+}
+
+static void osst_proc_init(void)
+{
+ if (!proc_scsi) return;
+
+ osst_proc_dir = proc_mkdir(osst_proc_dirname, proc_scsi);
+ osst_proc_dir->owner = THIS_MODULE;
+}
+
+static void osst_proc_create(OS_Scsi_Tape * STp, int dev)
+{
+ char s[16];
+ struct proc_dir_entry * p_entry;
+
+ if (!osst_proc_dir) return;
+
+ sprintf(s, "osst%d", dev);
+ p_entry = create_proc_read_entry(s, 0444, osst_proc_dir, osst_proc_read, (void *) STp);
+ p_entry->owner = THIS_MODULE;
+}
+
+static void osst_proc_destroy(int dev)
+{
+ char s[16];
+
+ if (!osst_proc_dir) return;
+
+ sprintf(s, "osst%d", dev);
+ remove_proc_entry(s, osst_proc_dir);
+}
+
+static void osst_proc_cleanup(void)
+{
+ if ((! proc_scsi) || (!osst_proc_dir)) return;
+
+ remove_proc_entry(osst_proc_dirname, proc_scsi);
+ osst_proc_dir = NULL;
+}
+
+/*
+ * osst startup / cleanup code
+ */
+
static int osst_attach(Scsi_Device * SDp)
{
OS_Scsi_Tape * tpnt;
@@ -5522,7 +5665,8 @@
tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
tpnt->omit_blklims = 1;
- tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
+ tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
+ (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
tpnt->frame_in_buffer = 0;
tpnt->header_ok = 0;
tpnt->linux_media = 0;
@@ -5559,6 +5703,8 @@
osst_template.nr_dev++;
+ osst_proc_create(tpnt, dev);
+
printk(KERN_INFO
"osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as osst%d\n",
SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, dev);
@@ -5597,7 +5743,7 @@
}
if (os_scsi_tapes) return 0;
- osst_template.dev_max = OSST_MAX_TAPES;
+ osst_template.dev_max = osst_max_dev;
if (osst_template.dev_max > 128 / ST_NBR_MODES)
printk(KERN_INFO "osst :I: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
os_scsi_tapes =
@@ -5637,39 +5783,42 @@
printk(OSST_DEB_MSG "osst :D: Buffer size %d bytes, write threshold %d bytes.\n",
osst_buffer_size, osst_write_threshold);
#endif
+ osst_proc_init();
return 0;
}
static void osst_detach(Scsi_Device * SDp)
{
- OS_Scsi_Tape * tpnt;
- int i;
+ OS_Scsi_Tape * tpnt;
+ int i;
#ifdef CONFIG_DEVFS_FS
- int mode;
+ int mode;
#endif
-
- for(i=0; i<osst_template.dev_max; i++) {
- tpnt = os_scsi_tapes[i];
- if(tpnt != NULL && tpnt->device == SDp) {
- tpnt->device = NULL;
+ for(i=0; i<osst_template.dev_max; i++) {
+ tpnt = os_scsi_tapes[i];
+ if(tpnt != NULL && tpnt->device == SDp) {
+ osst_proc_destroy(i);
+ tpnt->device = NULL;
#ifdef CONFIG_DEVFS_FS
- for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- devfs_unregister (tpnt->de_r[mode]);
- tpnt->de_r[mode] = NULL;
- devfs_unregister (tpnt->de_n[mode]);
- tpnt->de_n[mode] = NULL;
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ devfs_unregister (tpnt->de_r[mode]);
+ tpnt->de_r[mode] = NULL;
+ devfs_unregister (tpnt->de_n[mode]);
+ tpnt->de_n[mode] = NULL;
+ }
+#endif
+ if (tpnt->header_cache != NULL) {
+ vfree(tpnt->header_cache);
+ }
+ kfree(tpnt);
+ os_scsi_tapes[i] = NULL;
+ SDp->attached--;
+ osst_template.nr_dev--;
+ osst_template.dev_noticed--;
+ return;
}
-#endif
- kfree(tpnt);
- os_scsi_tapes[i] = NULL;
- SDp->attached--;
- osst_template.nr_dev--;
- osst_template.dev_noticed--;
- return;
}
- }
- return;
}
static int __init init_osst(void)
@@ -5681,38 +5830,32 @@
static void __exit exit_osst (void)
{
- int i;
- OS_Scsi_Tape * STp;
+ int i;
- scsi_unregister_module(MODULE_SCSI_DEV, &osst_template);
+ scsi_unregister_module(MODULE_SCSI_DEV, &osst_template);
#ifdef CONFIG_DEVFS_FS
- devfs_unregister_chrdev(MAJOR_NR, "osst");
+ devfs_unregister_chrdev(MAJOR_NR, "osst");
#else
- unregister_chrdev(MAJOR_NR, "osst");
+ unregister_chrdev(MAJOR_NR, "osst");
#endif
- osst_registered--;
- if(os_scsi_tapes != NULL) {
- for (i=0; i < osst_template.dev_max; ++i) {
- if ((STp = os_scsi_tapes[i])) {
- if (STp->header_cache != NULL) vfree(STp->header_cache);
- kfree(STp);
- }
- }
- kfree(os_scsi_tapes);
+ osst_registered--;
+ osst_proc_cleanup();
+
+ if(os_scsi_tapes != NULL) {
+ kfree(os_scsi_tapes);
+ }
if (osst_buffers != NULL) {
for (i=0; i < osst_nbr_buffers; i++)
- if (osst_buffers[i] != NULL) {
- osst_buffers[i]->orig_sg_segs = 0;
- normalize_buffer(osst_buffers[i]);
- kfree(osst_buffers[i]);
- }
-
+ if (osst_buffers[i] != NULL) {
+ osst_buffers[i]->orig_sg_segs = 0;
+ normalize_buffer(osst_buffers[i]);
+ kfree(osst_buffers[i]);
+ }
kfree(osst_buffers);
}
- }
- osst_template.dev_max = 0;
- printk(KERN_INFO "osst :I: Unloaded.\n");
+ osst_template.dev_max = 0;
+ printk(KERN_INFO "osst :I: Unloaded.\n");
}
module_init(init_osst);
Reply to:
- References:
- onstream DI 30
- From: patrice peretti <patrice.peretti@club-internet.fr>