From e93e63cb392cb4f63235265bd3cdd5e49a41bbc7 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Fri, 15 Jan 1999 09:15:27 +0000 Subject: [PATCH] Fixed corruption of the fd buffer queue. Once upon a time, the active buffer had to be left on the head of the queue for [bufq]disksort() to sort against. This isn't right for devices that can support multiple active i/o's, and only the fd driver did it. "Fixing" this in rev.1.36 of ufs_disksubr.c broke the fd driver in much the same way as rev.1.52 of broke it (see rev.1.119). Bug reported and fix tested by: dt --- sys/dev/fdc/fdc.c | 19 +++++++++++++------ sys/i386/isa/fd.c | 19 +++++++++++++------ sys/i386/isa/fdc.h | 5 +++-- sys/isa/fd.c | 19 +++++++++++++------ sys/isa/fdc.h | 5 +++-- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 5380d54151d4..c8e35a5ae07d 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.129 1998/12/14 16:29:58 bde Exp $ + * $Id: fd.c,v 1.130 1998/12/27 13:40:56 phk Exp $ * */ @@ -1530,8 +1530,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) struct fd_formb *finfo = NULL; size_t fdblk; - bp = bufq_first(&fdc->head); - if(!bp) { + bp = fdc->bp; + if (bp == NULL) { + bp = bufq_first(&fdc->head); + if (bp != NULL) { + bufq_remove(&fdc->head, bp); + fdc->bp = bp; + } + } + if (bp == NULL) { /***********************************************\ * nothing left for this controller to do * * Force into the IDLE state, * @@ -1903,7 +1910,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { /* ALL DONE */ fd->skip = 0; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fd->device_stats, bp->b_bcount - bp->b_resid, @@ -2026,7 +2033,7 @@ retrier(fdcu) fdc_p fdc = fdc_data + fdcu; register struct buf *bp; - bp = bufq_first(&fdc->head); + bp = fdc->bp; if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) goto fail; @@ -2070,7 +2077,7 @@ retrier(fdcu) bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid += bp->b_bcount - fdc->fd->skip; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fdc->fd->device_stats, diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index 5380d54151d4..c8e35a5ae07d 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.129 1998/12/14 16:29:58 bde Exp $ + * $Id: fd.c,v 1.130 1998/12/27 13:40:56 phk Exp $ * */ @@ -1530,8 +1530,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) struct fd_formb *finfo = NULL; size_t fdblk; - bp = bufq_first(&fdc->head); - if(!bp) { + bp = fdc->bp; + if (bp == NULL) { + bp = bufq_first(&fdc->head); + if (bp != NULL) { + bufq_remove(&fdc->head, bp); + fdc->bp = bp; + } + } + if (bp == NULL) { /***********************************************\ * nothing left for this controller to do * * Force into the IDLE state, * @@ -1903,7 +1910,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { /* ALL DONE */ fd->skip = 0; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fd->device_stats, bp->b_bcount - bp->b_resid, @@ -2026,7 +2033,7 @@ retrier(fdcu) fdc_p fdc = fdc_data + fdcu; register struct buf *bp; - bp = bufq_first(&fdc->head); + bp = fdc->bp; if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) goto fail; @@ -2070,7 +2077,7 @@ retrier(fdcu) bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid += bp->b_bcount - fdc->fd->skip; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fdc->fd->device_stats, diff --git a/sys/i386/isa/fdc.h b/sys/i386/isa/fdc.h index c8c275f78cc6..43bf9f8f5f4c 100644 --- a/sys/i386/isa/fdc.h +++ b/sys/i386/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.11 1998/07/29 13:00:42 bde Exp $ + * $Id: fdc.h,v 1.12 1998/12/12 08:16:01 imp Exp $ * */ @@ -68,7 +68,8 @@ struct fdc_data u_int status[7]; /* copy of the registers */ enum fdc_type fdct; /* chip version of FDC */ int fdc_errs; /* number of logged errors */ - struct buf_queue_head head; /* Head of buf chain */ + struct buf_queue_head head; + struct buf *bp; /* active buffer */ }; /***********************************************************************\ diff --git a/sys/isa/fd.c b/sys/isa/fd.c index 5380d54151d4..c8e35a5ae07d 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.129 1998/12/14 16:29:58 bde Exp $ + * $Id: fd.c,v 1.130 1998/12/27 13:40:56 phk Exp $ * */ @@ -1530,8 +1530,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) struct fd_formb *finfo = NULL; size_t fdblk; - bp = bufq_first(&fdc->head); - if(!bp) { + bp = fdc->bp; + if (bp == NULL) { + bp = bufq_first(&fdc->head); + if (bp != NULL) { + bufq_remove(&fdc->head, bp); + fdc->bp = bp; + } + } + if (bp == NULL) { /***********************************************\ * nothing left for this controller to do * * Force into the IDLE state, * @@ -1903,7 +1910,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { /* ALL DONE */ fd->skip = 0; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fd->device_stats, bp->b_bcount - bp->b_resid, @@ -2026,7 +2033,7 @@ retrier(fdcu) fdc_p fdc = fdc_data + fdcu; register struct buf *bp; - bp = bufq_first(&fdc->head); + bp = fdc->bp; if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) goto fail; @@ -2070,7 +2077,7 @@ retrier(fdcu) bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid += bp->b_bcount - fdc->fd->skip; - bufq_remove(&fdc->head, bp); + fdc->bp = NULL; /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fdc->fd->device_stats, diff --git a/sys/isa/fdc.h b/sys/isa/fdc.h index c8c275f78cc6..43bf9f8f5f4c 100644 --- a/sys/isa/fdc.h +++ b/sys/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.11 1998/07/29 13:00:42 bde Exp $ + * $Id: fdc.h,v 1.12 1998/12/12 08:16:01 imp Exp $ * */ @@ -68,7 +68,8 @@ struct fdc_data u_int status[7]; /* copy of the registers */ enum fdc_type fdct; /* chip version of FDC */ int fdc_errs; /* number of logged errors */ - struct buf_queue_head head; /* Head of buf chain */ + struct buf_queue_head head; + struct buf *bp; /* active buffer */ }; /***********************************************************************\