linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/8] ext4: io type accouting
@ 2012-01-23 16:50 Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 1/8] ext4: add percpu counters and related functions to account io types Zheng Liu
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel; +Cc: Jens Axboe, Steven Whitehouse, Aditya Kali

Hi all,

Here is the fourth version of ext4 io type accouting. It can be used to
understand the detailed IO in ext4. It is closed by default when a device is
mounted. We can turn on/off it manually in sysfs. There has three files in
/sys/fs/ext4/${DEVICE}/. io_stats shows the result of accounting,
io_stats_enable can turn on/off accouting and io_stats_reset resets the
counters.  We can use 'echo 1 >/sys/fs/ext4/${DEVICE}/io_stats_enable' to turn
on accouting. Then we can read the result from io_stats file. It can displays
ten types, which are super block, group descritptor, inode bitmap, block bitmap,
inode table, extent block, indirect block, dir index and entry, xattr, and
regular data block. So we can precisely understand how many IOs are issued by
ext4. It can help us to improve the performance of applications and filesystems.
Meanwhile, we can type 'echo 1 > /sys/fs/ext4/${DEVICE}/io_stats_reset' to
reset counters.

Any comments or suggestions are appreciated. Thanks!

Changes since v3:
* Add io_stats_enable to turn on/off accouting. Now it is closed by
  default. If we need to use it, we can type the following command:
	$ echo 1 >/sys/fs/ext4/${DEVICE}/io_stats_enable
* Rebase to 3.3.

Changes since v2:
* Define wrapper function for io type accouting in ext4:
  submit_bh(), bh_submit_read(), sb_bread(), sb_breadahead() and ll_rw_blocK() 
  are replaced by these wrapper functions. In these wrapper functions, 
  percpu_couters are added to account the number of different IO requests which
  are issued to the disk.
* Add per-device counter: 
  The percpu_counter is moved into ext4_sb_info structure in order to supprt
  per-device accouting.
* Add io_stats_reset to reset counter:
  io_stats_reset file is created in /sys/fs/ext4/$DEVICE/. We can use 
  'echo 1 > /sys/fs/ext4/$DEVICE/io_stats_reset' command to reset counter.
* Add version information into io_stats:
  'Version' field is printed in io_stats in order to userspace tool can parse
  the format according to the current version.

Changes since v1:
* Totoally redisgn the implementation:
  A 'Issue' flag is added in buffer_head structure to let filesystem can check
  it and do related things.

Regards,
Zheng

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v4 1/8] ext4: add percpu counters and related functions to account io types.
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 2/8] ext4: add wrapper functions for buffer layer Zheng Liu
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

Add percpu counters in ext4_sb_info and related functions to save the result of
io types. IO types in ext4 are splitted as follows:

* Metadata:
 - super block
 - group descriptor
 - inode bitmap
 - block bitmap
 - inode table
 - extent block
 - indirect block
 - dir index and entry
 - extended attribute
* Data:
 - regular data block

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/ext4.h  |   37 +++++++++++++++++++++++++++++++++
 fs/ext4/super.c |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 513004f..7ec0596 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1118,6 +1118,23 @@ struct ext4_super_block {
 #define EXT4_MF_FS_ABORTED	0x0002	/* Fatal error detected */
 
 /*
+ * ext4 io types
+ */
+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,
+};
+
+/*
  * fourth extended-fs super-block data in memory
  */
 struct ext4_sb_info {
@@ -1259,6 +1276,9 @@ struct ext4_sb_info {
 
 	/* record the last minlen when FITRIM is called. */
 	atomic_t s_last_trim_minblks;
+
+	/* for io type accouting */
+	struct percpu_counter s_ios_counters[EXT4_IOS_TYPE_END][2];
 };
 
 static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -1294,6 +1314,11 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode,
 	}
 }
 
+static inline unsigned int ext4_blocks_per_page(struct inode *inode)
+{
+	return PAGE_CACHE_SIZE >> inode->i_blkbits;
+}
+
 /*
  * Inode dynamic state flags
  */
@@ -1931,6 +1956,18 @@ extern int ext4_group_extend(struct super_block *sb,
 extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 
 /* super.c */
+extern void __ext4_io_stat(struct super_block *sb, int rw,
+			   int type, unsigned long count);
+extern void ext4_ios_write(struct super_block *sb, handle_t *handle,
+			   struct buffer_head *bh, int type,
+			   unsigned long count);
+
+static inline void ext4_ios_read(struct super_block *sb, int type,
+				 unsigned long count)
+{
+	__ext4_io_stat(sb, READ, type, count);
+}
+
 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);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 502c61f..f3a5cab 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -842,6 +842,10 @@ static void ext4_put_super(struct super_block *sb)
 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
 	percpu_counter_destroy(&sbi->s_dirs_counter);
 	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
+		percpu_counter_destroy(&sbi->s_ios_counters[i][READ]);
+		percpu_counter_destroy(&sbi->s_ios_counters[i][WRITE]);
+	}
 	brelse(sbi->s_sbh);
 #ifdef CONFIG_QUOTA
 	for (i = 0; i < MAXQUOTAS; i++)
@@ -3153,6 +3157,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	}
 
 	/*
+	 * Note: s_ios_counters must be initialized as soon as possible becuase
+	 *       ext4 io type accouting depends on it
+	 */
+	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
+		if (percpu_counter_init(&sbi->s_ios_counters[i][READ], 0))
+			goto out_init_ios;
+		if (percpu_counter_init(&sbi->s_ios_counters[i][WRITE], 0))
+			goto out_init_ios;
+	}
+	/*
 	 * The ext4 superblock will not be buffer aligned for other than 1kB
 	 * block sizes.  We need to calculate the offset from buffer start.
 	 */
@@ -3874,6 +3888,11 @@ out_fail:
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
+out_init_ios:
+	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
+		percpu_counter_destroy(&sbi->s_ios_counters[i][READ]);
+		percpu_counter_destroy(&sbi->s_ios_counters[i][WRITE]);
+	}
 out_free_orig:
 	kfree(orig_data);
 	return ret;
@@ -4939,6 +4958,47 @@ out:
 
 #endif
 
+static inline u64 ext4_get_ios_counter(struct ext4_sb_info *sbi,
+					int rw, int type)
+{
+	return percpu_counter_sum(&sbi->s_ios_counters[type][rw]);
+}
+
+static inline void ext4_reset_ios_counter(struct ext4_sb_info *sbi)
+{
+	int i;
+
+	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
+		percpu_counter_set(&sbi->s_ios_counters[i][READ], 0);
+		percpu_counter_set(&sbi->s_ios_counters[i][WRITE], 0);
+	}
+}
+
+void __ext4_io_stat(struct super_block *sb, int rw,
+		    int type, unsigned long count)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+	BUG_ON(type < 0 || type >= EXT4_IOS_TYPE_END);
+	percpu_counter_add(&sbi->s_ios_counters[type][rw], count);
+}
+
+void ext4_ios_write(struct super_block *sb, handle_t *handle,
+		    struct buffer_head *bh, int type, unsigned long count)
+{
+	if (!bh)
+		goto count;
+	if (!handle || !ext4_handle_valid(handle)) {
+		if (buffer_dirty(bh))
+			return;
+	} else {
+		if (buffer_jbddirty(bh))
+			return;
+	}
+count:
+	__ext4_io_stat(sb, WRITE, type, count);
+}
+
 static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
 		       const char *dev_name, void *data)
 {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 2/8] ext4: add wrapper functions for buffer layer
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 1/8] ext4: add percpu counters and related functions to account io types Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 3/8] ext4: account the metadata request of read operations in buffered io Zheng Liu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

