throttle-groups.c (6bd8ab6889f45a42d69a3a65a4d6e7fc2453c84c) | throttle-groups.c (6bf77e1c2dc24da1bade16e8a9a637f3b127314d) |
---|---|
1/* 2 * QEMU block throttling group infrastructure 3 * 4 * Copyright (C) Nodalink, EURL. 2014 5 * Copyright (C) Igalia, S.L. 2015 6 * 7 * Authors: 8 * Benoît Canet <benoit.canet@nodalink.com> --- 154 unchanged lines hidden (view full) --- 163 164 if (!next) { 165 next = QLIST_FIRST(&tg->head); 166 } 167 168 return blk_by_public(next); 169} 170 | 1/* 2 * QEMU block throttling group infrastructure 3 * 4 * Copyright (C) Nodalink, EURL. 2014 5 * Copyright (C) Igalia, S.L. 2015 6 * 7 * Authors: 8 * Benoît Canet <benoit.canet@nodalink.com> --- 154 unchanged lines hidden (view full) --- 163 164 if (!next) { 165 next = QLIST_FIRST(&tg->head); 166 } 167 168 return blk_by_public(next); 169} 170 |
171/* 172 * Return whether a BlockBackend has pending requests. 173 * 174 * This assumes that tg->lock is held. 175 * 176 * @blk: the BlockBackend 177 * @is_write: the type of operation (read/write) 178 * @ret: whether the BlockBackend has pending requests. 179 */ 180static inline bool blk_has_pending_reqs(BlockBackend *blk, 181 bool is_write) 182{ 183 const BlockBackendPublic *blkp = blk_get_public(blk); 184 return blkp->pending_reqs[is_write]; 185} 186 |
|
171/* Return the next BlockBackend in the round-robin sequence with pending I/O 172 * requests. 173 * 174 * This assumes that tg->lock is held. 175 * 176 * @blk: the current BlockBackend 177 * @is_write: the type of operation (read/write) 178 * @ret: the next BlockBackend with pending requests, or blk if there is --- 4 unchanged lines hidden (view full) --- 183 BlockBackendPublic *blkp = blk_get_public(blk); 184 ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts); 185 BlockBackend *token, *start; 186 187 start = token = tg->tokens[is_write]; 188 189 /* get next bs round in round robin style */ 190 token = throttle_group_next_blk(token); | 187/* Return the next BlockBackend in the round-robin sequence with pending I/O 188 * requests. 189 * 190 * This assumes that tg->lock is held. 191 * 192 * @blk: the current BlockBackend 193 * @is_write: the type of operation (read/write) 194 * @ret: the next BlockBackend with pending requests, or blk if there is --- 4 unchanged lines hidden (view full) --- 199 BlockBackendPublic *blkp = blk_get_public(blk); 200 ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts); 201 BlockBackend *token, *start; 202 203 start = token = tg->tokens[is_write]; 204 205 /* get next bs round in round robin style */ 206 token = throttle_group_next_blk(token); |
191 while (token != start && !blkp->pending_reqs[is_write]) { | 207 while (token != start && !blk_has_pending_reqs(token, is_write)) { |
192 token = throttle_group_next_blk(token); 193 } 194 195 /* If no IO are queued for scheduling on the next round robin token 196 * then decide the token is the current bs because chances are 197 * the current bs get the current request queued. 198 */ | 208 token = throttle_group_next_blk(token); 209 } 210 211 /* If no IO are queued for scheduling on the next round robin token 212 * then decide the token is the current bs because chances are 213 * the current bs get the current request queued. 214 */ |
199 if (token == start && !blkp->pending_reqs[is_write]) { | 215 if (token == start && !blk_has_pending_reqs(token, is_write)) { |
200 token = blk; 201 } 202 | 216 token = blk; 217 } 218 |
219 /* Either we return the original BB, or one with pending requests */ 220 assert(token == blk || blk_has_pending_reqs(token, is_write)); 221 |
|
203 return token; 204} 205 206/* Check if the next I/O request for a BlockBackend needs to be throttled or 207 * not. If there's no timer set in this group, set one and update the token 208 * accordingly. 209 * 210 * This assumes that tg->lock is held. --- 41 unchanged lines hidden (view full) --- 252{ 253 BlockBackendPublic *blkp = blk_get_public(blk); 254 ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts); 255 bool must_wait; 256 BlockBackend *token; 257 258 /* Check if there's any pending request to schedule next */ 259 token = next_throttle_token(blk, is_write); | 222 return token; 223} 224 225/* Check if the next I/O request for a BlockBackend needs to be throttled or 226 * not. If there's no timer set in this group, set one and update the token 227 * accordingly. 228 * 229 * This assumes that tg->lock is held. --- 41 unchanged lines hidden (view full) --- 271{ 272 BlockBackendPublic *blkp = blk_get_public(blk); 273 ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts); 274 bool must_wait; 275 BlockBackend *token; 276 277 /* Check if there's any pending request to schedule next */ 278 token = next_throttle_token(blk, is_write); |
260 if (!blkp->pending_reqs[is_write]) { | 279 if (!blk_has_pending_reqs(token, is_write)) { |
261 return; 262 } 263 264 /* Set a timer for the request if it needs to be throttled */ 265 must_wait = throttle_group_schedule_timer(token, is_write); 266 267 /* If it doesn't have to wait, queue it for immediate execution */ 268 if (!must_wait) { 269 /* Give preference to requests from the current blk */ 270 if (qemu_in_coroutine() && 271 qemu_co_queue_next(&blkp->throttled_reqs[is_write])) { 272 token = blk; 273 } else { | 280 return; 281 } 282 283 /* Set a timer for the request if it needs to be throttled */ 284 must_wait = throttle_group_schedule_timer(token, is_write); 285 286 /* If it doesn't have to wait, queue it for immediate execution */ 287 if (!must_wait) { 288 /* Give preference to requests from the current blk */ 289 if (qemu_in_coroutine() && 290 qemu_co_queue_next(&blkp->throttled_reqs[is_write])) { 291 token = blk; 292 } else { |
274 ThrottleTimers *tt = &blkp->throttle_timers; | 293 ThrottleTimers *tt = &blk_get_public(token)->throttle_timers; |
275 int64_t now = qemu_clock_get_ns(tt->clock_type); 276 timer_mod(tt->timers[is_write], now + 1); 277 tg->any_timer_armed[is_write] = true; 278 } 279 tg->tokens[is_write] = token; 280 } 281} 282 --- 227 unchanged lines hidden --- | 294 int64_t now = qemu_clock_get_ns(tt->clock_type); 295 timer_mod(tt->timers[is_write], now + 1); 296 tg->any_timer_armed[is_write] = true; 297 } 298 tg->tokens[is_write] = token; 299 } 300} 301 --- 227 unchanged lines hidden --- |