Convert tqdisksort to bufqdisksort. Honor the B_ORDERED buffer flag
so that meta-data writes go out to the device in the right order.
This commit is contained in:
parent
f935b9668d
commit
df1f24e6bb
@ -36,7 +36,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
|
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
|
||||||
* $Id: ufs_disksubr.c,v 1.30 1997/02/22 09:47:45 peter Exp $
|
* $Id: ufs_disksubr.c,v 1.31 1997/07/13 15:53:20 bde Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -50,109 +50,88 @@
|
|||||||
/*
|
/*
|
||||||
* Seek sort for disks.
|
* Seek sort for disks.
|
||||||
*
|
*
|
||||||
* The argument ap structure holds a b_actf activity chain pointer on which we
|
* The buf_queue keep two queues, sorted in ascending block order. The first
|
||||||
* keep two queues, sorted in ascending block order. The first queue holds
|
* queue holds those requests which are positioned after the current block
|
||||||
* those requests which are positioned after the current block (in the first
|
* (in the first request); the second, which starts at queue->switch_point,
|
||||||
* request); the second holds requests which came in after their block number
|
* holds requests which came in after their block number was passed. Thus
|
||||||
* was passed. Thus we implement a one way scan, retracting after reaching the
|
* we implement a one way scan, retracting after reaching the end of the drive
|
||||||
* end of the drive to the first request on the second queue, at which time it
|
* to the first request on the second queue, at which time it becomes the
|
||||||
* becomes the first queue.
|
* first queue.
|
||||||
*
|
*
|
||||||
* A one-way scan is natural because of the way UNIX read-ahead blocks are
|
* A one-way scan is natural because of the way UNIX read-ahead blocks are
|
||||||
* allocated.
|
* allocated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tqdisksort(ap, bp)
|
bufqdisksort(bufq, bp)
|
||||||
struct buf_queue_head *ap;
|
struct buf_queue_head *bufq;
|
||||||
register struct buf *bp;
|
struct buf *bp;
|
||||||
{
|
{
|
||||||
register struct buf *bq;
|
struct buf *bq;
|
||||||
struct buf *bn;
|
struct buf *bn;
|
||||||
|
int count;
|
||||||
|
|
||||||
/* If the queue is empty, then it's easy. */
|
/*
|
||||||
if ((bq = ap->tqh_first) == NULL) {
|
* If the queue is empty or we are an
|
||||||
TAILQ_INSERT_HEAD(ap, bp, b_act);
|
* ordered transaction, then it's easy.
|
||||||
|
*/
|
||||||
|
if ((bq = bufq_first(bufq)) == NULL
|
||||||
|
|| (bp->b_flags & B_ORDERED) != 0) {
|
||||||
|
bufq_insert_tail(bufq, bp);
|
||||||
|
return;
|
||||||
|
} else if (bufq->insert_point != NULL) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A certain portion of the list is
|
||||||
|
* "locked" to preserve ordering, so
|
||||||
|
* we can only insert after the insert
|
||||||
|
* point.
|
||||||
|
*/
|
||||||
|
bq = TAILQ_NEXT(bufq->insert_point, b_act);
|
||||||
|
if (bq == NULL) {
|
||||||
|
bufq_insert_tail(bufq, bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Put new writes after all reads */
|
|
||||||
if ((bp->b_flags & B_READ) == 0) {
|
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
if ((bq->b_flags & B_READ) == 0)
|
|
||||||
break;
|
|
||||||
bq = bn;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
if ((bq->b_flags & B_READ) == 0) {
|
|
||||||
if (ap->tqh_first != bq) {
|
|
||||||
bq = *bq->b_act.tqe_prev;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bq = bn;
|
|
||||||
}
|
|
||||||
goto insert;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we lie after the first (currently active) request, then we
|
* If we lie before the first (currently active) request, then we
|
||||||
* must locate the second request list and add ourselves to it.
|
* must add ourselves to the second request list.
|
||||||
*/
|
*/
|
||||||
if (bp->b_pblkno < bq->b_pblkno) {
|
if (bp->b_pblkno < bq->b_pblkno) {
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
|
bq = bufq->switch_point;
|
||||||
/*
|
/*
|
||||||
* Check for an ``inversion'' in the normally ascending
|
* If we are starting a new secondary list, then it's easy.
|
||||||
* cylinder numbers, indicating the start of the second
|
|
||||||
* request list.
|
|
||||||
*/
|
*/
|
||||||
if (bn->b_pblkno < bq->b_pblkno) {
|
if (bq == NULL) {
|
||||||
/*
|
bufq->switch_point = bp;
|
||||||
* Search the second request list for the first
|
bufq_insert_tail(bufq, bp);
|
||||||
* request at a larger cylinder number. We go
|
return;
|
||||||
* before that; if there is no such request, we
|
|
||||||
* go at end.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
if (bp->b_pblkno < bn->b_pblkno)
|
|
||||||
goto insert;
|
|
||||||
bq = bn;
|
|
||||||
} while (bn = bq->b_act.tqe_next);
|
|
||||||
goto insert; /* after last */
|
|
||||||
}
|
}
|
||||||
bq = bn;
|
if (bp->b_pblkno < bq->b_pblkno) {
|
||||||
|
bufq->switch_point = bp;
|
||||||
|
TAILQ_INSERT_BEFORE(bq, bp, b_act);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* No inversions... we will go after the last, and
|
|
||||||
* be the first request in the second request list.
|
|
||||||
*/
|
|
||||||
goto insert;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Request is at/after the current request...
|
* Request is at/after the current request...
|
||||||
* sort in the first request list.
|
* sort in the first request list.
|
||||||
*/
|
*/
|
||||||
while (bn = bq->b_act.tqe_next) {
|
while ((bn = TAILQ_NEXT(bq, b_act)) != NULL) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to go after the current request if there is an
|
* We want to go after the current request if it is the end
|
||||||
* inversion after it (i.e. it is the end of the first
|
* of the first request list, or if the next request is a
|
||||||
* request list), or if the next request is a larger cylinder
|
* larger cylinder than our request.
|
||||||
* than our request.
|
|
||||||
*/
|
*/
|
||||||
if (bn->b_pblkno < bq->b_pblkno ||
|
if (bn == bufq->switch_point
|
||||||
bp->b_pblkno < bn->b_pblkno)
|
|| bp->b_pblkno < bn->b_pblkno)
|
||||||
goto insert;
|
break;
|
||||||
bq = bn;
|
bq = bn;
|
||||||
}
|
}
|
||||||
/*
|
TAILQ_INSERT_AFTER(&bufq->queue, bq, bp, b_act);
|
||||||
* Neither a second list nor a larger request... we go at the end of
|
|
||||||
* the first list, which is the same as the end of the whole schebang.
|
|
||||||
*/
|
|
||||||
insert:
|
|
||||||
TAILQ_INSERT_AFTER(ap, bq, bp, b_act);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
|
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
|
||||||
* $Id: ufs_disksubr.c,v 1.30 1997/02/22 09:47:45 peter Exp $
|
* $Id: ufs_disksubr.c,v 1.31 1997/07/13 15:53:20 bde Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -50,109 +50,88 @@
|
|||||||
/*
|
/*
|
||||||
* Seek sort for disks.
|
* Seek sort for disks.
|
||||||
*
|
*
|
||||||
* The argument ap structure holds a b_actf activity chain pointer on which we
|
* The buf_queue keep two queues, sorted in ascending block order. The first
|
||||||
* keep two queues, sorted in ascending block order. The first queue holds
|
* queue holds those requests which are positioned after the current block
|
||||||
* those requests which are positioned after the current block (in the first
|
* (in the first request); the second, which starts at queue->switch_point,
|
||||||
* request); the second holds requests which came in after their block number
|
* holds requests which came in after their block number was passed. Thus
|
||||||
* was passed. Thus we implement a one way scan, retracting after reaching the
|
* we implement a one way scan, retracting after reaching the end of the drive
|
||||||
* end of the drive to the first request on the second queue, at which time it
|
* to the first request on the second queue, at which time it becomes the
|
||||||
* becomes the first queue.
|
* first queue.
|
||||||
*
|
*
|
||||||
* A one-way scan is natural because of the way UNIX read-ahead blocks are
|
* A one-way scan is natural because of the way UNIX read-ahead blocks are
|
||||||
* allocated.
|
* allocated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tqdisksort(ap, bp)
|
bufqdisksort(bufq, bp)
|
||||||
struct buf_queue_head *ap;
|
struct buf_queue_head *bufq;
|
||||||
register struct buf *bp;
|
struct buf *bp;
|
||||||
{
|
{
|
||||||
register struct buf *bq;
|
struct buf *bq;
|
||||||
struct buf *bn;
|
struct buf *bn;
|
||||||
|
int count;
|
||||||
|
|
||||||
/* If the queue is empty, then it's easy. */
|
/*
|
||||||
if ((bq = ap->tqh_first) == NULL) {
|
* If the queue is empty or we are an
|
||||||
TAILQ_INSERT_HEAD(ap, bp, b_act);
|
* ordered transaction, then it's easy.
|
||||||
|
*/
|
||||||
|
if ((bq = bufq_first(bufq)) == NULL
|
||||||
|
|| (bp->b_flags & B_ORDERED) != 0) {
|
||||||
|
bufq_insert_tail(bufq, bp);
|
||||||
|
return;
|
||||||
|
} else if (bufq->insert_point != NULL) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A certain portion of the list is
|
||||||
|
* "locked" to preserve ordering, so
|
||||||
|
* we can only insert after the insert
|
||||||
|
* point.
|
||||||
|
*/
|
||||||
|
bq = TAILQ_NEXT(bufq->insert_point, b_act);
|
||||||
|
if (bq == NULL) {
|
||||||
|
bufq_insert_tail(bufq, bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Put new writes after all reads */
|
|
||||||
if ((bp->b_flags & B_READ) == 0) {
|
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
if ((bq->b_flags & B_READ) == 0)
|
|
||||||
break;
|
|
||||||
bq = bn;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
if ((bq->b_flags & B_READ) == 0) {
|
|
||||||
if (ap->tqh_first != bq) {
|
|
||||||
bq = *bq->b_act.tqe_prev;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bq = bn;
|
|
||||||
}
|
|
||||||
goto insert;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we lie after the first (currently active) request, then we
|
* If we lie before the first (currently active) request, then we
|
||||||
* must locate the second request list and add ourselves to it.
|
* must add ourselves to the second request list.
|
||||||
*/
|
*/
|
||||||
if (bp->b_pblkno < bq->b_pblkno) {
|
if (bp->b_pblkno < bq->b_pblkno) {
|
||||||
while (bn = bq->b_act.tqe_next) {
|
|
||||||
|
bq = bufq->switch_point;
|
||||||
/*
|
/*
|
||||||
* Check for an ``inversion'' in the normally ascending
|
* If we are starting a new secondary list, then it's easy.
|
||||||
* cylinder numbers, indicating the start of the second
|
|
||||||
* request list.
|
|
||||||
*/
|
*/
|
||||||
if (bn->b_pblkno < bq->b_pblkno) {
|
if (bq == NULL) {
|
||||||
/*
|
bufq->switch_point = bp;
|
||||||
* Search the second request list for the first
|
bufq_insert_tail(bufq, bp);
|
||||||
* request at a larger cylinder number. We go
|
return;
|
||||||
* before that; if there is no such request, we
|
|
||||||
* go at end.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
if (bp->b_pblkno < bn->b_pblkno)
|
|
||||||
goto insert;
|
|
||||||
bq = bn;
|
|
||||||
} while (bn = bq->b_act.tqe_next);
|
|
||||||
goto insert; /* after last */
|
|
||||||
}
|
}
|
||||||
bq = bn;
|
if (bp->b_pblkno < bq->b_pblkno) {
|
||||||
|
bufq->switch_point = bp;
|
||||||
|
TAILQ_INSERT_BEFORE(bq, bp, b_act);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* No inversions... we will go after the last, and
|
|
||||||
* be the first request in the second request list.
|
|
||||||
*/
|
|
||||||
goto insert;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Request is at/after the current request...
|
* Request is at/after the current request...
|
||||||
* sort in the first request list.
|
* sort in the first request list.
|
||||||
*/
|
*/
|
||||||
while (bn = bq->b_act.tqe_next) {
|
while ((bn = TAILQ_NEXT(bq, b_act)) != NULL) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to go after the current request if there is an
|
* We want to go after the current request if it is the end
|
||||||
* inversion after it (i.e. it is the end of the first
|
* of the first request list, or if the next request is a
|
||||||
* request list), or if the next request is a larger cylinder
|
* larger cylinder than our request.
|
||||||
* than our request.
|
|
||||||
*/
|
*/
|
||||||
if (bn->b_pblkno < bq->b_pblkno ||
|
if (bn == bufq->switch_point
|
||||||
bp->b_pblkno < bn->b_pblkno)
|
|| bp->b_pblkno < bn->b_pblkno)
|
||||||
goto insert;
|
break;
|
||||||
bq = bn;
|
bq = bn;
|
||||||
}
|
}
|
||||||
/*
|
TAILQ_INSERT_AFTER(&bufq->queue, bq, bp, b_act);
|
||||||
* Neither a second list nor a larger request... we go at the end of
|
|
||||||
* the first list, which is the same as the end of the whole schebang.
|
|
||||||
*/
|
|
||||||
insert:
|
|
||||||
TAILQ_INSERT_AFTER(ap, bq, bp, b_act);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user