Wrapper functions are defined to account the result of different IO type.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/ext4.h  |   21 +++++++++++++++
 fs/ext4/super.c |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 7ec0596..688891e 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1968,6 +1968,27 @@ static inline void ext4_ios_read(struct super_block *sb, int type,
 	__ext4_io_stat(sb, READ, type, count);
 }
 
+extern void ext4_submit_bh_read_nowait(int rw, struct buffer_head *bh,
+				       struct super_block *sb, int type,
+				       unsigned long count);
+extern int ext4_submit_bh_read(int rw, struct buffer_head *bh,
+			       struct super_block *sb, int type,
+			       unsigned long count);
+extern void ext4_submit_bh_write_nowait(int rw, struct buffer_head *bh,
+					struct super_block *sb, int type,
+					unsigned long count);
+extern struct buffer_head *ext4_sb_bread(struct super_block *sb, sector_t block,
+					 int type, unsigned long count);
+extern void ext4_sb_breadahead(struct super_block *sb,
+			       sector_t block, int type);
+
+static inline int ext4_bh_submit_read(struct buffer_head *bh,
+				      struct super_block *sb,
+				      int type, unsigned long count)
+{
+	return ext4_submit_bh_read(READ, bh, sb, type, count);
+}
+
 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);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f3a5cab..305ece7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4999,6 +4999,84 @@ count:
 	__ext4_io_stat(sb, WRITE, type, count);
 }
 
+void ext4_submit_bh_read_nowait(int rw, struct buffer_head *bh,
+				struct super_block *sb, int type,
+				unsigned long count)
+{
+	BUG_ON(rw & WRITE);
+	BUG_ON(!buffer_locked(bh));
+
+	/* IO type accouting */
+	ext4_ios_read(sb, type, count);
+
+	get_bh(bh);
+	bh->b_end_io = end_buffer_read_sync;
+	submit_bh(rw, bh);
+}
+
+int ext4_submit_bh_read(int rw, struct buffer_head *bh, struct super_block *sb,
+			int type, unsigned long count)
+{
+	BUG_ON(rw & WRITE);
+	BUG_ON(!buffer_locked(bh));
+
+	if (buffer_uptodate(bh)) {
+		unlock_buffer(bh);
+		return 0;
+	}
+
+	ext4_submit_bh_read_nowait(rw, bh, sb, type, count);
+	wait_on_buffer(bh);
+	if (buffer_uptodate(bh))
+		return 0;
+	return -EIO;
+}
+
+void ext4_submit_bh_write_nowait(int rw, struct buffer_head *bh,
+				 struct super_block *sb, int type,
+				 unsigned long count)
+{
+	BUG_ON(!(rw & WRITE));
+	BUG_ON(!buffer_locked(bh));
+
+	/* IO type accouting */
+	ext4_ios_write(sb, NULL, NULL, type, count);
+
+	get_bh(bh);
+	bh->b_end_io = end_buffer_write_sync;
+	submit_bh(rw, bh);
+}
+
+struct buffer_head *ext4_sb_bread(struct super_block *sb, sector_t block,
+				  int type, unsigned long count)
+{
+	struct buffer_head *bh = __getblk(sb->s_bdev, block, sb->s_blocksize);
+
+	if (likely(bh) && !buffer_uptodate(bh)) {
+		lock_buffer(bh);
+		if (ext4_submit_bh_read(READ, bh, sb, type, count)) {
+			brelse(bh);
+			bh = NULL;
+		}
+	}
+	return bh;
+}
+
+void ext4_sb_breadahead(struct super_block *sb, sector_t block, int type)
+{
+	struct buffer_head *bh = __getblk(sb->s_bdev, block, sb->s_blocksize);
+	if (likely(bh)) {
+		if (trylock_buffer(bh)) {
+			if (buffer_uptodate(bh))
+				ext4_submit_bh_read_nowait(READ, bh, sb,
+							   type, 1);
+			else
+				unlock_buffer(bh);
+		}
+		brelse(bh);
+	}
+}
+
 static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
 		       const char *dev_name, void *data)
 {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 3/8] ext4: account the metadata request of read operations in buffered io
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 1/8] ext4: add percpu counters and related functions to account io types Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 2/8] ext4: add wrapper functions for buffer layer Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 4/8] ext4: account the data " Zheng Liu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

We replace all the call to the buffer layer with wrapper functions we defined.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/balloc.c      |    2 +-
 fs/ext4/extents.c     |   11 +++++++----
 fs/ext4/ialloc.c      |    2 +-
 fs/ext4/indirect.c    |    6 ++++--
 fs/ext4/inode.c       |   17 +++++++----------
 fs/ext4/mballoc.c     |    5 ++---
 fs/ext4/move_extent.c |    8 +++++---
 fs/ext4/namei.c       |    7 ++++---
 fs/ext4/super.c       |    9 ++++++---
 fs/ext4/xattr.c       |   18 ++++++++++++------
 10 files changed, 49 insertions(+), 36 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index f9e2cd8..6768a03 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -389,7 +389,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
 	 */
 	trace_ext4_read_block_bitmap_load(sb, block_group);
 	set_bitmap_uptodate(bh);
