summaryrefslogtreecommitdiffstats
path: root/sys/geom/sched
diff options
context:
space:
mode:
Diffstat (limited to 'sys/geom/sched')
-rw-r--r--sys/geom/sched/subr_disk.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/sys/geom/sched/subr_disk.c b/sys/geom/sched/subr_disk.c
index 008eaab..db2a9ef 100644
--- a/sys/geom/sched/subr_disk.c
+++ b/sys/geom/sched/subr_disk.c
@@ -86,7 +86,7 @@ __FBSDID("$FreeBSD$");
* bioq_remove() remove a generic element from the queue, act as
* bioq_takefirst() if invoked on the head of the queue.
*
- * The semantic of these methods is the same of the operations
+ * The semantic of these methods is the same as the operations
* on the underlying TAILQ, but with additional guarantees on
* subsequent bioq_disksort() calls. E.g. bioq_insert_tail()
* can be useful for making sure that all previous ops are flushed
@@ -115,10 +115,10 @@ void
gs_bioq_remove(struct bio_queue_head *head, struct bio *bp)
{
- if (bp == TAILQ_FIRST(&head->queue))
- head->last_offset = bp->bio_offset + bp->bio_length;
-
- if (bp == head->insert_point)
+ if (head->insert_point == NULL) {
+ if (bp == TAILQ_FIRST(&head->queue))
+ head->last_offset = bp->bio_offset + bp->bio_length;
+ } else if (bp == head->insert_point)
head->insert_point = NULL;
TAILQ_REMOVE(&head->queue, bp, bio_queue);
@@ -137,7 +137,8 @@ void
gs_bioq_insert_head(struct bio_queue_head *head, struct bio *bp)
{
- head->last_offset = bp->bio_offset;
+ if (head->insert_point == NULL)
+ head->last_offset = bp->bio_offset;
TAILQ_INSERT_HEAD(&head->queue, bp, bio_queue);
}
@@ -147,6 +148,7 @@ gs_bioq_insert_tail(struct bio_queue_head *head, struct bio *bp)
TAILQ_INSERT_TAIL(&head->queue, bp, bio_queue);
head->insert_point = bp;
+ head->last_offset = bp->bio_offset;
}
struct bio *
@@ -189,13 +191,28 @@ gs_bioq_bio_key(struct bio_queue_head *head, struct bio *bp)
void
gs_bioq_disksort(struct bio_queue_head *head, struct bio *bp)
{
- struct bio *cur, *prev = NULL;
- uoff_t key = gs_bioq_bio_key(head, bp);
+ struct bio *cur, *prev;
+ uoff_t key;
+
+ if ((bp->bio_flags & BIO_ORDERED) != 0) {
+ /*
+ * Ordered transactions can only be dispatched
+ * after any currently queued transactions. They
+ * also have barrier semantics - no transactions
+ * queued in the future can pass them.
+ */
+ gs_bioq_insert_tail(head, bp);
+ return;
+ }
+ prev = NULL;
+ key = gs_bioq_bio_key(head, bp);
cur = TAILQ_FIRST(&head->queue);
- if (head->insert_point)
- cur = head->insert_point;
+ if (head->insert_point) {
+ prev = head->insert_point;
+ cur = TAILQ_NEXT(head->insert_point, bio_queue);
+ }
while (cur != NULL && key >= gs_bioq_bio_key(head, cur)) {
prev = cur;
OpenPOWER on IntegriCloud