FreeBSD/sys/geom/sched/gs_rr.c
/*
 * Called on a request arrival, timeout or completion.
 * Try to serve a request among those queued.
 */
Called on a request arrival, timeout or completion.
Try to serve a request among those queued.
Called on a request arrival timeout or completion . Try to serve a request among those queued .
static struct bio *
g_rr_next(void *data, int force)
{
	struct g_rr_softc *sc = data;
	struct g_rr_queue *qp;
	struct bio *bp, *next;
	int expired;
	qp = sc->sc_active;
	if (me.bypass == 0 && !force) {
		if (sc->sc_in_flight >= get_bounded(&me.queue_depth, 0))
			return (NULL);
		if (qp != NULL && qp->q_status != G_QUEUE_READY) {
			return (NULL);
		}
	} else if (qp != NULL && qp->q_status != G_QUEUE_READY) {
		g_rr_queue_put(qp);
		sc->sc_active = qp = NULL;
	}
	if (qp == NULL) {
		qp = TAILQ_FIRST(&sc->sc_rr_tailq);
		if (qp == NULL)
			return (NULL); 
		TAILQ_REMOVE(&sc->sc_rr_tailq, qp, q_tailq);
		sc->sc_active = qp;
		qp->q_service = 0;
		qp->q_flags &= ~G_FLAG_COMPLETED;
	}
	bp = bioq_takefirst(&qp->q_bioq);	
	qp->q_service += bp->bio_length;	
	expired = g_rr_queue_expired(qp);	
	next = bioq_first(&qp->q_bioq);	
 	if (expired) {
		sc->sc_active = NULL;
		if (next != NULL)
			TAILQ_INSERT_TAIL(&sc->sc_rr_tailq, qp, q_tailq);
		else
			g_rr_queue_put(qp);
	} else if (next != NULL) {
		qp->q_status = G_QUEUE_READY;
	} else {
		if (!force && g_rr_should_anticipate(qp, bp)) {
			qp->q_status = G_QUEUE_BUSY;
		} else {
			g_rr_queue_put(qp);
			sc->sc_active = NULL;
		}
	}
	sc->sc_in_flight++;
	return (bp);
}
static struct bio * g_rr_next ( void * data , int force ) { struct g_rr_softc * sc = data ; struct g_rr_queue * qp ; struct bio * bp , * next ; int expired ; qp = sc -> sc_active ; if ( me . bypass == 0 && ! force ) { if ( sc -> sc_in_flight >= get_bounded ( & me . queue_depth , 0 ) ) return ( NULL ) ; if ( qp != NULL && qp -> q_status != G_QUEUE_READY ) { return ( NULL ) ; } } else if ( qp != NULL && qp -> q_status != G_QUEUE_READY ) { g_rr_queue_put ( qp ) ; sc -> sc_active = qp = NULL ; } if ( qp == NULL ) { qp = TAILQ_FIRST ( & sc -> sc_rr_tailq ) ; if ( qp == NULL ) return ( NULL ) ; TAILQ_REMOVE ( & sc -> sc_rr_tailq , qp , q_tailq ) ; sc -> sc_active = qp ; qp -> q_service = 0 ; qp -> q_flags &= ~ G_FLAG_COMPLETED ; } bp = bioq_takefirst ( & qp -> q_bioq ) ; qp -> q_service += bp -> bio_length ; expired = g_rr_queue_expired ( qp ) ; next = bioq_first ( & qp -> q_bioq ) ; if ( expired ) { sc -> sc_active = NULL ; if ( next != NULL ) TAILQ_INSERT_TAIL ( & sc -> sc_rr_tailq , qp , q_tailq ) ; else g_rr_queue_put ( qp ) ; } else if ( next != NULL ) { qp -> q_status = G_QUEUE_READY ; } else { if ( ! force && g_rr_should_anticipate ( qp , bp ) ) { qp -> q_status = G_QUEUE_BUSY ; } else { g_rr_queue_put ( qp ) ; sc -> sc_active = NULL ; } } sc -> sc_in_flight ++ ; return ( bp ) ; }
Called on a request arrival, timeout or completion.
Called on a request arrival timeout or completion .
/* Try with the queue under service first. */ /*
			 * Queue is anticipating, ignore request.
			 * We should check that we are not past
			 * the timeout, but in that case the timeout
			 * will fire immediately afterwards so we
			 * don't bother.
			 */ /*
	 * No queue under service, look for the first in RR order.
	 * If we find it, select if as sc_active, clear service
	 * and record the end time of the slice.
	 */ /* no queues at all, return */ /* otherwise select the new queue for service. */ /* surely not NULL */ /* charge the service */ /*
	 * The request at the head of the active queue is always
	 * dispatched, and gs_rr_next() will be called again
	 * immediately.
	 * We need to prepare for what to do next:
	 *
	 * 1. have we reached the end of the (time or service) slice ?
	 *    If so, clear sc_active and possibly requeue the previous
	 *    active queue if it has more requests pending;
	 * 2. do we have more requests in sc_active ?
	 *    If yes, do not anticipate, as gs_rr_next() will run again;
	 *    if no, decide whether or not to anticipate depending
	 *    on read or writes (e.g., anticipate only on reads).
	 */ /* are we expired ? */ /* do we have one more ? */ /* Either requeue or release reference. */ /* anticipate */ /* do not anticipate, release reference */ /* If sc_active != NULL, its q_status is always correct. */