summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2001-01-16 00:53:45 +0000
committermjacob <mjacob@FreeBSD.org>2001-01-16 00:53:45 +0000
commit437df10fdc957adbcfb372d6fc7638929d3df25e (patch)
tree5bc4f02e7be182fb42ea4ae030feac8c2f8b4a8b /sys/cam
parent7919bbf81bd80fa98115daa1298164135ea3c4eb (diff)
downloadFreeBSD-src-437df10fdc957adbcfb372d6fc7638929d3df25e.zip
FreeBSD-src-437df10fdc957adbcfb372d6fc7638929d3df25e.tar.gz
Use the residual from a spacing operation to try and figure out where
we *really* are. It should be noted that there is a degenerate case where soft tape location will be lost (not causing a frozen state- but causing the loss of reporting fileno/blockno)- that's where you backspace over a filemark- you stop backspacing as soon as you cross the filemark, but you have no idea what the record number now is because you have no idea how many records you are into the file you just backed into. Such is life. While I'm at it, also pick up residuals from writing filemarks. PR: 24222
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_sa.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index 226ab99..785f0f7 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -2984,6 +2984,11 @@ saspace(struct cam_periph *periph, int count, scsi_space_code code)
scsi_space(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, code, count,
SSD_FULL_SIZE, SPACE_TIMEOUT);
+ /*
+ * Clear residual because we will be using it.
+ */
+ softc->last_ctl_resid = 0;
+
softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD;
error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
softc->dsreg = MTIO_DSREG_REST;
@@ -3000,17 +3005,38 @@ saspace(struct cam_periph *periph, int count, scsi_space_code code)
* If the spacing operation was setmarks or to end of recorded data,
* we no longer know our relative position.
*
- * We are not managing residuals here (really).
+ * If the spacing operations was spacing files in reverse, we
+ * take account of the residual, but still check against less
+ * than zero- if we've gone negative, we must have hit BOT.
+ *
+ * If the spacing operations was spacing records in reverse and
+ * we have a residual, we've either hit BOT or hit a filemark.
+ * In the former case, we know our new record number (0). In
+ * the latter case, we have absolutely no idea what the real
+ * record number is- we've stopped between the end of the last
+ * record in the previous file and the filemark that stopped
+ * our spacing backwards.
*/
if (error) {
softc->fileno = softc->blkno = (daddr_t) -1;
} else if (code == SS_SETMARKS || code == SS_EOD) {
softc->fileno = softc->blkno = (daddr_t) -1;
} else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) {
- softc->fileno += count;
+ softc->fileno += (count - softc->last_ctl_resid);
+ if (softc->fileno < 0) /* we must of hit BOT */
+ softc->fileno = 0;
softc->blkno = 0;
} else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) {
- softc->blkno += count;
+ softc->blkno += (count - softc->last_ctl_resid);
+ if (count < 0) {
+ if (softc->last_ctl_resid || softc->blkno < 0) {
+ if (softc->fileno == 0) {
+ softc->blkno = 0;
+ } else {
+ softc->blkno = (daddr_t) -1;
+ }
+ }
+ }
}
return (error);
}
@@ -3020,11 +3046,15 @@ sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks)
{
union ccb *ccb;
struct sa_softc *softc;
- int error;
+ int error, nwm = 0;
softc = (struct sa_softc *)periph->softc;
ccb = cam_periph_getccb(periph, 1);
+ /*
+ * Clear residual because we will be using it.
+ */
+ softc->last_ctl_resid = 0;
softc->dsreg = MTIO_DSREG_FMK;
/* this *must* not be retried */
@@ -3038,14 +3068,12 @@ sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks)
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
- /*
- * XXXX: Get back the actual number of filemarks written
- * XXXX: (there can be a residual).
- */
if (error == 0 && nmarks) {
struct sa_softc *softc = (struct sa_softc *)periph->softc;
- softc->filemarks += nmarks;
+ nwm = nmarks - softc->last_ctl_resid;
+ softc->filemarks += nwm;
}
+
xpt_release_ccb(ccb);
/*
@@ -3054,7 +3082,7 @@ sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks)
if (error) {
softc->fileno = softc->blkno = (daddr_t) -1;
} else if (softc->fileno != (daddr_t) -1) {
- softc->fileno += nmarks;
+ softc->fileno += nwm;
softc->blkno = 0;
}
return (error);
OpenPOWER on IntegriCloud