diff options
author | mjacob <mjacob@FreeBSD.org> | 2001-01-16 00:53:45 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2001-01-16 00:53:45 +0000 |
commit | 437df10fdc957adbcfb372d6fc7638929d3df25e (patch) | |
tree | 5bc4f02e7be182fb42ea4ae030feac8c2f8b4a8b /sys/cam/scsi | |
parent | 7919bbf81bd80fa98115daa1298164135ea3c4eb (diff) | |
download | FreeBSD-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/scsi')
-rw-r--r-- | sys/cam/scsi/scsi_sa.c | 48 |
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); |