[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1320054184-14329-3-git-send-email-wenqing.lz@taobao.com>
Date: Mon, 31 Oct 2011 17:43:01 +0800
From: Zheng Liu <gnehzuil.liu@...il.com>
To: linux-ext4@...r.kernel.org, linux-fsdevel@...r.kernel.org
Cc: Wang Shaoyan <wangshaoyan.pt@...bao.com>
Subject: [PATCH 2/5] ext4: add hooks in buffer layer
From: Wang Shaoyan <wangshaoyan.pt@...bao.com>
Add hooks in buffer layer, we just ignore the IO which hit in cache.
Some interfaces are changed to pass ios argument.
Signed-off-by: Wang Shaoyan <wangshaoyan.pt@...bao.com>
---
fs/buffer.c | 61 ++++++++++++++++++++++++++++++++++++------
include/linux/buffer_head.h | 17 ++++++++++++
2 files changed, 69 insertions(+), 9 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 936d603..1e12533 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1208,7 +1208,8 @@ void __bforget(struct buffer_head *bh)
}
EXPORT_SYMBOL(__bforget);
-static struct buffer_head *__bread_slow(struct buffer_head *bh)
+static struct buffer_head *__bread_slow_stat(struct buffer_head *bh,
+ struct ios *ios)
{
lock_buffer(bh);
if (buffer_uptodate(bh)) {
@@ -1219,13 +1220,21 @@ static struct buffer_head *__bread_slow(struct buffer_head *bh)
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
wait_on_buffer(bh);
- if (buffer_uptodate(bh))
+ if (buffer_uptodate(bh)) {
+ if (ios)
+ ios->io_stat(ios->data);
return bh;
+ }
}
brelse(bh);
return NULL;
}
+static struct buffer_head *__bread_slow(struct buffer_head *bh)
+{
+ return __bread_slow_stat(bh, NULL);
+}
+
/*
* Per-cpu buffer LRU implementation. To reduce the cost of __find_get_block().
* The bhs[] array is sorted - newest buffer is at bhs[0]. Buffers have their
@@ -1387,13 +1396,20 @@ EXPORT_SYMBOL(__getblk);
*/
void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
{
+ __breadahead_stat(bdev, block, size, NULL);
+}
+EXPORT_SYMBOL(__breadahead);
+
+void __breadahead_stat(struct block_device *bdev, sector_t block,
+ unsigned size, struct ios *ios)
+{
struct buffer_head *bh = __getblk(bdev, block, size);
if (likely(bh)) {
- ll_rw_block(READA, 1, &bh);
+ ll_rw_block_stat(READA, 1, &bh, ios);
brelse(bh);
}
}
-EXPORT_SYMBOL(__breadahead);
+EXPORT_SYMBOL(__breadahead_stat);
/**
* __bread() - reads a specified block and returns the bh
@@ -1407,13 +1423,21 @@ EXPORT_SYMBOL(__breadahead);
struct buffer_head *
__bread(struct block_device *bdev, sector_t block, unsigned size)
{
+ return __bread_stat(bdev, block, size, NULL);
+}
+EXPORT_SYMBOL(__bread);
+
+struct buffer_head *
+__bread_stat(struct block_device *bdev, sector_t block, unsigned size,
+ struct ios *ios)
+{
struct buffer_head *bh = __getblk(bdev, block, size);
if (likely(bh) && !buffer_uptodate(bh))
- bh = __bread_slow(bh);
+ bh = __bread_slow_stat(bh, ios);
return bh;
}
-EXPORT_SYMBOL(__bread);
+EXPORT_SYMBOL(__bread_stat);
/*
* invalidate_bh_lrus() is called rarely - but not only at unmount.
@@ -2978,7 +3002,8 @@ EXPORT_SYMBOL(submit_bh);
* All of the buffers must be for the same device, and must also be a
* multiple of the current approved size for the device.
*/
-void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
+void ll_rw_block_stat(int rw, int nr, struct buffer_head *bhs[],
+ struct ios *ios)
{
int i;
@@ -2992,6 +3017,8 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
bh->b_end_io = end_buffer_write_sync;
get_bh(bh);
submit_bh(WRITE, bh);
+ if (ios)
+ ios->io_stat(ios->data);
continue;
}
} else {
@@ -2999,12 +3026,19 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
bh->b_end_io = end_buffer_read_sync;
get_bh(bh);
submit_bh(rw, bh);
+ if (ios)
+ ios->io_stat(ios->data);
continue;
}
}
unlock_buffer(bh);
}
}
+EXPORT_SYMBOL(ll_rw_block_stat);
+void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
+{
+ ll_rw_block_stat(rw, nr, bhs, NULL);
+}
EXPORT_SYMBOL(ll_rw_block);
void write_dirty_buffer(struct buffer_head *bh, int rw)
@@ -3288,6 +3322,12 @@ EXPORT_SYMBOL(bh_uptodate_or_lock);
*/
int bh_submit_read(struct buffer_head *bh)
{
+ return bh_submit_read_stat(bh, NULL);
+}
+EXPORT_SYMBOL(bh_submit_read);
+
+int bh_submit_read_stat(struct buffer_head *bh, struct ios *ios)
+{
BUG_ON(!buffer_locked(bh));
if (buffer_uptodate(bh)) {
@@ -3299,11 +3339,14 @@ int bh_submit_read(struct buffer_head *bh)
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
wait_on_buffer(bh);
- if (buffer_uptodate(bh))
+ if (buffer_uptodate(bh)) {
+ if (ios)
+ ios->io_stat(ios->data);
return 0;
+ }
return -EIO;
}
-EXPORT_SYMBOL(bh_submit_read);
+EXPORT_SYMBOL(bh_submit_read_stat);
void __init buffer_init(void)
{
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 458f497..07306a9 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -171,13 +171,18 @@ struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
void __brelse(struct buffer_head *);
void __bforget(struct buffer_head *);
void __breadahead(struct block_device *, sector_t block, unsigned int size);
+void __breadahead_stat(struct block_device *, sector_t block,
+ unsigned int size, struct ios *ios);
struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
+struct buffer_head *__bread_stat(struct block_device *, sector_t block,
+ unsigned size, struct ios *ios);
void invalidate_bh_lrus(void);
struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
void free_buffer_head(struct buffer_head * bh);
void unlock_buffer(struct buffer_head *bh);
void __lock_buffer(struct buffer_head *bh);
void ll_rw_block(int, int, struct buffer_head * bh[]);
+void ll_rw_block_stat(int, int, struct buffer_head *bh[], struct ios *ios);
int sync_dirty_buffer(struct buffer_head *bh);
int __sync_dirty_buffer(struct buffer_head *bh, int rw);
void write_dirty_buffer(struct buffer_head *bh, int rw);
@@ -186,6 +191,7 @@ void write_boundary_block(struct block_device *bdev,
sector_t bblock, unsigned blocksize);
int bh_uptodate_or_lock(struct buffer_head *bh);
int bh_submit_read(struct buffer_head *bh);
+int bh_submit_read_stat(struct buffer_head *bh, struct ios *ios);
extern int buffer_heads_over_limit;
@@ -288,12 +294,23 @@ sb_bread(struct super_block *sb, sector_t block)
{
return __bread(sb->s_bdev, block, sb->s_blocksize);
}
+static inline struct buffer_head *
+sb_bread_stat(struct super_block *sb, sector_t block, struct ios *ios)
+{
+ return __bread_stat(sb->s_bdev, block, sb->s_blocksize, ios);
+}
+
static inline void
sb_breadahead(struct super_block *sb, sector_t block)
{
__breadahead(sb->s_bdev, block, sb->s_blocksize);
}
+static inline void
+sb_breadahead_stat(struct super_block *sb, sector_t block, struct ios *ios)
+{
+ __breadahead_stat(sb->s_bdev, block, sb->s_blocksize, ios);
+}
static inline struct buffer_head *
sb_getblk(struct super_block *sb, sector_t block)
--
1.7.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists