summaryrefslogtreecommitdiff
path: root/sys/scsi/st.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2007-01-20 18:21:52 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2007-01-20 18:21:52 +0000
commit19ae454459cc23e3ed40f12506ad079bd3f6870e (patch)
tree9176e5131984098baabf523be2f365fa09800026 /sys/scsi/st.c
parentc73cd37b0087c92a9e0b2d0a2c0bbe10f75ff916 (diff)
Add media_fileno, media_blkno into st_softc and report their values
back via MTIOCGET ioctl, rather than always reporting -1 (unknown). Simple 'Set to 0 on rewind, increment on file marks and positioning, and set back to -1 on any ambiguity' logic. No functional impact on current operation. Should allow things like Bacula to work much faster by keeping track of the current media position. Adapted from FreeBSD code. ok beck@
Diffstat (limited to 'sys/scsi/st.c')
-rw-r--r--sys/scsi/st.c85
1 files changed, 79 insertions, 6 deletions
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
index 99bba3b8438..beaa67b7d6f 100644
--- a/sys/scsi/st.c
+++ b/sys/scsi/st.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: st.c,v 1.71 2007/01/05 00:42:47 krw Exp $ */
+/* $OpenBSD: st.c,v 1.72 2007/01/20 18:21:51 krw Exp $ */
/* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */
/*
@@ -204,6 +204,8 @@ struct st_softc {
u_int64_t numblks; /* nominal blocks capacity */
u_int32_t media_blksize; /* 0 if not ST_FIXEDBLOCKS */
u_int32_t media_density; /* this is what it said when asked */
+ daddr_t media_fileno; /* relative to BOT. -1 means unknown. */
+ daddr_t media_blkno; /* relative to BOF. -1 means unknown. */
/*--------------------quirks for the whole drive------------------------------*/
u_int drive_quirks; /* quirks of this drive */
/*--------------------How we should set up when opening each minor device----*/
@@ -335,6 +337,10 @@ stattach(parent, self, aux)
st->buf_queue.b_actf = 0;
st->buf_queue.b_actb = &st->buf_queue.b_actf;
+ /* Start up with media position unknown. */
+ st->media_fileno = -1;
+ st->media_blkno = -1;
+
/*
* Reset the media loaded flag, sometimes the data
* acquired at boot time is not quite accurate. This
@@ -624,6 +630,9 @@ st_unmount(st, eject, rewind)
struct scsi_link *sc_link = st->sc_link;
int nmarks;
+ st->media_fileno = -1;
+ st->media_blkno = -1;
+
if (!(st->flags & ST_MOUNTED))
return;
SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
@@ -961,6 +970,14 @@ ststart(v)
} else
_lto3b(bp->b_bcount, cmd.len);
+ if (st->media_blkno != -1) {
+ /* Update block count now, errors will set it to -1. */
+ if (st->flags & ST_FIXEDBLOCKS)
+ st->media_blkno += _3btol(cmd.len);
+ else if (cmd.len != 0)
+ st->media_blkno++;
+ }
+
/*
* go ask the adapter to do all this for us
*/
@@ -1076,8 +1093,8 @@ stioctl(dev, cmd, arg, flag, p)
g->mt_dsreg |= MT_DS_MOUNTED;
g->mt_resid = st->mt_resid;
g->mt_erreg = st->mt_erreg;
- g->mt_fileno = -1; /* -1 means we don't know */
- g->mt_blkno = -1; /* -1 means we don't know */
+ g->mt_fileno = st->media_fileno;
+ g->mt_blkno = st->media_blkno;
/*
* clear latched errors.
*/
@@ -1592,8 +1609,35 @@ st_space(st, number, what, flags)
cmd.byte2 = what;
_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_SPC_TIME, NULL, flags);
+
+ if (error != 0) {
+ st->media_fileno = (daddr_t) -1;
+ st->media_blkno = (daddr_t) -1;
+ } else {
+ switch (what) {
+ case SP_BLKS:
+ if (st->media_blkno != -1) {
+ st->media_blkno += number;
+ if (st->media_blkno < 0)
+ st->media_blkno = -1;
+ }
+ break;
+ case SP_FILEMARKS:
+ if (st->media_fileno != -1) {
+ st->media_fileno += number;
+ st->media_blkno = 0;
+ }
+ break;
+ default:
+ st->media_fileno = -1;
+ st->media_blkno = -1;
+ break;
+ }
+ }
+
+ return (error);
}
/*
@@ -1606,6 +1650,7 @@ st_write_filemarks(st, number, flags)
daddr_t number;
{
struct scsi_write_filemarks cmd;
+ int error;
/*
* It's hard to write a negative number of file marks.
@@ -1631,8 +1676,18 @@ st_write_filemarks(st, number, flags)
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->media_fileno = -1;
+ st->media_blkno = -1;
+ } else if (st->media_fileno != -1) {
+ st->media_fileno += number;
+ st->media_blkno = 0;
+ }
+
+ return (error);
}
/*
@@ -1680,6 +1735,9 @@ st_load(st, type, flags)
{
struct scsi_load cmd;
+ st->media_fileno = -1;
+ st->media_blkno = -1;
+
if (type != LD_LOAD) {
int error;
int nmarks;
@@ -1729,9 +1787,16 @@ st_rewind(st, immediate, flags)
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 == 0) {
+ st->media_fileno = 0;
+ st->media_blkno = 0;
+ }
+
+ return (error);
}
/*
@@ -1808,6 +1873,10 @@ st_interpret_sense(xs)
}
if (sense->flags & SSD_FILEMARK) {
st->flags |= ST_AT_FILEMARK;
+ if (st->media_fileno != -1) {
+ st->media_fileno++;
+ st->media_blkno = 0;
+ }
if (bp)
bp->b_resid = xs->resid;
}
@@ -1848,6 +1917,10 @@ st_interpret_sense(xs)
if (sense->flags & SSD_EOM)
return EIO;
if (sense->flags & SSD_FILEMARK) {
+ if (st->media_fileno != -1) {
+ st->media_fileno++;
+ st->media_blkno = 0;
+ }
if (bp)
bp->b_resid = bp->b_bcount;
return 0;