From e2a59bc08d2fb1e22396f8b3d6feb6b0b9c3d054 Mon Sep 17 00:00:00 2001 From: Michel Machado Date: Fri, 19 Jun 2020 11:23:24 -0400 Subject: [PATCH] libflow: avoid fdatasync() and posix_fadvise() This patch moves calls to fdatasync() and posix_fadvise() out of libflow as one more step to generalize libflow. --- f3write.c | 14 +++++++++++++- libflow.c | 24 +++++++++++++----------- libflow.h | 12 +++++++++++- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/f3write.c b/f3write.c index e5feb55..5dd90d5 100644 --- a/f3write.c +++ b/f3write.c @@ -262,6 +262,18 @@ static inline void pr_avg_speed(double speed) printf("Average writing speed: %.2f %s/s\n", speed, unit); } +static int flush_chunk(const struct flow *fw, int fd) +{ + UNUSED(fw); + + if (fdatasync(fd) < 0) + return -1; /* Caller can read errno(3). */ + + /* Help the kernel to help us. */ + assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)); + return 0; +} + static int fill_fs(const char *path, long start_at, long end_at, long max_write_rate, int progress) { @@ -296,7 +308,7 @@ static int fill_fs(const char *path, long start_at, long end_at, end_at = start_at + (free_space >> 30); } - init_flow(&fw, free_space, max_write_rate, progress); + init_flow(&fw, free_space, max_write_rate, progress, flush_chunk); assert(!gettimeofday(&t1, NULL)); for (i = start_at; i <= end_at; i++) if (create_and_fill_file(path, i, GIGABYTES, diff --git a/libflow.c b/libflow.c index 9a87363..601fa96 100644 --- a/libflow.c +++ b/libflow.c @@ -6,11 +6,9 @@ #include #include #include +#include #include -#include /* Needed for fdatasync(2). */ -#include /* Needed for posix_fadvise(2). */ - #include "libflow.h" #include "utils.h" @@ -21,7 +19,8 @@ static inline void move_to_inc_at_start(struct flow *fw) } void init_flow(struct flow *fw, uint64_t total_size, - long max_write_rate, int progress) + long max_write_rate, int progress, + flow_func_flush_chunk_t func_flush_chunk) { fw->total_size = total_size; fw->total_written = 0; @@ -34,6 +33,7 @@ void init_flow(struct flow *fw, uint64_t total_size, fw->measured_blocks = 0; fw->measured_time_ms = 0; fw->erase = 0; + fw->func_flush_chunk = func_flush_chunk; fw->written_blocks = 0; fw->acc_delay_us = 0; assert(fw->block_size > 0); @@ -198,6 +198,13 @@ static inline int is_rate_below(const struct flow *fw, return delay <= fw->delay_ms && inst_speed < fw->max_write_rate; } +static inline int flush_chunk(const struct flow *fw, int fd) +{ + if (fw->func_flush_chunk) + return fw->func_flush_chunk(fw, fd); + return 0; +} + /* XXX Avoid duplicate this function, which was copied from libutils.h. */ static inline uint64_t diff_timeval_us(const struct timeval *t1, const struct timeval *t2) @@ -221,12 +228,9 @@ int measure(int fd, struct flow *fw, ssize_t written) return 0; assert(fw->written_blocks == fw->blocks_per_delay); - if (fdatasync(fd) < 0) + if (flush_chunk(fw, fd) < 0) return -1; /* Caller can read errno(3). */ - /* Help the kernel to help us. */ - assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)); - assert(!gettimeofday(&t2, NULL)); delay = (diff_timeval_us(&fw->t1, &t2) + fw->acc_delay_us) / 1000; @@ -339,13 +343,11 @@ int end_measurement(int fd, struct flow *fw) if (fw->written_blocks <= 0) goto out; - if (fdatasync(fd) < 0) { + if (flush_chunk(fw, fd) < 0) { saved_errno = errno; ret = -1; goto out; } - /* Help the kernel to help us. */ - assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)); /* Save time in between closing ongoing file and creating a new file. */ assert(!gettimeofday(&t2, NULL)); diff --git a/libflow.h b/libflow.h index d3b6355..b3f7b79 100644 --- a/libflow.h +++ b/libflow.h @@ -3,6 +3,10 @@ #include +struct flow; + +typedef int (*flow_func_flush_chunk_t)(const struct flow *fw, int fd); + struct flow { /* Total number of bytes to be written. */ uint64_t total_size; @@ -29,6 +33,11 @@ struct flow { /* Number of characters to erase before printing out progress. */ int erase; + /* + * Methods + */ + flow_func_flush_chunk_t func_flush_chunk; + /* * Initialized while measuring */ @@ -50,7 +59,8 @@ struct flow { * The unit of @max_write_rate is KB per second. */ void init_flow(struct flow *fw, uint64_t total_size, - long max_write_rate, int progress); + long max_write_rate, int progress, + flow_func_flush_chunk_t func_flush_chunk); void start_measurement(struct flow *fw); int measure(int fd, struct flow *fw, ssize_t written);