-	if (bh_submit_read(bh) < 0) {
+	if (ext4_bh_submit_read(bh, sb, EXT4_IOS_BLOCK_BITMAP, 1) < 0) {
 		put_bh(bh);
 		ext4_error(sb, "Cannot read block bitmap - "
 			    "block_group = %u, block_bitmap = %llu",
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 74f23c2..a26423f 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -667,7 +667,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		if (!bh_uptodate_or_lock(bh)) {
 			trace_ext4_ext_load_extent(inode, block,
 						path[ppos].p_block);
-			if (bh_submit_read(bh) < 0) {
+			if (ext4_bh_submit_read(bh, inode->i_sb,
+				EXT4_IOS_EXTENT_BLOCK, 1) < 0) {
 				put_bh(bh);
 				goto err;
 			}
@@ -1322,7 +1323,8 @@ got_index:
 	ix++;
 	block = ext4_idx_pblock(ix);
 	while (++depth < path->p_depth) {
-		bh = sb_bread(inode->i_sb, block);
+		bh = ext4_sb_bread(inode->i_sb, block,
+				   EXT4_IOS_EXTENT_BLOCK, 1);
 		if (bh == NULL)
 			return -EIO;
 		eh = ext_block_hdr(bh);
@@ -1336,7 +1338,7 @@ got_index:
 		put_bh(bh);
 	}
 
-	bh = sb_bread(inode->i_sb, block);
+	bh = ext4_sb_bread(inode->i_sb, block, EXT4_IOS_EXTENT_BLOCK, 1);
 	if (bh == NULL)
 		return -EIO;
 	eh = ext_block_hdr(bh);
@@ -2561,7 +2563,8 @@ again:
 			ext_debug("move to level %d (block %llu)\n",
 				  i + 1, ext4_idx_pblock(path[i].p_idx));
 			memset(path + i + 1, 0, sizeof(*path));
-			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
+			bh = ext4_sb_bread(sb, ext4_idx_pblock(path[i].p_idx),
+					   EXT4_IOS_EXTENT_BLOCK, 1);
 			if (!bh) {
 				/* should we reset i_size? */
 				err = -EIO;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 25d8c97..7edc9c0 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -154,7 +154,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
 	 */
 	trace_ext4_load_inode_bitmap(sb, block_group);
 	set_bitmap_uptodate(bh);
-	if (bh_submit_read(bh) < 0) {
+	if (ext4_bh_submit_read(bh, sb, EXT4_IOS_INODE_BITMAP, 1) < 0) {
 		put_bh(bh);
 		ext4_error(sb, "Cannot read inode bitmap - "
 			    "block_group = %u, inode_bitmap = %llu",
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 830e1b2..f0219fa 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -157,7 +157,8 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
 			goto failure;
 
 		if (!bh_uptodate_or_lock(bh)) {
-			if (bh_submit_read(bh) < 0) {
+			if (ext4_bh_submit_read(bh, sb,
+			    EXT4_IOS_INDIRECT_BLOCK, 1) < 0) {
 				put_bh(bh);
 				goto failure;
 			}
@@ -1253,7 +1254,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 			}
 
 			/* Go read the buffer for the next level down */
-			bh = sb_bread(inode->i_sb, nr);
+			bh = ext4_sb_bread(inode->i_sb, nr,
+					   EXT4_IOS_INDIRECT_BLOCK, 1);
 
 			/*
 			 * A read failure? Report error and clear slot
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index feaa82f..b68d129 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -699,11 +699,10 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
 	bh = ext4_getblk(handle, inode, block, create, err);
 	if (!bh)
 		return bh;
-	if (buffer_uptodate(bh))
+	if (bh_uptodate_or_lock(bh))
 		return bh;
-	ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
-	wait_on_buffer(bh);
-	if (buffer_uptodate(bh))
+	if (!ext4_submit_bh_read(READ | REQ_META | REQ_PRIO, bh, inode->i_sb,
+				 EXT4_IOS_DIR_ENTRY, 1))
 		return bh;
 	put_bh(bh);
 	*err = -EIO;
@@ -3513,7 +3512,8 @@ make_io:
 			if (end > table)
 				end = table;
 			while (b <= end)
-				sb_breadahead(sb, b++);
+				ext4_sb_breadahead(sb, b++,
+					EXT4_IOS_INODE_TABLE);
 		}
 
 		/*
@@ -3522,11 +3522,8 @@ make_io:
 		 * Read the block from disk.
 		 */
 		trace_ext4_load_inode(inode);
-		get_bh(bh);
-		bh->b_end_io = end_buffer_read_sync;
-		submit_bh(READ | REQ_META | REQ_PRIO, bh);
-		wait_on_buffer(bh);
-		if (!buffer_uptodate(bh)) {
+		if (ext4_submit_bh_read(READ | REQ_META | REQ_PRIO, bh, sb,
+					EXT4_IOS_INODE_TABLE, 1)) {
 			EXT4_ERROR_INODE_BLOCK(inode, block,
 					       "unable to read itable block");
 			brelse(bh);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index cb990b2..f9bc9eb 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -873,7 +873,6 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
 			unlock_buffer(bh[i]);
 			continue;
 		}
-		get_bh(bh[i]);
 		/*
 		 * submit the buffer_head for read. We can
 		 * safely mark the bitmap as uptodate now.
@@ -881,8 +880,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
 		 * get set with buffer lock held.
 		 */
 		set_bitmap_uptodate(bh[i]);
-		bh[i]->b_end_io = end_buffer_read_sync;
-		submit_bh(READ, bh[i]);
+		ext4_submit_bh_read_nowait(READ, bh[i], sb,
+					EXT4_IOS_BLOCK_BITMAP, 1);
 		mb_debug(1, "read bitmap for group %u\n", first_group + i);
 	}
 
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index c5826c6..c1d2d3a 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -99,7 +99,8 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
 			if (path[ppos+1].p_bh)
 				brelse(path[ppos+1].p_bh);
 			path[ppos+1].p_bh =
-				sb_bread(inode->i_sb, path[ppos].p_block);
+				ext4_sb_bread(inode->i_sb, path[ppos].p_block,
+					      EXT4_IOS_EXTENT_BLOCK, 1);
 			if (!path[ppos+1].p_bh)
 				return -EIO;
 			path[ppos+1].p_hdr =
@@ -113,8 +114,9 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
 					ext4_idx_pblock(path[cur_ppos].p_idx);
 				if (path[cur_ppos+1].p_bh)
 					brelse(path[cur_ppos+1].p_bh);
-				path[cur_ppos+1].p_bh = sb_bread(inode->i_sb,
-					path[cur_ppos].p_block);
+				path[cur_ppos+1].p_bh = ext4_sb_bread(
+					inode->i_sb, path[cur_ppos].p_block,
+					EXT4_IOS_EXTENT_BLOCK, 1);
 				if (!path[cur_ppos+1].p_bh)
 					return -EIO;
 				path[cur_ppos+1].p_hdr =
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2043f48..4508257 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -921,9 +921,10 @@ restart:
 				num++;
 				bh = ext4_getblk(NULL, dir, b++, 0, &err);
 				bh_use[ra_max] = bh;
-				if (bh)
-					ll_rw_block(READ | REQ_META | REQ_PRIO,
-						    1, &bh);
+				if (bh && !bh_uptodate_or_lock(bh))
+					ext4_submit_bh_read_nowait(
+						READ | REQ_META | REQ_PRIO,
+						bh, sb, EXT4_IOS_DIR_ENTRY, 1);
 			}
 		}
 		if ((bh = bh_use[ra_ptr++]) == NULL)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 305ece7..f6f4a0f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3177,7 +3177,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		logical_sb_block = sb_block;
 	}
 
-	if (!(bh = sb_bread(sb, logical_sb_block))) {
+	if (!(bh = ext4_sb_bread(sb, logical_sb_block,
+				 EXT4_IOS_SUPER_BLOCK, 1))) {
 		ext4_msg(sb, KERN_ERR, "unable to read superblock");
 		goto out_fail;
 	}
@@ -3349,7 +3350,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		brelse(bh);
 		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
 		offset = do_div(logical_sb_block, blocksize);
-		bh = sb_bread(sb, logical_sb_block);
+		bh = ext4_sb_bread(sb, logical_sb_block,
+				EXT4_IOS_SUPER_BLOCK, 1);
 		if (!bh) {
 			ext4_msg(sb, KERN_ERR,
 			       "Can't read superblock on 2nd try");
@@ -3558,7 +3560,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 
 	for (i = 0; i < db_count; i++) {
 		block = descriptor_loc(sb, logical_sb_block, i);
-		sbi->s_group_desc[i] = sb_bread(sb, block);
+		sbi->s_group_desc[i] = ext4_sb_bread(sb, block,
+					EXT4_IOS_GROUP_DESC, 1);
 		if (!sbi->s_group_desc[i]) {
 			ext4_msg(sb, KERN_ERR,
 			       "can't read group descriptor %d", i);
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 93a00d8..a7b393f 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -221,7 +221,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
 	if (!EXT4_I(inode)->i_file_acl)
 		goto cleanup;
 	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl,
+				EXT4_IOS_EXTENDED_ATTR, 1);
 	if (!bh)
 		goto cleanup;
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
@@ -364,7 +365,8 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 	if (!EXT4_I(inode)->i_file_acl)
 		goto cleanup;
 	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl,
+				EXT4_IOS_EXTENDED_ATTR, 1);
 	error = -EIO;
 	if (!bh)
 		goto cleanup;
@@ -655,7 +657,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
 
 	if (EXT4_I(inode)->i_file_acl) {
 		/* The inode already has an extended attribute block. */
-		bs->bh = sb_bread(sb, EXT4_I(inode)->i_file_acl);
+		bs->bh = ext4_sb_bread(sb, EXT4_I(inode)->i_file_acl,
+					EXT4_IOS_EXTENDED_ATTR, 1);
 		error = -EIO;
 		if (!bs->bh)
 			goto cleanup;
@@ -1188,7 +1191,8 @@ retry:
 	 * EA block can hold new_extra_isize bytes.
 	 */
 	if (EXT4_I(inode)->i_file_acl) {
-		bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl,
+					EXT4_IOS_EXTENDED_ATTR, 1);
 		error = -EIO;
 		if (!bh)
 			goto cleanup;
@@ -1369,7 +1373,8 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
 
 	if (!EXT4_I(inode)->i_file_acl)
 		goto cleanup;
-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl,
+				EXT4_IOS_EXTENDED_ATTR, 1);
 	if (!bh) {
 		EXT4_ERROR_INODE(inode, "block %llu read error",
 				 EXT4_I(inode)->i_file_acl);
@@ -1501,7 +1506,8 @@ again:
 				goto again;
 			break;
 		}
-		bh = sb_bread(inode->i_sb, ce->e_block);
+		bh = ext4_sb_bread(inode->i_sb, ce->e_block,
+					EXT4_IOS_EXTENDED_ATTR, 1);
 		if (!bh) {
 			EXT4_ERROR_INODE(inode, "block %lu read error",
 					 (unsigned long) ce->e_block);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 4/8] ext4: account the data request of read operations in buffered io
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
                   ` (2 preceding siblings ...)
  2012-01-23 16:50 ` [PATCH v4 3/8] ext4: account the metadata request of read operations in buffered io Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 5/8] ext4: account the metadata request of write " Zheng Liu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

ll_rw_block in ext4_discard_partial_page_buffers_no_lock is replaced with
ext4_submit_bh_read, and ext4_ios_read are called in ext4_readpage and
ext4_readpages in order to account the data request.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/inode.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b68d129..ff56658 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2665,6 +2665,8 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
 static int ext4_readpage(struct file *file, struct page *page)
 {
 	trace_ext4_readpage(page);
+	ext4_ios_read(page->mapping->host->i_sb, EXT4_IOS_REGULAR_DATA,
+		      ext4_blocks_per_page(page->mapping->host));
 	return mpage_readpage(page, ext4_get_block);
 }
 
@@ -2672,6 +2674,8 @@ static int
 ext4_readpages(struct file *file, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
+	ext4_ios_read(mapping->host->i_sb, EXT4_IOS_REGULAR_DATA,
+		      ext4_blocks_per_page(mapping->host));
 	return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
@@ -3268,12 +3272,12 @@ static int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
 		if (PageUptodate(page))
 			set_buffer_uptodate(bh);
 
-		if (!buffer_uptodate(bh)) {
-			err = -EIO;
-			ll_rw_block(READ, 1, &bh);
-			wait_on_buffer(bh);
+		if (!bh_uptodate_or_lock(bh)) {
+			err = ext4_submit_bh_read(READ, bh, inode->i_sb,
+						  EXT4_IOS_REGULAR_DATA,
+						  ext4_blocks_per_page(inode));
 			/* Uhhuh. Read error. Complain and punt.*/
-			if (!buffer_uptodate(bh))
+			if (err)
 				goto next;
 		}
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 5/8] ext4: account the metadata request of write operations in buffered io
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
                   ` (3 preceding siblings ...)
  2012-01-23 16:50 ` [PATCH v4 4/8] ext4: account the data " Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 6/8] ext4: account the data " Zheng Liu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

ext4_ios_write is used to account metadata request of write in buffered io.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/extents.c     |    6 ++++++
 fs/ext4/ialloc.c      |    8 ++++++++
 fs/ext4/indirect.c    |   15 +++++++++++++--
 fs/ext4/inode.c       |    4 ++++
 fs/ext4/mballoc.c     |    7 +++++++
 fs/ext4/move_extent.c |    2 ++
 fs/ext4/namei.c       |   19 +++++++++++++++++++
 fs/ext4/super.c       |    2 ++
 fs/ext4/xattr.c       |   11 ++++++++++-
 9 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a26423f..1f0938a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -105,6 +105,8 @@ static int __ext4_ext_dirty(const char *where, unsigned int line,
 		/* path points to block */
 		err = __ext4_handle_dirty_metadata(where, line, handle,
 						   inode, path->p_bh);
+		ext4_ios_write(inode->i_sb, handle, path->p_bh,
+				EXT4_IOS_EXTENT_BLOCK, 1);
 	} else {
 		/* path points to leaf/index in inode body */
 		err = ext4_mark_inode_dirty(handle, inode);
@@ -901,6 +903,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 	set_buffer_uptodate(bh);
 	unlock_buffer(bh);
 
+	ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_EXTENT_BLOCK, 1);
 	err = ext4_handle_dirty_metadata(handle, inode, bh);
 	if (err)
 		goto cleanup;
@@ -979,6 +982,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
 
+		ext4_ios_write(inode->i_sb, handle, bh,
+				EXT4_IOS_EXTENT_BLOCK, 1);
 		err = ext4_handle_dirty_metadata(handle, inode, bh);
 		if (err)
 			goto cleanup;
@@ -1076,6 +1081,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	set_buffer_uptodate(bh);
 	unlock_buffer(bh);
 
+	ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_EXTENT_BLOCK, 1);
 	err = ext4_handle_dirty_metadata(handle, inode, bh);
 	if (err)
 		goto out;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 7edc9c0..88424c5 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -277,10 +277,12 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
 			atomic_dec(&sbi->s_flex_groups[f].used_dirs);
 	}
 	BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
+	ext4_ios_write(sb, handle, bh2, EXT4_IOS_GROUP_DESC, 1);
 	fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
 out:
 	if (cleared) {
 		BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(sb, handle, bitmap_bh, EXT4_IOS_INODE_BITMAP, 1);
 		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 		if (!fatal)
 			fatal = err;
@@ -776,6 +778,8 @@ repeat_in_this_group:
 				/* we won it */
 				BUFFER_TRACE(inode_bitmap_bh,
 					"call ext4_handle_dirty_metadata");
+				ext4_ios_write(sb, handle, inode_bitmap_bh,
+						EXT4_IOS_INODE_BITMAP, 1);
 				err = ext4_handle_dirty_metadata(handle,
 								 NULL,
 							inode_bitmap_bh);
@@ -821,6 +825,8 @@ got:
 		}
 
 		BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+		ext4_ios_write(sb, handle, block_bitmap_bh,
+				EXT4_IOS_BLOCK_BITMAP, 1);
 		err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
 		brelse(block_bitmap_bh);
 
@@ -839,6 +845,7 @@ got:
 			goto fail;
 	}
 	BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
+	ext4_ios_write(sb, handle, group_desc_bh, EXT4_IOS_GROUP_DESC, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
 	if (err)
 		goto fail;
@@ -1191,6 +1198,7 @@ skip_zeroout:
 
 	BUFFER_TRACE(group_desc_bh,
 		     "call ext4_handle_dirty_metadata");
+	ext4_ios_write(sb, handle, group_desc_bh, EXT4_IOS_GROUP_DESC, 1);
 	ret = ext4_handle_dirty_metadata(handle, NULL,
 					 group_desc_bh);
 
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index f0219fa..8f9bfd2 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -505,6 +505,8 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 		unlock_buffer(bh);
 
 		BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(inode->i_sb, handle, bh,
+				EXT4_IOS_INDIRECT_BLOCK, 1);
 		err = ext4_handle_dirty_metadata(handle, inode, bh);
 		if (err)
 			goto failed;
@@ -592,6 +594,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
 		 */
 		jbd_debug(5, "splicing indirect only\n");
 		BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(inode->i_sb, handle, where->bh,
+				EXT4_IOS_INDIRECT_BLOCK, 1);
 		err = ext4_handle_dirty_metadata(handle, inode, where->bh);
 		if (err)
 			goto err_out;
@@ -1092,6 +1096,8 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
 	if (try_to_extend_transaction(handle, inode)) {
 		if (bh) {
 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+			ext4_ios_write(inode->i_sb, handle, bh,
+					EXT4_IOS_INDIRECT_BLOCK, 1);
 			err = ext4_handle_dirty_metadata(handle, inode, bh);
 			if (unlikely(err))
 				goto out_err;
@@ -1202,9 +1208,11 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
 		 * block pointed to itself, it would have been detached when
 		 * the block was cleared. Check for this instead of OOPSing.
 		 */
-		if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
+		if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh)) {
+			ext4_ios_write(inode->i_sb, handle, this_bh,
+					EXT4_IOS_INDIRECT_BLOCK, 1);
 			ext4_handle_dirty_metadata(handle, inode, this_bh);
-		else
+		} else
 			EXT4_ERROR_INODE(inode,
 					 "circular indirect block detected at "
 					 "block %llu",
@@ -1325,6 +1333,9 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 					*p = 0;
 					BUFFER_TRACE(parent_bh,
 					"call ext4_handle_dirty_metadata");
+					ext4_ios_write(inode->i_sb, handle,
+						parent_bh,
+						EXT4_IOS_INDIRECT_BLOCK, 1);
 					ext4_handle_dirty_metadata(handle,
 								   inode,
 								   parent_bh);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ff56658..176977a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -677,6 +677,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
 		}
 		unlock_buffer(bh);
 		BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_DIR_ENTRY, 1);
 		err = ext4_handle_dirty_metadata(handle, inode, bh);
 		if (!fatal)
 			fatal = err;
@@ -3927,6 +3928,8 @@ static int ext4_do_update_inode(handle_t *handle,
 					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
 			sb->s_dirt = 1;
 			ext4_handle_sync(handle);
+			ext4_ios_write(inode->i_sb, handle, EXT4_SB(sb)->s_sbh,
+					EXT4_IOS_SUPER_BLOCK, 1);
 			err = ext4_handle_dirty_metadata(handle, NULL,
 					EXT4_SB(sb)->s_sbh);
 		}
@@ -3956,6 +3959,7 @@ static int ext4_do_update_inode(handle_t *handle,
 	}
 
 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+	ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_INODE_TABLE, 1);
 	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
 	if (!err)
 		err = rc;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index f9bc9eb..f09416c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2823,6 +2823,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 		ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
 			      ac->ac_b_ex.fe_len);
 		ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
+		ext4_ios_write(sb, handle, bitmap_bh, EXT4_IOS_BLOCK_BITMAP, 1);
 		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 		if (!err)
 			err = -EAGAIN;
@@ -2868,9 +2869,11 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 			   &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
+	ext4_ios_write(sb, handle, bitmap_bh, EXT4_IOS_BLOCK_BITMAP, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 	if (err)
 		goto out_err;
+	ext4_ios_write(sb, handle, gdp_bh, EXT4_IOS_GROUP_DESC, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh);
 
 out_err:
@@ -4734,10 +4737,12 @@ do_more:
 
 	/* We dirtied the bitmap block */
 	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
+	ext4_ios_write(sb, handle, bitmap_bh, EXT4_IOS_BLOCK_BITMAP, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 
 	/* And the group descriptor block */
 	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+	ext4_ios_write(sb, handle, gd_bh, EXT4_IOS_GROUP_DESC, 1);
 	ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
 	if (!err)
 		err = ret;
@@ -4874,10 +4879,12 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 
 	/* We dirtied the bitmap block */
 	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
+	ext4_ios_write(sb, handle, bitmap_bh, EXT4_IOS_BLOCK_BITMAP, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 
 	/* And the group descriptor block */
 	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+	ext4_ios_write(sb, handle, gd_bh, EXT4_IOS_GROUP_DESC, 1);
 	ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
 	if (!err)
 		err = ret;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index c1d2d3a..8807abc 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -441,6 +441,8 @@ mext_insert_extents(handle_t *handle, struct inode *orig_inode,
 						end_ext, eh, range_to_move);
 
 	if (depth) {
+		ext4_ios_write(orig_inode->i_sb, handle, orig_path->p_bh,
+				EXT4_IOS_EXTENT_BLOCK, 1);
 		ret = ext4_handle_dirty_metadata(handle, orig_inode,
 						 orig_path->p_bh);
 		if (ret)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4508257..a4f83f2 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1222,9 +1222,11 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 		de = de2;
 	}
 	dx_insert_block(frame, hash2 + continued, newblock);
+	ext4_ios_write(dir->i_sb, handle, bh2, EXT4_IOS_DIR_ENTRY, 1);
 	err = ext4_handle_dirty_metadata(handle, dir, bh2);
 	if (err)
 		goto journal_error;
+	ext4_ios_write(dir->i_sb, handle, frame->bh, EXT4_IOS_DIR_ENTRY, 1);
 	err = ext4_handle_dirty_metadata(handle, dir, frame->bh);
 	if (err)
 		goto journal_error;
@@ -1322,6 +1324,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 	dir->i_version++;
 	ext4_mark_inode_dirty(handle, dir);
 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+	ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_DIR_ENTRY, 1);
 	err = ext4_handle_dirty_metadata(handle, dir, bh);
 	if (err)
 		ext4_std_error(dir->i_sb, err);
@@ -1412,7 +1415,9 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 	frame->bh = bh;
 	bh = bh2;
 
+	ext4_ios_write(inode->i_sb, handle, frame->bh, EXT4_IOS_DIR_ENTRY, 1);
 	ext4_handle_dirty_metadata(handle, dir, frame->bh);
+	ext4_ios_write(inode->i_sb, handle, bh, EXT4_IOS_DIR_ENTRY, 1);
 	ext4_handle_dirty_metadata(handle, dir, bh);
 
 	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
@@ -1587,6 +1592,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			dxtrace(dx_show_index("node", frames[1].entries));
 			dxtrace(dx_show_index("node",
 			       ((struct dx_node *) bh2->b_data)->entries));
+			ext4_ios_write(inode->i_sb, handle, bh2,
+					EXT4_IOS_DIR_ENTRY, 1);
 			err = ext4_handle_dirty_metadata(handle, dir, bh2);
 			if (err)
 				goto journal_error;
@@ -1613,6 +1620,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			if (err)
 				goto journal_error;
 		}
+		ext4_ios_write(inode->i_sb, handle, frames[0].bh,
+				EXT4_IOS_DIR_ENTRY, 1);
 		err = ext4_handle_dirty_metadata(handle, dir, frames[0].bh);
 		if (err) {
 			ext4_std_error(inode->i_sb, err);
@@ -1671,6 +1680,8 @@ static int ext4_delete_entry(handle_t *handle,
 				de->inode = 0;
 			dir->i_version++;
 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+			ext4_ios_write(dir->i_sb, handle, bh,
+					EXT4_IOS_DIR_ENTRY, 1);
 			err = ext4_handle_dirty_metadata(handle, dir, bh);
 			if (unlikely(err)) {
 				ext4_std_error(dir->i_sb, err);
@@ -1863,6 +1874,7 @@ retry:
 	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
 	set_nlink(inode, 2);
 	BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
+	ext4_ios_write(inode->i_sb, handle, dir_block, EXT4_IOS_DIR_ENTRY, 1);
 	err = ext4_handle_dirty_metadata(handle, inode, dir_block);
 	if (err)
 		goto out_clear_inode;
@@ -2014,6 +2026,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
 	/* Insert this inode at the head of the on-disk orphan list... */
 	NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan);
 	EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+	ext4_ios_write(sb, handle, EXT4_SB(sb)->s_sbh, EXT4_IOS_DIR_ENTRY, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
 	rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
 	if (!err)
@@ -2087,6 +2100,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
 		if (err)
 			goto out_brelse;
 		sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+		ext4_ios_write(inode->i_sb, handle, sbi->s_sbh,
+				EXT4_IOS_SUPER_BLOCK, 1);
 		err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
 	} else {
 		struct ext4_iloc iloc2;
@@ -2476,6 +2491,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 					ext4_current_time(new_dir);
 		ext4_mark_inode_dirty(handle, new_dir);
 		BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(old_dir->i_sb, handle, new_bh,
+				EXT4_IOS_DIR_ENTRY, 1);
 		retval = ext4_handle_dirty_metadata(handle, new_dir, new_bh);
 		if (unlikely(retval)) {
 			ext4_std_error(new_dir->i_sb, retval);
@@ -2530,6 +2547,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) =
 						cpu_to_le32(new_dir->i_ino);
 		BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata");
+		ext4_ios_write(old_dir->i_sb, handle, dir_bh,
+				EXT4_IOS_DIR_ENTRY, 1);
 		retval = ext4_handle_dirty_metadata(handle, old_inode, dir_bh);
 		if (retval) {
 			ext4_std_error(old_dir->i_sb, retval);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f6f4a0f..7aee0dd 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4206,6 +4206,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
 				&EXT4_SB(sb)->s_freeinodes_counter));
 	sb->s_dirt = 0;
 	BUFFER_TRACE(sbh, "marking dirty");
+	ext4_ios_write(sb, NULL, sbh, EXT4_IOS_SUPER_BLOCK, 1);
 	mark_buffer_dirty(sbh);
 	if (sync) {
 		error = sync_dirty_buffer(sbh);
@@ -4943,6 +4944,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
 	memcpy(bh->b_data+offset, data, len);
 	flush_dcache_page(bh->b_page);
 	unlock_buffer(bh);
+	ext4_ios_write(sb, handle, bh, EXT4_IOS_SUPER_BLOCK, 1);
 	err = ext4_handle_dirty_metadata(handle, NULL, bh);
 	brelse(bh);
 out:
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index a7b393f..7bb3258 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -491,6 +491,8 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
 				 EXT4_FREE_BLOCKS_FORGET);
 	} else {
 		le32_add_cpu(&BHDR(bh)->h_refcount, -1);
+		ext4_ios_write(inode->i_sb, handle, bh,
+				EXT4_IOS_EXTENDED_ATTR, 1);
 		error = ext4_handle_dirty_metadata(handle, inode, bh);
 		if (IS_SYNC(inode))
 			ext4_handle_sync(handle);
@@ -727,10 +729,13 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
 			unlock_buffer(bs->bh);
 			if (error == -EIO)
 				goto bad_block;
-			if (!error)
+			if (!error) {
+				ext4_ios_write(sb, handle, bs->bh,
+					EXT4_IOS_EXTENDED_ATTR, 1);
 				error = ext4_handle_dirty_metadata(handle,
 								   inode,
 								   bs->bh);
+			}
 			if (error)
 				goto cleanup;
 			goto inserted;
@@ -799,6 +804,8 @@ inserted:
 				ea_bdebug(new_bh, "reusing; refcount now=%d",
 					le32_to_cpu(BHDR(new_bh)->h_refcount));
 				unlock_buffer(new_bh);
+				ext4_ios_write(sb, handle, new_bh,
+						EXT4_IOS_EXTENDED_ATTR, 1);
 				error = ext4_handle_dirty_metadata(handle,
 								   inode,
 								   new_bh);
@@ -857,6 +864,8 @@ getblk_failed:
 			set_buffer_uptodate(new_bh);
 			unlock_buffer(new_bh);
 			ext4_xattr_cache_insert(new_bh);
+			ext4_ios_write(sb, handle, new_bh,
+					EXT4_IOS_EXTENDED_ATTR, 1);
 			error = ext4_handle_dirty_metadata(handle,
 							   inode, new_bh);
 			if (error)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 6/8] ext4: account the data request of write operations in buffered io
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
                   ` (4 preceding siblings ...)
  2012-01-23 16:50 ` [PATCH v4 5/8] ext4: account the metadata request of write " Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 7/8] ext4: request accouting in direct io Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 8/8] ext4: show the result of io types accouting Zheng Liu
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

We call ext4_ios_write() function to account the data request of write in
buffered io.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/inode.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 176977a..cfebc6d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1910,6 +1910,8 @@ static int ext4_writepage(struct page *page,
 	struct inode *inode = page->mapping->host;
 
 	trace_ext4_writepage(page);
+	ext4_ios_write(inode->i_sb, NULL, NULL, EXT4_IOS_REGULAR_DATA,
+			ext4_blocks_per_page(inode));
 	size = i_size_read(inode);
 	if (page->index == size >> PAGE_CACHE_SHIFT)
 		len = size & ~PAGE_CACHE_MASK;
@@ -2084,6 +2086,9 @@ static int write_cache_pages_da(struct address_space *mapping,
 			logical = (sector_t) page->index <<
 				(PAGE_CACHE_SHIFT - inode->i_blkbits);
 
+			ext4_ios_write(inode->i_sb, NULL, NULL,
+					EXT4_IOS_REGULAR_DATA,
+					ext4_blocks_per_page(inode));
 			if (!page_has_buffers(page)) {
 				mpage_add_bh_to_extent(mpd, logical,
 						       PAGE_CACHE_SIZE,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 7/8] ext4: request accouting in direct io
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
                   ` (5 preceding siblings ...)
  2012-01-23 16:50 ` [PATCH v4 6/8] ext4: account the data " Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  2012-01-23 16:50 ` [PATCH v4 8/8] ext4: show the result of io types accouting Zheng Liu
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

ext4_ios_submit_io() function is defined to be called by __blockdev_direct_IO()
to count direct io.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/ext4.h     |    2 ++
 fs/ext4/indirect.c |    9 ++++++---
 fs/ext4/inode.c    |   13 ++++++++++++-
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 688891e..0f67d92 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1923,6 +1923,8 @@ extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern void ext4_da_update_reserve_space(struct inode *inode,
 					int used, int quota_claim);
+extern void ext4_ios_submit_io(int rw, struct bio *bio,
+			       struct inode *inode, loff_t file_offset);
 
 /* indirect.c */
 extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 8f9bfd2..143276a 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -820,10 +820,13 @@ retry:
 		ret = __blockdev_direct_IO(rw, iocb, inode,
 				 inode->i_sb->s_bdev, iov,
 				 offset, nr_segs,
-				 ext4_get_block, NULL, NULL, 0);
+				 ext4_get_block, NULL, ext4_ios_submit_io, 0);
 	} else {
-		ret = blockdev_direct_IO(rw, iocb, inode, iov,
-				 offset, nr_segs, ext4_get_block);
+		ret = __blockdev_direct_IO(rw, iocb, inode,
+				 inode->i_sb->s_bdev, iov,
+				 offset, nr_segs,
+				 ext4_get_block, NULL, ext4_ios_submit_io,
+				 DIO_LOCKING | DIO_SKIP_HOLES);
 
 		if (unlikely((rw & WRITE) && ret < 0)) {
 			loff_t isize = i_size_read(inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cfebc6d..8ff6aea 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2948,7 +2948,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 					 offset, nr_segs,
 					 ext4_get_block_write,
 					 ext4_end_io_dio,
-					 NULL,
+					 ext4_ios_submit_io,
 					 DIO_LOCKING | DIO_SKIP_HOLES);
 		if (iocb->private)
 			EXT4_I(inode)->cur_aio_dio = NULL;
@@ -2989,6 +2989,17 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 	return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
 }
 
+void ext4_ios_submit_io(int rw, struct bio *bio,
+			struct inode *inode, loff_t file_offset)
+{
+	int tmprw = !!rw;
+
+	/* ext4 io type accouting */
+	__ext4_io_stat(inode->i_sb, tmprw, EXT4_IOS_REGULAR_DATA,
+			ext4_blocks_per_page(inode));
+	submit_bio(rw, bio);
+}
+
 static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
 			      const struct iovec *iov, loff_t offset,
 			      unsigned long nr_segs)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 8/8] ext4: show the result of io types accouting
  2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
                   ` (6 preceding siblings ...)
  2012-01-23 16:50 ` [PATCH v4 7/8] ext4: request accouting in direct io Zheng Liu
@ 2012-01-23 16:50 ` Zheng Liu
  7 siblings, 0 replies; 9+ messages in thread
From: Zheng Liu @ 2012-01-23 16:50 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel
  Cc: Zheng Liu, Jens Axboe, Steven Whitehouse, Aditya Kali,
	Wang Shaoyan

We create three files to control io type accouting and show the result.

* io_stats_enable is used to turn on/off io type accouting.
* io_stats_reset is used to reset the counters.
* io_stats shows the result of accouting.

CC: Jens Axboe <axboe@kernel.dk>
CC: Steven Whitehouse <swhiteho@redhat.com>
CC: Aditya Kali <adityakali@google.com>
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@taobao.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/ext4.h  |    3 ++
 fs/ext4/super.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 103 insertions(+), 1 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0f67d92..8c6d25f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1117,6 +1117,8 @@ struct ext4_super_block {
 #define EXT4_MF_MNTDIR_SAMPLED	0x0001
 #define EXT4_MF_FS_ABORTED	0x0002	/* Fatal error detected */
 
+#define EXT4_IOS_VERSION	"1.0"
+
 /*
  * ext4 io types
  */
@@ -1278,6 +1280,7 @@ struct ext4_sb_info {
 	atomic_t s_last_trim_minblks;
 
 	/* for io type accouting */
+	int s_ios_enable;
 	struct percpu_counter s_ios_counters[EXT4_IOS_TYPE_END][2];
 };
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7aee0dd..0a47cee 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2535,6 +2535,96 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
 	return count;
 }
 
+static inline u64 ext4_get_ios_counter(struct ext4_sb_info *sbi,
+		int rw, int flag);
+static inline void ext4_reset_ios_counter(struct ext4_sb_info *sbi);
+static ssize_t io_stats_show(struct ext4_attr *a,
+		struct ext4_sb_info *sbi, char *buf)
+{
+	int i;
+	unsigned long ios_counters[EXT4_IOS_TYPE_END][2] = {{0,},};
+
+	if (!sbi->s_ios_enable)
+		return snprintf(buf, PAGE_SIZE, "disabled\n");
+
+	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
+		ios_counters[i][READ] = ext4_get_ios_counter(sbi, READ, i);
+		ios_counters[i][WRITE] = ext4_get_ios_counter(sbi, WRITE, i);
+	}
+
+	return snprintf(buf, PAGE_SIZE,
+			"Version: %s\n"
+			"TYPE                   READ    WRITE\n"
+			"super block            %8lu %8lu\n"
+			"group descriptor       %8lu %8lu\n"
+			"inode bitmap           %8lu %8lu\n"
+			"block bitmap           %8lu %8lu\n"
+			"inode table            %8lu %8lu\n"
+			"extent block           %8lu %8lu\n"
+			"indirect block         %8lu %8lu\n"
+			"dir entry              %8lu %8lu\n"
+			"extended attribute     %8lu %8lu\n"
+			"regular data           %8lu %8lu\n",
+			EXT4_IOS_VERSION,
+			ios_counters[EXT4_IOS_SUPER_BLOCK][READ],
+			ios_counters[EXT4_IOS_SUPER_BLOCK][WRITE],
+			ios_counters[EXT4_IOS_GROUP_DESC][READ],
+			ios_counters[EXT4_IOS_GROUP_DESC][WRITE],
+			ios_counters[EXT4_IOS_INODE_BITMAP][READ],
+			ios_counters[EXT4_IOS_INODE_BITMAP][WRITE],
+			ios_counters[EXT4_IOS_BLOCK_BITMAP][READ],
+			ios_counters[EXT4_IOS_BLOCK_BITMAP][WRITE],
+			ios_counters[EXT4_IOS_INODE_TABLE][READ],
+			ios_counters[EXT4_IOS_INODE_TABLE][WRITE],
+			ios_counters[EXT4_IOS_EXTENT_BLOCK][READ],
+			ios_counters[EXT4_IOS_EXTENT_BLOCK][WRITE],
+			ios_counters[EXT4_IOS_INDIRECT_BLOCK][READ],
+			ios_counters[EXT4_IOS_INDIRECT_BLOCK][WRITE],
+			ios_counters[EXT4_IOS_DIR_ENTRY][READ],
+			ios_counters[EXT4_IOS_DIR_ENTRY][WRITE],
+			ios_counters[EXT4_IOS_EXTENDED_ATTR][READ],
+			ios_counters[EXT4_IOS_EXTENDED_ATTR][WRITE],
+			ios_counters[EXT4_IOS_REGULAR_DATA][READ],
+			ios_counters[EXT4_IOS_REGULAR_DATA][WRITE]);
+}
+
+static ssize_t io_stats_reset_store(struct ext4_attr *a,
+				    struct ext4_sb_info *sbi,
+				    const char *buf, size_t count)
+{
+	unsigned long t;
+
+	if (parse_strtoul(buf, 0xffffffff, &t))
+		return -EINVAL;
+	if (t == 1)
+		ext4_reset_ios_counter(sbi);
+	return count;
+}
+
+static ssize_t io_stats_enable_show(struct ext4_attr *a,
+				    struct ext4_sb_info *sbi, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", sbi->s_ios_enable);
+}
+
+static ssize_t io_stats_enable_store(struct ext4_attr *a,
+				     struct ext4_sb_info *sbi,
+				     const char *buf, size_t count)
+{
+	unsigned long val;
+
+	if (parse_strtoul(buf, 0xffffffff, &val))
+		return -EINVAL;
+
+	switch (val) {
+	case 0: ext4_reset_ios_counter(sbi);
+	case 1: sbi->s_ios_enable = val; break;
+	default: return -EINVAL;
+	}
+
+	return count;
+}
+
 static ssize_t sbi_ui_show(struct ext4_attr *a,
 			   struct ext4_sb_info *sbi, char *buf)
 {
@@ -2568,6 +2658,7 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
 
 #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
 #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
+#define EXT4_WO_ATTR(name) EXT4_ATTR(name, 0222, NULL, name##_store)
 #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
 #define EXT4_RW_ATTR_SBI_UI(name, elname)	\
 	EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
@@ -2578,6 +2669,9 @@ EXT4_RO_ATTR(session_write_kbytes);
 EXT4_RO_ATTR(lifetime_write_kbytes);
 EXT4_RO_ATTR(extent_cache_hits);
 EXT4_RO_ATTR(extent_cache_misses);
+EXT4_RO_ATTR(io_stats);
+EXT4_RW_ATTR(io_stats_enable);
+EXT4_WO_ATTR(io_stats_reset);
 EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
 		 inode_readahead_blks_store, s_inode_readahead_blks);
 EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
@@ -2597,6 +2691,9 @@ static struct attribute *ext4_attrs[] = {
 	ATTR_LIST(extent_cache_misses),
 	ATTR_LIST(inode_readahead_blks),
 	ATTR_LIST(inode_goal),
+	ATTR_LIST(io_stats),
+	ATTR_LIST(io_stats_enable),
+	ATTR_LIST(io_stats_reset),
 	ATTR_LIST(mb_stats),
 	ATTR_LIST(mb_max_to_scan),
 	ATTR_LIST(mb_min_to_scan),
@@ -3160,6 +3257,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	 * Note: s_ios_counters must be initialized as soon as possible becuase
 	 *       ext4 io type accouting depends on it
 	 */
+	sbi->s_ios_enable = 0;
 	for (i = 0; i < EXT4_IOS_TYPE_END; i++) {
 		if (percpu_counter_init(&sbi->s_ios_counters[i][READ], 0))
 			goto out_init_ios;
@@ -4985,7 +5083,8 @@ void __ext4_io_stat(struct super_block *sb, int rw,
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
 	BUG_ON(type < 0 || type >= EXT4_IOS_TYPE_END);
-	percpu_counter_add(&sbi->s_ios_counters[type][rw], count);
+	if (sbi->s_ios_enable)
+		percpu_counter_add(&sbi->s_ios_counters[type][rw], count);
 }
 
 void ext4_ios_write(struct super_block *sb, handle_t *handle,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-01-23 16:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-23 16:50 [PATCH v4 0/8] ext4: io type accouting Zheng Liu
2012-01-23 16:50 ` [PATCH v4 1/8] ext4: add percpu counters and related functions to account io types Zheng Liu
2012-01-23 16:50 ` [PATCH v4 2/8] ext4: add wrapper functions for buffer layer Zheng Liu
2012-01-23 16:50 ` [PATCH v4 3/8] ext4: account the metadata request of read operations in buffered io Zheng Liu
2012-01-23 16:50 ` [PATCH v4 4/8] ext4: account the data " Zheng Liu
2012-01-23 16:50 ` [PATCH v4 5/8] ext4: account the metadata request of write " Zheng Liu
2012-01-23 16:50 ` [PATCH v4 6/8] ext4: account the data " Zheng Liu
2012-01-23 16:50 ` [PATCH v4 7/8] ext4: request accouting in direct io Zheng Liu
2012-01-23 16:50 ` [PATCH v4 8/8] ext4: show the result of io types accouting Zheng Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).