diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 12ccacd..930d19c 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -387,7 +387,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 61fa9e1..50aff92 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -668,7 +668,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;
 			}
@@ -1323,7 +1324,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);
@@ -1337,7 +1339,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);
@@ -2562,7 +2564,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 00beb4f..4eb4e59 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 3cfc73f..0bd0125 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -158,7 +158,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;
 			}
@@ -1254,7 +1255,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 fffec40..52fcaab 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -697,11 +697,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;
@@ -3665,7 +3664,8 @@ make_io:
 			if (end > table)
 				end = table;
 			while (b <= end)
-				sb_breadahead(sb, b++);
+				ext4_sb_breadahead(sb, b++,
+					EXT4_IOS_INODE_TABLE);
 		}
 
 		/*
@@ -3674,11 +3674,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 e2d8be8..dba224c 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 aa4c782..4be6165 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 b10b5ed..ab999de 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3181,7 +3181,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;
 	}
@@ -3353,7 +3354,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");
@@ -3562,7 +3564,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);
