Bad Day
Today was a bad day at work. I didn't get much sleep because I was up late
finishing up the st driver patch, and then it was just radically hectic at
work. Blech.
Patch is done. I've submitted a note to Theo offering it. We'll see if
he bites. Here it is:
--- /usr/src/sys/scsi/t/st.c Sun Oct 20 16:24:21 2002
+++ /usr/src/sys/scsi/st.c Wed Oct 23 14:52:40 2002
@@ -1,4 +1,4 @@
-/* $OpenBSD: st.c,v 1.29 2001/06/22 14:35:43 deraadt Exp $ */
+/* $OpenBSD: st.c,v 1.29 2002/23/10 sallot Exp $ */
/* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */
/*
@@ -54,6 +54,12 @@
* to be depending on whether we expect to retension or not.
*/
+/*
+ * filenumber/block support added for fsf/bsf, open, close, write, read, and eom.
+ *
+ */
+
+
#include
#include
#include
@@ -81,6 +87,11 @@
#define STUNIT(z) ((minor(z) >> 4) )
#define CTLMODE 3
+#define NORMAL_MODE 0
+#define NOREW_MODE 1
+#define EJECT_MODE 2
+#define CTRL_MODE 3
+
#define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */
#define ST_CTL_TIME (30 * 1000) /* 30 seconds */
#define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */
@@ -107,6 +118,9 @@
#define ST_Q_IGNORE_LOADS 0x0004
#define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */
#define ST_Q_UNIMODAL 0x0010 /* unimode drive rejects mode select */
+#define ST_Q_NOPREVENT 0x0020 /* does not support PREVENT */
+#define ST_Q_ERASE_NOIMM 0x0040 /* drive rejects ERASE/w Immed bit */
+#define ST_Q_NOFILEMARKS 0x0080 /* can only write 0 filemarks */
u_int page_0_size;
#define MAX_PAGE_0_SIZE 64
struct modes modes[4];
@@ -259,6 +273,12 @@
u_int last_dsty; /* last density opened */
short mt_resid; /* last (short) resid */
short mt_erreg; /* last error (sense key) seen */
+ /* relative to beginning of tape */
+ daddr_t fileno; /* current file number */
+ daddr_t blkno;
+ int32_t last_io_resid;
+ int32_t last_ctl_resid;
+
/*--------------------device/scsi parameters----------------------------------*/
struct scsi_link *sc_link; /* our link to the adpter etc. */
/*--------------------parameters reported by the device ----------------------*/
@@ -340,11 +360,15 @@
#define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
#define ST_MOUNTED 0x0800 /* Device is presently mounted */
#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
+#define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
+
+#define ST_POSUPDATED 0x8000 /* tape position has been updated */
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
- ST_2FM_AT_EOD | ST_PER_ACTION)
+ ST_2FM_AT_EOD | ST_PER_ACTION | ST_EARLYWARN)
+#define ST_INIT_FLAGS ST_EARLYWARN
struct scsi_inquiry_pattern st_patterns[] = {
{T_SEQUENTIAL, T_REMOV,
@@ -388,6 +412,8 @@
sc_link->device_softc = st;
sc_link->openings = 1;
+ st->flags = ST_INIT_FLAGS;
+
/*
* Check if the drive is a known criminal and take
* Any steps needed to bring it into line
@@ -558,7 +584,8 @@
* mount session.
*/
if (!(st->flags & ST_MOUNTED)) {
- st_mount_tape(dev, flags);
+ if ((error = st_mount_tape(dev, flags)) !=0 )
+ goto bad;
st->last_dsty = dsty;
}
@@ -590,30 +617,80 @@
int mode;
struct proc *p;
{
+ int stxx, error=0;
struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
+ struct scsi_link *sclink = st->sc_link;
+
+
+ /*
+ * Make sure that a tape opened in write-only mode will have
+ * file marks written on it when closed, even if not written to.
+ *
+ * This is for SUN compatibility. Actually, the Sun way of
+ * things is to:
+ *
+ * only write filemarks if there are fmks to be written and
+ * - open for write (possibly read/write)
+ * - the last operation was a write
+ * or:
+ * - opened for wronly
+ * - no data was written (including filemarks)
+ */
+
+ stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN);
+ if (((flags & FWRITE) && stxx == ST_WRITTEN) ||
+ ((flags & O_ACCMODE) == FWRITE && stxx == 0)) {
+ int nm;
+ error = st_check_eod(st, FALSE, &nm, 0);
+ }
- SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n"));
- if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
- st_write_filemarks(st, 1, 0);
switch (STMODE(dev)) {
- case 0: /* normal */
+ case NORMAL_MODE:
st_unmount(st, NOEJECT, DOREWIND);
break;
- case 3: /* eject, no rewind */
- st_unmount(st, EJECT, NOREWIND);
- break;
- case 1: /* no rewind */
- /* leave mounted unless media seems to have been removed */
- if (!(st->sc_link->flags & SDEV_MEDIA_LOADED))
- st_unmount(st, NOEJECT, NOREWIND);
+ case NOREW_MODE:
+ case CTRL_MODE:
+ /*
+ * Leave mounted unless media seems to have been removed.
+ *
+ * Otherwise, if we're to terminate a tape with more than one
+ * filemark [ and because we're not rewinding here ], backspace
+ * one filemark so that later appends will see an unbroken
+ * sequence of:
+ *
+ * file - FMK - file - FMK ... file - FMK FMK (EOM)
+ */
+ if ((sclink->flags & SDEV_MEDIA_LOADED) == 0) {
+ st_unmount(st, NOEJECT,DOREWIND);
+ } else if (error == 0) {
+ /*
+ * ST_WRITTEN was preserved from above.
+ *
+ * All we need to know here is:
+ *
+ * Were we writing this tape and was the last
+ * operation a write?
+ *
+ * Are there supposed to be 2FM at EOD?
+ *
+ * If both statements are true, then we backspace
+ * one filemark.
+ */
+ stxx |= (st->flags & ST_2FM_AT_EOD);
+ if ((flags & FWRITE) != 0 &&
+ (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) {
+ error = st_space(st, -1, SP_FILEMARKS, 0);
+ }
+ }
break;
- case 2: /* rewind, eject */
- st_unmount(st, EJECT, DOREWIND);
+ case EJECT_MODE:
+ st_unmount(st, EJECT,DOREWIND);
break;
}
- st->sc_link->flags &= ~SDEV_OPEN;
- return 0;
+ sclink->flags &= ~SDEV_OPEN;
+
+ return (error);
}
/*
@@ -715,6 +792,7 @@
st->flags &= ~ST_NEW_MOUNT;
st->flags |= ST_MOUNTED;
sc_link->flags |= SDEV_MEDIA_LOADED; /* move earlier? */
+ st->blkno = st->fileno = (daddr_t) 0;
return 0;
}
@@ -741,8 +819,12 @@
st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
scsi_prevent(sc_link, PR_ALLOW,
SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
- if (eject)
+ if (eject) {
st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
+ st->blkno = st->fileno = (daddr_t) -1;
+ } else {
+ st->blkno = st->fileno = (daddr_t) 0;
+ }
st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
sc_link->flags &= ~SDEV_MEDIA_LOADED;
}
@@ -1065,6 +1147,8 @@
_lto3b(bp->b_bcount / st->blksize, cmd.len);
} else
_lto3b(bp->b_bcount, cmd.len);
+ /* clear position updated indicator */
+ st->flags &= ~ST_POSUPDATED;
/*
* go ask the adapter to do all this for us
@@ -1113,7 +1197,7 @@
struct proc *p;
{
int error = 0;
- int unit;
+ int unit,count;
int number, nmarks, dsty;
int flags;
struct st_softc *st;
@@ -1156,6 +1240,8 @@
g->mt_mdensity[1] = st->modes[1].density;
g->mt_mdensity[2] = st->modes[2].density;
g->mt_mdensity[3] = st->modes[3].density;
+ g->mt_fileno = st->fileno;
+ g->mt_blkno = st->blkno;
if (st->flags & ST_READONLY)
g->mt_dsreg |= MT_DS_RDONLY;
if (st->flags & ST_MOUNTED)
@@ -1183,11 +1269,11 @@
case MTBSF: /* backward space file */
number = -number;
case MTFSF: /* forward space file */
- error = st_check_eod(st, FALSE, &nmarks, flags);
- if (!error)
- error = st_space(st, number - nmarks,
- SP_FILEMARKS, flags);
- break;
+ error = st_check_eod(st, FALSE, &nmarks, flags);
+ if (!error)
+ error = st_space(st, number - nmarks,
+ SP_FILEMARKS, flags);
+ break;
case MTBSR: /* backward space record */
number = -number;
case MTFSR: /* forward space record */
@@ -1208,10 +1294,27 @@
if (!error)
error = st_load(st, LD_LOAD, flags);
break;
- case MTEOM: /* forward space to end of media */
- error = st_check_eod(st, FALSE, &nmarks, flags);
- if (!error)
- error = st_space(st, 1, SP_EOM, flags);
+ case MTEOM: /* rather than call SP_EOM and lose
+ * the file count, we'll just FSF once
+ * per file until we reach the end of the
+ * tape.
+ */
+ error=0;
+ count=0;
+ while ( (error==0) && (count<2000) ) {
+ /* do we think there'll be more than 2k filesets on a tape?? god I hope not */
+ error = st_check_eod(st, FALSE, &nmarks, flags);
+ if (!error)
+ error = st_space(st, 1, SP_FILEMARKS, flags);
+ count++;
+ }
+ if (error==EIO) /*
+ * good, we hit the end of the tape, BUT
+ * we don't want to produce an error output
+ * just for doing what we're supposed to..
+ *
+ */
+ error=0;
break;
case MTCACHE: /* enable controller cache */
st->flags &= ~ST_DONTBUFFER;
@@ -1575,7 +1678,7 @@
{
struct scsi_space cmd;
int error;
-
+
switch (what) {
case SP_BLKS:
if (st->flags & ST_PER_ACTION) {
@@ -1603,7 +1706,7 @@
}
break;
case SP_FILEMARKS:
- if (st->flags & ST_EIO_PENDING) {
+ if (st->flags & ST_EIO_PENDING) { /* check scsi_base */
if (number > 0) {
/* pretend we just discovered the error */
st->flags &= ~ST_EIO_PENDING;
@@ -1641,8 +1744,47 @@
cmd.byte2 = what;
_lto3b(number, cmd.number);
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ st->flags &= ~ST_POSUPDATED;
+ st->last_ctl_resid = 0;
+
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, 0, ST_SPC_TIME, NULL, flags);
+
+ if ( (error == 0) || ((error==EIO) && (number<0)) ) {
+ /* requests still in command queue */
+ if (number>0) { /* we're counting forward */
+ number = number - st->last_ctl_resid;
+ } else if (number<0) { /* we're counting down sir! */
+ number = number + st->last_ctl_resid;
+ }
+ if (what == SP_BLKS) {
+ if (st->blkno != -1) {
+ st->blkno += number;
+ }
+ } else if (what == SP_FILEMARKS) { /* was != -1 */
+ if (st->fileno > -1) {
+ st->fileno += number;
+ if (number > 0) {
+ st->blkno = 0;
+ } else if (number < 0) {
+ st->blkno = -1;
+ }
+ }
+ } else if (what == SP_EOM) {
+ /*
+ * This loses us relative position.
+ * But, we should never be here.
+ */
+ st->fileno = st->blkno = -1;
+ }
+ if (st->flags & ST_POSUPDATED) { /* if we're here, there's an error. most likely end of tape data */
+ error=EIO;
+ }
+
+ }
+
+ return (error);
+
}
/*
@@ -1654,6 +1796,7 @@
int flags;
int number;
{
+ int error;
struct scsi_write_filemarks cmd;
/*
@@ -1680,8 +1823,13 @@
cmd.opcode = WRITE_FILEMARKS;
_lto3b(number, cmd.number);
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
+ if (error == 0 && st->fileno != -1) {
+ st->fileno += number;
+ }
+ return (error);
+
}
/*
@@ -1778,9 +1926,20 @@
cmd.opcode = REWIND;
cmd.byte2 = immediate;
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, ST_RETRIES,
immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
+ if (error) {
+ printf("%s: error %d trying to rewind\n",
+ st->sc_dev.dv_xname, error);
+ /* lost position */
+ st->fileno = st->blkno = -1;
+ } else {
+ st->fileno = st->blkno = 0;
+ }
+ return (error);
+
+
}
/*
@@ -1806,19 +1965,39 @@
info = _4btol(sense->info);
else
info = xs->datalen; /* bad choice if fixed blocks */
- if ((sense->error_code & SSD_ERRCODE) != 0x70)
- return SCSIRET_CONTINUE; /* let the generic code handle it */
+
+ if ((sense->error_code & SSD_ERRCODE) != 0x70) {
+
+ return SCSIRET_CONTINUE; /* let the generic code handle it */
+ }
+
+ xs->resid = info;
+
if (st->flags & ST_FIXEDBLOCKS) {
- xs->resid = info * st->blksize;
+ if (bp) {
+ xs->resid *= st->blksize;
+ st->last_io_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
+ }
+
if (sense->flags & SSD_EOM) {
- st->flags |= ST_EIO_PENDING;
- if (bp)
+ st->flags |= ST_EIO_PENDING;
+ if (bp) {
bp->b_resid = xs->resid;
+ st->last_io_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
+ }
}
if (sense->flags & SSD_FILEMARK) {
st->flags |= ST_AT_FILEMARK;
- if (bp)
+ if (bp) {
bp->b_resid = xs->resid;
+ st->last_io_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
+ }
}
if (sense->flags & SSD_ILI) {
st->flags |= ST_EIO_PENDING;
@@ -1840,6 +2019,19 @@
!(sc_link->flags & SDEV_MEDIA_LOADED))
st->blksize -= 512;
}
+ if (sense->flags & SSD_EOM) {
+ st->flags |= ST_EIO_PENDING;
+ if (bp) {
+ /*
+ * Grotesque as it seems, the few times
+ * I've actually seen a non-zero resid,
+ * the tape drive actually lied and had
+ * written all the data!
+ */
+
+ bp->b_resid = 0;
+ }
+ }
/*
* If no data was tranfered, do it immediatly
*/
@@ -1853,20 +2045,36 @@
}
}
} else { /* must be variable mode */
- xs->resid = xs->datalen; /* to be sure */
- if (sense->flags & SSD_EOM)
+
+ if (bp) {
+ st->last_io_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
+ }
+
+ if (sense->flags & SSD_EOM) {
return EIO;
+ }
+
+ /* xs->resid = xs->datalen; */ /* to be sure we've lost our mind.. */
+
if (sense->flags & SSD_FILEMARK) {
if (bp)
bp->b_resid = bp->b_bcount;
+ if (st->fileno != (daddr_t) -1) {
+ st->fileno++;
+ st->blkno=0;
+ st->flags |= ST_POSUPDATED;
+ }
return 0;
}
+
if (sense->flags & SSD_ILI) {
if (info < 0) {
/*
* the record was bigger than the read
*/
- if ((xs->flags & SCSI_SILENT) == 0)
+ if ((xs->flags & SCSI_SILENT) == 0)
printf("%s: %d-byte record too big\n",
st->sc_dev.dv_xname,
xs->datalen - info);
@@ -1882,8 +2090,15 @@
xs->datalen);
return (EIO);
}
+ } else {
+ if (st->blkno != (daddr_t) -1) {
+ st->blkno++;
+ st->flags |= ST_POSUPDATED;
+ }
}
- xs->resid = info;
+ /* let's go ahead and corrupt the results why don't we?? */
+ /* xs->resid=info; */
+
if (bp)
bp->b_resid = info;
return 0;
@@ -1892,6 +2107,7 @@
key = sense->flags & SSD_KEY;
if (key == 0x8) {
+ printf("key = 0x8\n");
/*
* This quirk code helps the drive read the
* first tape block, regardless of format. That
@@ -1905,13 +2121,28 @@
} else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
st->flags |= ST_BLANK_READ;
xs->resid = xs->datalen;
+ if (st->blkno != (daddr_t) -1) {
+ if (st->blksize>0) {
+ st->blkno += (xs->datalen / st->blksize);
+ st->flags |= ST_POSUPDATED;
+ }
+ }
if (bp) {
bp->b_resid = xs->resid;
/* return an EOF */
}
+ /* lost position */
+ st->fileno = st->blkno = -1;
return 0;
}
}
+
+ /* trap this before it gets ugly. */
+ if (sense->error_code & SSD_EOM) {
+ st->flags &= ~ST_EIO_PENDING;
+ st->flags |= ST_POSUPDATED;
+ }
+
return SCSIRET_CONTINUE;
}
@@ -1981,3 +2212,4 @@
/* Not implemented. */
return ENXIO;
}
+
Well, Jim Greenlee's in town. I'm supposed to grab dinner with him, so I
better call it a night..
Posted at: 22:49 on 23/10/2002
[ / ]
#
Mon, 21 Oct 2002
She sells C Shells by the C Shore
So, I dropped the scsi card into urchin a few days ago. Dropped the
tape drive on it. Thought I had backups working perfectly. I was wrong...
The openbsd mt utility doesn't return an error code when you reach the end of
the tape. Whoops.
Also, the OpenBSD scsi-tape driver does not implement file number counting
and block counting. Personally, I don't care about block counting, but I
do really want file counting..
So, I've spent some time hacking on the openbsd scsi tape driver today.
The hacking is slow because it requires a recompile of the kernel for any
change, ugh. I'm integrating the file number code from the netbsd scsi-tape
driver and putting in the openbsd scsi tape driver. It's still VERY beta,
but I have a preliminary version working (mt fsf correctly counts numbers
until you hit eom).
If you care, here's the current patches. The first patch is for the
mt utility to provide displaying of the file number. The second is for
the 3.0_stable kernel st driver. It's funny, it looks like back in 1997
someone thought about adding this support since the "mt_fileno" construct
was added to the scsi tape driver..
I'll continue working on them until I'm happy with the change, then I'll
go ahead and submit the patches to theo and company..
Patch for the mt utility
--- /usr/src/bin/mt/t/mt.c Sun Oct 20 16:59:04 2002
+++ /usr/src/bin/mt/mt.c Sun Oct 20 17:01:35 2002
@@ -261,6 +261,7 @@
printreg("ds", bp->mt_dsreg, mt->t_dsbits);
printreg("\ner", bp->mt_erreg, mt->t_erbits);
(void)putchar('\n');
+ (void)printf("file number=%d\n",bp->mt_fileno);
(void)printf("blocksize: %d (%d, %d, %d, %d)\n",
bp->mt_blksiz, bp->mt_mblksiz[0], bp->mt_mblksiz[1],
bp->mt_mblksiz[2], bp->mt_mblksiz[3]);
Patch for the OpenBSD 3.0_stable scsi-tape kernel driver
--- /usr/src/sys/scsi/t/st.c Sun Oct 20 16:24:21 2002
+++ /usr/src/sys/scsi/st.c Sun Oct 20 19:34:44 2002
@@ -1,3 +1,6 @@
+/* to still do -- fsf rewinding past eom switches fileno to a negative
+ #.. Should be in the st_space function */
+
/* $OpenBSD: st.c,v 1.29 2001/06/22 14:35:43 deraadt Exp $ */
/* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */
@@ -259,6 +262,12 @@
u_int last_dsty; /* last density opened */
short mt_resid; /* last (short) resid */
short mt_erreg; /* last error (sense key) seen */
+ /* relative to beginning of tape */
+ daddr_t fileno; /* current file number */
+ daddr_t blkno;
+ int32_t last_io_resid;
+ int32_t last_ctl_resid;
+
/*--------------------device/scsi parameters----------------------------------*/
struct scsi_link *sc_link; /* our link to the adpter etc. */
/*--------------------parameters reported by the device ----------------------*/
@@ -340,6 +349,7 @@
#define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
#define ST_MOUNTED 0x0800 /* Device is presently mounted */
#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
+#define ST_POSUPDATED 0x8000 /* tape position has been updated */
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
@@ -715,6 +725,7 @@
st->flags &= ~ST_NEW_MOUNT;
st->flags |= ST_MOUNTED;
sc_link->flags |= SDEV_MEDIA_LOADED; /* move earlier? */
+ st->blkno = st->fileno = (daddr_t) 0;
return 0;
}
@@ -741,8 +752,12 @@
st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
scsi_prevent(sc_link, PR_ALLOW,
SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
- if (eject)
+ if (eject) {
st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
+ st->blkno = st->fileno = (daddr_t) -1;
+ } else {
+ st->blkno = st->fileno = (daddr_t) 0;
+ }
st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
sc_link->flags &= ~SDEV_MEDIA_LOADED;
}
@@ -1065,6 +1080,8 @@
_lto3b(bp->b_bcount / st->blksize, cmd.len);
} else
_lto3b(bp->b_bcount, cmd.len);
+ /* clear position updated indicator */
+ st->flags &= ~ST_POSUPDATED;
/*
* go ask the adapter to do all this for us
@@ -1156,6 +1173,8 @@
g->mt_mdensity[1] = st->modes[1].density;
g->mt_mdensity[2] = st->modes[2].density;
g->mt_mdensity[3] = st->modes[3].density;
+ g->mt_fileno = st->fileno;
+ g->mt_blkno = st->blkno;
if (st->flags & ST_READONLY)
g->mt_dsreg |= MT_DS_RDONLY;
if (st->flags & ST_MOUNTED)
@@ -1641,8 +1660,37 @@
cmd.byte2 = what;
_lto3b(number, cmd.number);
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ st->flags &= ~ST_POSUPDATED;
+ st->last_ctl_resid = 0;
+
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, 0, ST_SPC_TIME, NULL, flags);
+
+ if (error == 0 && (st->flags & ST_POSUPDATED) == 0) {
+ number = number - st->last_ctl_resid;
+ if (what == SP_BLKS) {
+ if (st->blkno != -1) {
+ st->blkno += number;
+ }
+ } else if (what == SP_FILEMARKS) {
+ if (st->fileno != -1) {
+ if (number > 0) {
+ /* ks */
+ st->fileno += number;
+ st->blkno = 0;
+ } else if (number < 0) {
+ st->blkno = -1;
+ }
+ }
+ } else if (what == SP_EOM) {
+ /*
+ * This loses us relative position.
+ */
+ st->fileno = st->blkno = -1;
+ }
+ }
+ return (error);
+
}
/*
@@ -1654,6 +1702,7 @@
int flags;
int number;
{
+ int error;
struct scsi_write_filemarks cmd;
/*
@@ -1680,8 +1729,13 @@
cmd.opcode = WRITE_FILEMARKS;
_lto3b(number, cmd.number);
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
+ if (error == 0 && st->fileno != -1) {
+ st->fileno += number;
+ }
+ return (error);
+
}
/*
@@ -1778,9 +1832,20 @@
cmd.opcode = REWIND;
cmd.byte2 = immediate;
- return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+ error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
sizeof(cmd), 0, 0, ST_RETRIES,
immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
+ if (error) {
+ printf("%s: error %d trying to rewind\n",
+ st->sc_dev.dv_xname, error);
+ /* lost position */
+ st->fileno = st->blkno = -1;
+ } else {
+ st->fileno = st->blkno = 0;
+ }
+ return (error);
+
+
}
/*
@@ -1810,15 +1875,23 @@
return SCSIRET_CONTINUE; /* let the generic code handle it */
if (st->flags & ST_FIXEDBLOCKS) {
xs->resid = info * st->blksize;
+ st->last_io_resid = xs->resid;
if (sense->flags & SSD_EOM) {
st->flags |= ST_EIO_PENDING;
if (bp)
bp->b_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
}
if (sense->flags & SSD_FILEMARK) {
st->flags |= ST_AT_FILEMARK;
if (bp)
bp->b_resid = xs->resid;
+ if (st->fileno != (daddr_t) -1) {
+ st->fileno++;
+ st->blkno=0;
+ st->flags |= ST_POSUPDATED;
+ }
}
if (sense->flags & SSD_ILI) {
st->flags |= ST_EIO_PENDING;
@@ -1853,10 +1926,20 @@
}
}
} else { /* must be variable mode */
+ if (bp) {
+ st->last_io_resid = xs->resid;
+ } else {
+ st->last_ctl_resid = xs->resid;
+ }
xs->resid = xs->datalen; /* to be sure */
if (sense->flags & SSD_EOM)
return EIO;
if (sense->flags & SSD_FILEMARK) {
+ if (st->fileno != (daddr_t) -1) {
+ st->fileno++;
+ st->blkno=0;
+ st->flags |= ST_POSUPDATED;
+ }
if (bp)
bp->b_resid = bp->b_bcount;
return 0;
@@ -1909,6 +1992,8 @@
bp->b_resid = xs->resid;
/* return an EOF */
}
+ /* lost position */
+ st->fileno = st->blkno = (daddr_t) -1;
return 0;
}
}
Posted at: 00:51 on 21/10/2002
[ / ]
#