@@ -1080,6 +1080,31 @@ struct ext4_super_block {
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
/*
+ * ext4 io statistics flags
+ */
+enum {
+ EXT4_IOS_SUPER_BLOCK = 0,
+ EXT4_IOS_GROUP_DESC,
+ EXT4_IOS_INODE_BITMAP,
+ EXT4_IOS_BLOCK_BITMAP,
+ EXT4_IOS_INODE_TABLE,
+ EXT4_IOS_EXTENT_BLOCK,
+ EXT4_IOS_INDIRECT_BLOCK,
+ EXT4_IOS_DIR_ENTRY,
+ EXT4_IOS_EXTENDED_ATTR,
+ EXT4_IOS_REGULAR_DATA,
+ EXT4_IOS_TYPE_END,
+};
+
+struct ext4_ios {
+ const char *function;
+ unsigned int line;
+ int rw;
+ int flag;
+ int count;
+};
+
+/*
* fourth extended-fs super-block data in memory
*/
struct ext4_sb_info {
@@ -1248,6 +1273,11 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
}
+static inline unsigned ext4_blocks_per_page(struct inode *inode)
+{
+ return PAGE_CACHE_SIZE >> inode->i_blkbits;
+}
+
/*
* Inode dynamic state flags
*/
@@ -1875,6 +1905,19 @@ extern int ext4_group_extend(struct super_block *sb,
ext4_fsblk_t n_blocks_count);
/* super.c */
+extern void __ext4_io_stat(const char *, unsigned int, int, int, unsigned long);
+extern void ext4_io_stat_read(void *ios);
+extern void ext4_io_stat_write(handle_t *, struct buffer_head *,
+ const char *, unsigned int,
+ int, unsigned long);
+extern void __ext4_init_ios(struct ios *ios, struct ext4_ios *ext4_ios,
+ const char *function, unsigned int line,
+ int rw, int flag, unsigned long count,
+ void (*io_stat)(void *));
+#define ext4_init_ios(ios, ext4_ios, flag) \
+ __ext4_init_ios(ios, ext4_ios, __func__, __LINE__, \
+ READ, flag, 1, ext4_io_stat_read)
+
extern void *ext4_kvmalloc(size_t size, gfp_t flags);
extern void *ext4_kvzalloc(size_t size, gfp_t flags);
extern void ext4_kvfree(void *ptr);
@@ -4851,6 +4851,86 @@ out:
#endif
+#define EXT4_IOS_DEBUG
+
+#ifdef EXT4_IOS_DEBUG
+#define ext4_ios_debug(f, a...) trace_printk(f, ##a)
+#else
+#define ext4_ios_debug(f, a...)
+#endif
+
+static DEFINE_PER_CPU(unsigned long [EXT4_IOS_TYPE_END][2], ext4_ios_counters);
+
+void ext4_io_stat_write(handle_t *handle, struct buffer_head *bh,
+ const char *function, unsigned int line,
+ int flag, unsigned long count)
+{
+ if (!bh)
+ goto write;
+
+ if (!handle || !ext4_handle_valid(handle)) {
+ if (buffer_dirty(bh))
+ return;
+ } else {
+ if (buffer_jbddirty(bh))
+ return;
+ }
+write:
+ __ext4_io_stat(function, line, WRITE, flag, count);
+}
+
+static inline unsigned long ext4_get_ios_counter(int rw, int flag)
+{
+ unsigned long sum = 0;
+ int i;
+
+ for_each_possible_cpu(i)
+ sum += per_cpu(ext4_ios_counters[flag][rw], i);
+
+ return sum;
+}
+
+void __ext4_io_stat(const char *function, unsigned int line,
+ int rw, int flag, unsigned long count)
+{
+ const char *rwstr = rw ? "write" : "read";
+ const char *typestr[EXT4_IOS_TYPE_END] = {
+ "super block", "group descriptor",
+ "inode bitmap", "block bitmap",
+ "inode table", "extent block",
+ "indirect block", "dir entry",
+ "extended attributes", "regular data"
+ };
+
+ BUG_ON(flag < 0 || flag >= EXT4_IOS_TYPE_END);
+ this_cpu_add(ext4_ios_counters[flag][rw], count);
+
+ ext4_ios_debug("%s:%d - %s %s - %ld block" " - total %s %ld block\n",
+ function, line, rwstr, typestr[flag], count, rwstr,
+ ext4_get_ios_counter(rw, flag));
+}
+
+void ext4_io_stat_read(void *data)
+{
+ struct ext4_ios *ext4_ios = data;
+ return __ext4_io_stat(ext4_ios->function, ext4_ios->line,
+ ext4_ios->rw, ext4_ios->flag, ext4_ios->count);
+}
+
+void __ext4_init_ios(struct ios *ios, struct ext4_ios *ext4_ios,
+ const char *function, unsigned int line,
+ int rw, int flag, unsigned long count,
+ void (*io_stat)(void *))
+{
+ ext4_ios->function = function;
+ ext4_ios->line = line;
+ ext4_ios->rw = rw;
+ ext4_ios->flag = flag;
+ ext4_ios->count = count;
+ ios->data = ext4_ios;
+ ios->io_stat = io_stat;
+}
+
static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
@@ -2676,5 +2676,13 @@ static inline void inode_has_no_xattr(struct inode *inode)
inode->i_flags |= S_NOSEC;
}
+/*
+ * IO statistics
+ */
+struct ios {
+ void *data;
+ void (*io_stat)(void *data);
+};
+
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */