/* super.c */
 extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
                                         sector_t block, int op_flags);
+extern void ext4_read_bh_nowait(struct buffer_head *bh, int op_flags,
+                               bh_end_io_t *end_io);
+extern int ext4_read_bh(struct buffer_head *bh, int op_flags,
+                       bh_end_io_t *end_io);
+extern int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, bool wait);
 extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern void ext4_superblock_csum_set(struct super_block *sb);
 
 MODULE_ALIAS("ext3");
 #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 
+
+static inline void __ext4_read_bh(struct buffer_head *bh, int op_flags,
+                                 bh_end_io_t *end_io)
+{
+       /*
+        * buffer's verified bit is no longer valid after reading from
+        * disk again due to write out error, clear it to make sure we
+        * recheck the buffer contents.
+        */
+       clear_buffer_verified(bh);
+
+       bh->b_end_io = end_io ? end_io : end_buffer_read_sync;
+       get_bh(bh);
+       submit_bh(REQ_OP_READ, op_flags, bh);
+}
+
+void ext4_read_bh_nowait(struct buffer_head *bh, int op_flags,
+                        bh_end_io_t *end_io)
+{
+       BUG_ON(!buffer_locked(bh));
+
+       if (ext4_buffer_uptodate(bh)) {
+               unlock_buffer(bh);
+               return;
+       }
+       __ext4_read_bh(bh, op_flags, end_io);
+}
+
+int ext4_read_bh(struct buffer_head *bh, int op_flags, bh_end_io_t *end_io)
+{
+       BUG_ON(!buffer_locked(bh));
+
+       if (ext4_buffer_uptodate(bh)) {
+               unlock_buffer(bh);
+               return 0;
+       }
+
+       __ext4_read_bh(bh, op_flags, end_io);
+
+       wait_on_buffer(bh);
+       if (buffer_uptodate(bh))
+               return 0;
+       return -EIO;
+}
+
+int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, bool wait)
+{
+       if (trylock_buffer(bh)) {
+               if (wait)
+                       return ext4_read_bh(bh, op_flags, NULL);
+               ext4_read_bh_nowait(bh, op_flags, NULL);
+               return 0;
+       }
+       if (wait) {
+               wait_on_buffer(bh);
+               if (buffer_uptodate(bh))
+                       return 0;
+               return -EIO;
+       }
+       return 0;
+}
+
 /*
  * This works like sb_bread() except it uses ERR_PTR for error
  * returns.  Currently with sb_bread it's impossible to distinguish