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 [EMAIL PROTECTED]
- $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 [EMAIL PROTECTED]
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);