diff options
-rw-r--r-- | libbcachefs.c | 14 | ||||
-rw-r--r-- | tools-util.c | 126 | ||||
-rw-r--r-- | tools-util.h | 2 |
3 files changed, 142 insertions, 0 deletions
diff --git a/libbcachefs.c b/libbcachefs.c index 499badb..e55d8ec 100644 --- a/libbcachefs.c +++ b/libbcachefs.c @@ -258,6 +258,20 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs, SET_BCH_MEMBER_GROUP(m, idx + 1); } + for (i = devs; i < devs + nr_devs; i++) { + struct bch_member *m = bch2_members_v2_get_mut(sb.sb, (i - devs)); + + for (unsigned j = 0; j < ARRAY_SIZE(m->iops); j++) { + int iops = benchmark_device(i->bdev, j); + + if (iops < 0) + die("error benchmarking device %s", i->path); + if (!iops) + fprintf(stderr, "Warning device not performing any operations"); + m->iops[j] = cpu_to_le32(iops); + } + } + SET_BCH_SB_FOREGROUND_TARGET(sb.sb, parse_target(&sb, devs, nr_devs, fs_opt_strs.foreground_target)); SET_BCH_SB_BACKGROUND_TARGET(sb.sb, diff --git a/tools-util.c b/tools-util.c index f6e9a47..2f138c0 100644 --- a/tools-util.c +++ b/tools-util.c @@ -17,6 +17,7 @@ #include <blkid.h> #include <uuid/uuid.h> +#include <linux/random.h> #include "libbcachefs.h" #include "libbcachefs/bcachefs_ioctl.h" #include "linux/sort.h" @@ -681,3 +682,128 @@ struct bbpos bbpos_parse(char *buf) ret.pos = bpos_parse(s); return ret; } + +struct benchmark_bios; + +struct benchmark_bio { + struct benchmark_bios *bios; + bool complete; + void *p; + size_t nr_bio_vecs; + struct bio bio; + struct bio_vec *bv; +}; + +struct benchmark_bios { + struct block_device *bdev; + enum bch_iops_measurement mode; + unsigned blocksize; + u64 nr_blocks; + u64 nr_done; + wait_queue_head_t wait; + struct benchmark_bio bios[64]; +}; + +static void benchmark_device_endio(struct bio *bio) +{ + struct benchmark_bio *bbio = container_of(bio, struct benchmark_bio, bio); + struct benchmark_bios *bios = bbio->bios; + + bbio->complete = true; + + wake_up(&bios->wait); +} + +static bool benchmark_submit(struct benchmark_bios *bios) +{ + bool submitted = false; + + for (unsigned i = 0; i < ARRAY_SIZE(bios->bios); i++) { + struct bio *bio = &bios->bios[i].bio; + + if (!bios->bios[i].complete) + continue; + + bios->bios[i].complete = false; + bio_init(&bios->bios[i].bio, bios->bdev, bios->bios[i].bv, bios->bios[i].nr_bio_vecs, 0); + bio->bi_end_io = benchmark_device_endio; + + bch2_bio_map(bio, bios->bios[i].p, bios->blocksize << 9); + + switch (bios->mode) { + case BCH_IOPS_seqread: + bio->bi_opf = REQ_OP_READ; + bio->bi_iter.bi_sector = bios->nr_done * bios->blocksize; + break; + case BCH_IOPS_seqwrite: + bio->bi_opf = REQ_OP_WRITE; + bio->bi_iter.bi_sector = bios->nr_done * bios->blocksize; + break; + case BCH_IOPS_randread: + bio->bi_opf = REQ_OP_READ; + bio->bi_iter.bi_sector = get_random_u64() % bios->nr_blocks * bios->blocksize;// get random number + break; + case BCH_IOPS_randwrite: + bio->bi_opf = REQ_OP_WRITE; + bio->bi_iter.bi_sector = get_random_u64() % bios->nr_blocks * bios->blocksize;// get random number * bios->blocksize + break; + default: + BUG(); + } + + submit_bio(bio); + + submitted = true; + bios->nr_done++; + } + + return submitted; +} + +static bool bios_are(struct benchmark_bios *bios, bool completed) +{ + for (unsigned i = 0; i < ARRAY_SIZE(bios->bios); i++) + if (bios->bios[i].complete == completed) + return true; + return false; +} + +int benchmark_device(struct block_device *bdev, enum bch_iops_measurement mode) +{ + struct benchmark_bios bios; + unsigned i; + + bios.bdev = bdev; + bios.mode = mode; + bios.blocksize = get_blocksize(bios.bdev->bd_buffered_fd) >> 9; + bios.nr_blocks = (get_size(bios.bdev->bd_buffered_fd) >> 9)/bios.blocksize; + bios.nr_done = 0; + init_waitqueue_head(&bios.wait); + + for (i = 0; i < ARRAY_SIZE(bios.bios); i++) { + bios.bios[i].bios = &bios; + bios.bios[i].complete = true; + bios.bios[i].p = kmalloc(bios.blocksize << 9, GFP_KERNEL); + bios.bios[i].nr_bio_vecs = buf_pages(bios.bios[i].p, bios.blocksize << 9); + bios.bios[i].bv = kmalloc(bios.bios[i].nr_bio_vecs * sizeof(struct bio_vec), GFP_KERNEL); + } + + struct timespec start_ts, now_ts; + clock_gettime(CLOCK_MONOTONIC, &start_ts); + + u64 start = timespec_to_ns(&start_ts); + + while (true) { + wait_event(bios.wait, bios_are(&bios, true)); + benchmark_submit(&bios); + + clock_gettime(CLOCK_MONOTONIC, &now_ts); + u64 now = timespec_to_ns(&now_ts); + + if (now - start > 5 * NSEC_PER_SEC) + break; + } + + wait_event(bios.wait, !bios_are(&bios, false)); + return bios.nr_done / 5; +} diff --git a/tools-util.h b/tools-util.h index 7a04c10..f807dbd 100644 --- a/tools-util.h +++ b/tools-util.h @@ -172,4 +172,6 @@ do { \ struct bpos bpos_parse(char *); struct bbpos bbpos_parse(char *); +int benchmark_device(struct block_device *bdev, enum bch_iops_measurement mode); + #endif /* _TOOLS_UTIL_H */ |