* Record the ending of a transaction, and incrment the various counters. * * Ordering in this function, and in devstat_start_transaction() is VERY * important. The idea here is to run without locks, so we are very * careful to only modify some fields on the way "down" (i.e. at * transaction start) and some fields on the way "up" (i.e. at transaction * completion). One exception is busy_fro
| 298 | * atomic instructions using appropriate memory barriers. |
| 299 | */ |
| 300 | void |
| 301 | devstat_end_transaction(struct devstat *ds, uint32_t bytes, |
| 302 | devstat_tag_type tag_type, devstat_trans_flags flags, |
| 303 | const struct bintime *now, const struct bintime *then) |
| 304 | { |
| 305 | struct bintime dt, lnow; |
| 306 | |
| 307 | /* sanity check */ |
| 308 | if (ds == NULL) |
| 309 | return; |
| 310 | |
| 311 | if (now == NULL) { |
| 312 | binuptime(&lnow); |
| 313 | now = &lnow; |
| 314 | } |
| 315 | |
| 316 | atomic_add_acq_int(&ds->sequence1, 1); |
| 317 | /* Update byte and operations counts */ |
| 318 | ds->bytes[flags] += bytes; |
| 319 | ds->operations[flags]++; |
| 320 | |
| 321 | /* |
| 322 | * Keep a count of the various tag types sent. |
| 323 | */ |
| 324 | if ((ds->flags & DEVSTAT_NO_ORDERED_TAGS) == 0 && |
| 325 | tag_type != DEVSTAT_TAG_NONE) |
| 326 | ds->tag_types[tag_type]++; |
| 327 | |
| 328 | if (then != NULL) { |
| 329 | /* Update duration of operations */ |
| 330 | dt = *now; |
| 331 | bintime_sub(&dt, then); |
| 332 | bintime_add(&ds->duration[flags], &dt); |
| 333 | } |
| 334 | |
| 335 | /* Accumulate busy time */ |
| 336 | dt = *now; |
| 337 | bintime_sub(&dt, &ds->busy_from); |
| 338 | bintime_add(&ds->busy_time, &dt); |
| 339 | ds->busy_from = *now; |
| 340 | |
| 341 | ds->end_count++; |
| 342 | atomic_add_rel_int(&ds->sequence0, 1); |
| 343 | DTRACE_DEVSTAT_DONE(); |
| 344 | } |
| 345 | |
| 346 | void |
| 347 | devstat_end_transaction_bio(struct devstat *ds, const struct bio *bp) |
no test coverage detected