struct timeval user_start;
struct timeval system_start;
void *brk_start;
+ unsigned long long bytes_read;
+ unsigned long long bytes_written;
};
#endif
extern char *string_copy(e2fsck_t ctx, const char *str, int len);
#ifdef RESOURCE_TRACK
extern void print_resource_track(const char *desc,
- struct resource_track *track);
-extern void init_resource_track(struct resource_track *track);
+ struct resource_track *track,
+ io_channel channel);
+extern void init_resource_track(struct resource_track *track,
+ io_channel channel);
#endif
extern int inode_has_valid_blocks(struct ext2_inode *inode);
extern void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
int inode_size;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 1"), &rtrack);
+ print_resource_track(_("Pass 1"), &rtrack, ctx->fs->io);
}
#endif
}
int bad_dir;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&cd.pctx);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 2"), &rtrack);
+ print_resource_track(_("Pass 2"), &rtrack, fs->io);
}
#endif
}
unsigned long maxdirs, count;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Peak memory"), &ctx->global_rtrack);
+ print_resource_track(_("Peak memory"), &ctx->global_rtrack,
+ NULL);
}
#endif
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 3"), &rtrack);
+ print_resource_track(_("Pass 3"), &rtrack, ctx->fs->io);
}
#endif
}
int group, maxgroup;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
#ifdef MTRACE
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 4"), &rtrack);
+ print_resource_track(_("Pass 4"), &rtrack, ctx->fs->io);
}
#endif
}
#endif
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 5"), &rtrack);
+ print_resource_track(_("Pass 5"), &rtrack, ctx->fs->io);
}
#endif
}
int cur, max, all_dirs, dir_index, first = 1;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track("Pass 3A", &rtrack);
+ print_resource_track("Pass 3A", &rtrack, ctx->fs->io);
}
#endif
}
#ifdef RESOURCE_TRACK
struct resource_track rtrack;
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
if (!(ctx->options & E2F_OPT_PREEN))
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2)
- print_resource_track(_("Byte swap"), &rtrack);
+ print_resource_track(_("Byte swap"), &rtrack, fs->io);
#endif
}
reserve_stdio_fds();
#ifdef RESOURCE_TRACK
- init_resource_track(&ctx->global_rtrack);
+ init_resource_track(&ctx->global_rtrack, NULL);
#endif
if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
}
e2fsck_write_bitmaps(ctx);
-
+#ifdef RESOURCE_TRACK
+ io_channel_flush(ctx->fs->io);
+ if (ctx->options & E2F_OPT_TIME)
+ print_resource_track(NULL, &ctx->global_rtrack, ctx->fs->io);
+#endif
ext2fs_close(fs);
ctx->fs = NULL;
free(ctx->filesystem_name);
free(ctx->journal_name);
-#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME)
- print_resource_track(NULL, &ctx->global_rtrack);
-#endif
e2fsck_free_context(ctx);
remove_error_table(&et_ext2_error_table);
remove_error_table(&et_prof_error_table);
}
#ifdef RESOURCE_TRACK
-void init_resource_track(struct resource_track *track)
+void init_resource_track(struct resource_track *track, io_channel channel)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
#endif
+ io_stats io_start = 0;
track->brk_start = sbrk(0);
gettimeofday(&track->time_start, 0);
track->user_start.tv_sec = track->user_start.tv_usec = 0;
track->system_start.tv_sec = track->system_start.tv_usec = 0;
#endif
+ track->bytes_read = 0;
+ track->bytes_written = 0;
+ if (channel && channel->manager && channel->manager->get_stats)
+ channel->manager->get_stats(channel, &io_start);
+ if (io_start) {
+ track->bytes_read = io_start->bytes_read;
+ track->bytes_written = io_start->bytes_written;
+ }
}
#ifdef __GNUC__
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
-void print_resource_track(const char *desc, struct resource_track *track)
+void print_resource_track(const char *desc, struct resource_track *track,
+ io_channel channel)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
printf(_("elapsed time: %6.3f\n"),
timeval_subtract(&time_end, &track->time_start));
#endif
+#define mbytes(x) (((x) + 1048575) / 1048576)
+ if (channel && channel->manager && channel->manager->get_stats) {
+ io_stats delta = 0;
+ unsigned long long bytes_read = 0;
+ unsigned long long bytes_written = 0;
+
+ if (desc)
+ printf("%s: ", desc);
+
+ channel->manager->get_stats(channel, &delta);
+ if (delta) {
+ bytes_read = delta->bytes_read - track->bytes_read;
+ bytes_written = delta->bytes_written -
+ track->bytes_written;
+ }
+ printf("I/O read: %lluMB, write: %lluMB, rate: %.2fMB/s\n",
+ mbytes(bytes_read), mbytes(bytes_written),
+ (double)mbytes(bytes_read + bytes_written) /
+ timeval_subtract(&time_end, &track->time_start));
+ }
}
#endif /* RESOURCE_TRACK */
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
+typedef struct struct_io_stats *io_stats;
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
void *app_data;
};
+struct struct_io_stats {
+ int num_fields;
+ int reserved;
+ unsigned long long bytes_read;
+ unsigned long long bytes_written;
+};
+
struct struct_io_manager {
errcode_t magic;
const char *name;
int count, const void *data);
errcode_t (*set_option)(io_channel channel, const char *option,
const char *arg);
+ errcode_t (*get_stats)(io_channel channel, io_stats *io_stats);
int reserved[14];
};
int count, const void *buf);
static errcode_t test_set_option(io_channel channel, const char *option,
const char *arg);
+static errcode_t test_get_stats(io_channel channel, io_stats *stats);
+
static struct struct_io_manager struct_test_manager = {
EXT2_ET_MAGIC_IO_MANAGER,
test_write_blk,
test_flush,
test_write_byte,
- test_set_option
+ test_set_option,
+ test_get_stats,
};
io_manager test_io_manager = &struct_test_manager;
}
return retval;
}
+
+static errcode_t test_get_stats(io_channel channel, io_stats *stats)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real && data->real->manager->get_stats) {
+ retval = (data->real->manager->get_stats)(data->real, stats);
+ }
+ return retval;
+}
int access_time;
ext2_loff_t offset;
struct unix_cache cache[CACHE_SIZE];
+ struct struct_io_stats io_stats;
};
static errcode_t unix_open(const char *name, int flags, io_channel *channel);
int size, const void *data);
static errcode_t unix_set_option(io_channel channel, const char *option,
const char *arg);
-
+static errcode_t unix_get_stats(io_channel channel, io_stats *stats)
+;
static void reuse_cache(io_channel channel, struct unix_private_data *data,
struct unix_cache *cache, unsigned long block);
#else
unix_write_byte,
#endif
- unix_set_option
+ unix_set_option,
+ unix_get_stats,
};
io_manager unix_io_manager = &struct_unix_manager;
+static errcode_t unix_get_stats(io_channel channel, io_stats *stats)
+{
+ errcode_t retval = 0;
+
+ struct unix_private_data *data;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ if (stats)
+ *stats = &data->io_stats;
+
+ return retval;
+}
+
/*
* Here are the raw I/O functions
*/
int actual = 0;
size = (count < 0) ? -count : count * channel->block_size;
+ data->io_stats.bytes_read += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
char sector[BLOCKALIGN];
size = (count < 0) ? -count : count * channel->block_size;
+ data->io_stats.bytes_read += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
#ifdef DEBUG
printf("count=%d, size=%d, block=%lu, blk_size=%d, location=%llx\n",
else
size = count * channel->block_size;
}
+ data->io_stats.bytes_written += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
memset(data, 0, sizeof(struct unix_private_data));
data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
+ data->io_stats.num_fields = 2;
if ((retval = alloc_cache(io, data)))
goto cleanup;