]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Add I/O statistics to e2fsck
authorTheodore Ts'o <tytso@mit.edu>
Sat, 4 Aug 2007 00:07:09 +0000 (20:07 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 4 Aug 2007 00:07:09 +0000 (20:07 -0400)
This patch instruments the libext2fs unix I/O manager and adds bytes
read/written and data rate to e2fsck -tt pass/overall timing output.

Signed-off-by: Jim Garlick <garlick@llnl.gov>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
13 files changed:
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/pass2.c
e2fsck/pass3.c
e2fsck/pass4.c
e2fsck/pass5.c
e2fsck/rehash.c
e2fsck/swapfs.c
e2fsck/unix.c
e2fsck/util.c
lib/ext2fs/ext2_io.h
lib/ext2fs/test_io.c
lib/ext2fs/unix_io.c

index 96b83dab6fe63c56db3b59acb7a05264b1d9122f..5a9b44f32172dd1f8400e103447ababd4b647f5d 100644 (file)
@@ -135,6 +135,8 @@ struct resource_track {
        struct timeval user_start;
        struct timeval system_start;
        void    *brk_start;
+       unsigned long long bytes_read;
+       unsigned long long bytes_written;
 };
 #endif
 
@@ -469,8 +471,10 @@ extern void preenhalt(e2fsck_t ctx);
 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,
index bed1ec8909e609336a708134a3113d49af382dce..5c2c1aa211a1d84186850e9084c464ea7cb3f3db 100644 (file)
@@ -485,7 +485,7 @@ void e2fsck_pass1(e2fsck_t ctx)
        int             inode_size;
        
 #ifdef RESOURCE_TRACK
-       init_resource_track(&rtrack);
+       init_resource_track(&rtrack, ctx->fs->io);
 #endif
        clear_problem_context(&pctx);
 
@@ -1013,7 +1013,7 @@ endit:
 #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
 }
index 5e088e2dd015a78f3c9ba18307db223b4783b679..7f7635f27dd90658e0295cf1c9f47a9ca0014b2c 100644 (file)
@@ -102,7 +102,7 @@ void e2fsck_pass2(e2fsck_t ctx)
        int                     bad_dir;
 
 #ifdef RESOURCE_TRACK
-       init_resource_track(&rtrack);
+       init_resource_track(&rtrack, ctx->fs->io);
 #endif
 
        clear_problem_context(&cd.pctx);
@@ -287,7 +287,7 @@ void e2fsck_pass2(e2fsck_t ctx)
 #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
 }
index b9c6edd39c54625f5c2a8e2fd4864c8f1c9c0613..867cbf8310b6bdff0014719c52b0df4b545b06d9 100644 (file)
@@ -61,7 +61,7 @@ void e2fsck_pass3(e2fsck_t ctx)
        unsigned long maxdirs, count;
 
 #ifdef RESOURCE_TRACK
-       init_resource_track(&rtrack);
+       init_resource_track(&rtrack, ctx->fs->io);
 #endif
 
        clear_problem_context(&pctx);
@@ -87,7 +87,8 @@ void e2fsck_pass3(e2fsck_t ctx)
 #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
 
@@ -142,7 +143,7 @@ abort_exit:
 #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
 }
index dfb3a37ba5c7ccab85394c40bb65288453113a1d..0fb8ee7db265126a0b2a9de92fd7b7bf1fb577a8 100644 (file)
@@ -93,7 +93,7 @@ void e2fsck_pass4(e2fsck_t ctx)
        int     group, maxgroup;
        
 #ifdef RESOURCE_TRACK
-       init_resource_track(&rtrack);
+       init_resource_track(&rtrack, ctx->fs->io);
 #endif
 
 #ifdef MTRACE
@@ -173,7 +173,7 @@ errout:
 #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
 }
index deb558a8c1252ffc6ad6e0b72c512544b46eeef3..53248b01b502692c8936bb4715cbb5ff5644bd02 100644 (file)
@@ -30,7 +30,7 @@ void e2fsck_pass5(e2fsck_t ctx)
 #endif
 
 #ifdef RESOURCE_TRACK
