// SPDX-License-Identifier: GPL-2.0 /* * random utility code, for bcache but in theory not specific to bcache * * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com> * Copyright 2012 Google, Inc.
*/
/** * bch_hprint - formats @v to human readable string for sysfs. * @buf: the (at least 8 byte) buffer to format the result into. * @v: signed 64 bit integer * * Returns the number of bytes used by format.
*/
ssize_t bch_hprint(char *buf, int64_t v)
{ staticconstchar units[] = "?kMGTPEZY"; int u = 0, t;
uint64_t q;
if (v < 0)
q = -v; else
q = v;
/* For as long as the number is more than 3 digits, but at least * once, shift right / divide by 1024. Keep the remainder for * a digit after the decimal point.
*/ do {
u++;
t = q & ~(~0 << 10);
q >>= 10;
} while (q >= 1000);
if (v < 0) /* '-', up to 3 digits, '.', 1 digit, 1 character, null; * yields 8 bytes.
*/ return sprintf(buf, "-%llu.%i%c", q, t * 10 / 1024, units[u]); else return sprintf(buf, "%llu.%i%c", q, t * 10 / 1024, units[u]);
}
if (stats->last) {
ewma_add(stats->average_duration, duration, 8, 8);
if (stats->average_frequency)
ewma_add(stats->average_frequency, last, 8, 8); else
stats->average_frequency = last << 8;
} else {
stats->average_duration = duration << 8;
}
stats->last = now ?: 1;
spin_unlock(&stats->lock);
}
/** * bch_next_delay() - update ratelimiting statistics and calculate next delay * @d: the struct bch_ratelimit to update * @done: the amount of work done, in arbitrary units * * Increment @d by the amount of work done, and return how long to delay in * jiffies until the next time to do some work.
*/
uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
{
uint64_t now = local_clock();
/* Bound the time. Don't let us fall further than 2 seconds behind * (this prevents unnecessary backlog that would make it impossible * to catch up). If we're ahead of the desired writeback rate, * don't let us sleep more than 2.5 seconds (so we can notice/respond * if the control system tells us to speed up!).
*/ if (time_before64(now + NSEC_PER_SEC * 5LLU / 2LLU, d->next))
d->next = now + NSEC_PER_SEC * 5LLU / 2LLU;
if (time_after64(now - NSEC_PER_SEC * 2, d->next))
d->next = now - NSEC_PER_SEC * 2;
/* * Generally it isn't good to access .bi_io_vec and .bi_vcnt directly, * the preferred way is bio_add_page, but in this case, bch_bio_map() * supposes that the bvec table is empty, so it is safe to access * .bi_vcnt & .bi_io_vec in this way even after multipage bvec is * supported.
*/ void bch_bio_map(struct bio *bio, void *base)
{
size_t size = bio->bi_iter.bi_size; struct bio_vec *bv = bio->bi_io_vec;
/** * bch_bio_alloc_pages - allocates a single page for each bvec in a bio * @bio: bio to allocate pages for * @gfp_mask: flags for allocation * * Allocates pages up to @bio->bi_vcnt. * * Returns 0 on success, -ENOMEM on failure. On failure, any allocated pages are * freed.
*/ int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
{ int i; struct bio_vec *bv;
/* * This is called on freshly new bio, so it is safe to access the * bvec table directly.
*/ for (i = 0, bv = bio->bi_io_vec; i < bio->bi_vcnt; bv++, i++) {
bv->bv_page = alloc_page(gfp_mask); if (!bv->bv_page) { while (--bv >= bio->bi_io_vec)
__free_page(bv->bv_page); return -ENOMEM;
}
}
return 0;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.