-       init_resource_track(&rtrack);
+       init_resource_track(&rtrack, ctx->fs->io);
 #endif
        
        clear_problem_context(&pctx);
@@ -67,7 +67,7 @@ void e2fsck_pass5(e2fsck_t ctx)
 #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
 }
index 3aa3c06d6368069743c124dcce6c04e949846219..8c1459c41900f0e90bf5213f6d2921bcb4d304a0 100644 (file)
@@ -778,7 +778,7 @@ void e2fsck_rehash_directories(e2fsck_t ctx)
        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;
@@ -847,7 +847,7 @@ void e2fsck_rehash_directories(e2fsck_t ctx)
 #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
 }
index fb7270c0fe57611c1d923703ca6387ba9375dc18..81f3ca2c9b96ea006c782a10fc1aa551bdcab0b5 100644 (file)
@@ -219,7 +219,7 @@ void swap_filesys(e2fsck_t ctx)
 #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))
@@ -265,7 +265,7 @@ void swap_filesys(e2fsck_t ctx)
        
 #ifdef RESOURCE_TRACK
        if (ctx->options & E2F_OPT_TIME2)
-               print_resource_track(_("Byte swap"), &rtrack);
+               print_resource_track(_("Byte swap"), &rtrack, fs->io);
 #endif
 }
 
index 5a617d91cba0a9b75445e5b3eef393ffa65cb0d3..1809be49fbc49c3df352dc3e4786e7fcd6818d62 100644 (file)
@@ -883,7 +883,7 @@ int main (int argc, char *argv[])
        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)
@@ -1293,16 +1293,16 @@ no_journal:
        }
 
        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);
index f761ebba6380339b83616120d43d2cae8937819e..59a08b909486a9c6600a542b3d75274d13bd65ac 100644 (file)
@@ -276,11 +276,12 @@ void preenhalt(e2fsck_t ctx)
 }
 
 #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);
@@ -295,6 +296,14 @@ void init_resource_track(struct resource_track *track)
        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__
@@ -310,7 +319,8 @@ static _INLINE_ float timeval_subtract(struct timeval *tv1,
                ((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;
@@ -347,6 +357,26 @@ void print_resource_track(const char *desc, struct resource_track *track)
        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 */
 
index eada278ea6753b45f406f042717827921bd78f60..bee75a6a7730d1c80baf98418c6d4fc3e24deb65 100644 (file)
@@ -26,6 +26,7 @@ ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int);
 
 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
 
@@ -55,6 +56,13 @@ struct struct_io_channel {
        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;
@@ -70,6 +78,7 @@ struct struct_io_manager {
                                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];
 };
 
index 03d63ce13a9f8f9a4d737b2835532c94cdc7dbef..2fe10d24bdbf36c09d157b9d27eb561a878626ba 100644 (file)
@@ -66,6 +66,8 @@ static errcode_t test_write_byte(io_channel channel, unsigned long offset,
                                 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,
@@ -77,7 +79,8 @@ static struct struct_io_manager struct_test_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;
@@ -409,3 +412,18 @@ static errcode_t test_set_option(io_channel channel, const char *option,
        }
        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;
+}
index 4ede0009560254aa3b8f8f76f79b99a351badcca..8497a415a1ffb8f33929e9b8d62468eca7acb8b5 100644 (file)
@@ -70,6 +70,7 @@ struct unix_private_data {
        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);
@@ -84,7 +85,8 @@ static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
                                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);
 
@@ -110,11 +112,28 @@ static struct struct_io_manager struct_unix_manager = {
 #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
  */
@@ -130,6 +149,7 @@ static errcode_t raw_read_blk(io_channel channel,
        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;
@@ -168,6 +188,7 @@ static errcode_t raw_read_blk(io_channel channel,
        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",
@@ -224,6 +245,7 @@ static errcode_t raw_write_blk(io_channel channel,
                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) {
@@ -407,6 +429,7 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
 
        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;