--- /dev/null
+Index: linux/fs/buffer.c
+===================================================================
+--- linux.orig/fs/buffer.c
++++ linux/fs/buffer.c
+@@ -509,13 +509,18 @@ __find_get_block_slow(struct block_devic
+ struct buffer_head *head;
+ struct page *page;
+ int all_mapped = 1;
++ int spinlock = 0;
+
+ index = block >> (PAGE_CACHE_SHIFT - bd_inode->i_blkbits);
+ page = find_get_page(bd_mapping, index);
+ if (!page)
+ goto out;
+
++ if (unlikely(TestSetPageLocked(page))) {
+ spin_lock(&bd_mapping->private_lock);
++ spinlock = 1;
++ }
++
+ if (!page_has_buffers(page))
+ goto out_unlock;
+ head = page_buffers(page);
+@@ -536,7 +541,7 @@ __find_get_block_slow(struct block_devic
+ * file io on the block device and getblk. It gets dealt with
+ * elsewhere, don't buffer_error if we had some unmapped buffers
+ */
+- if (all_mapped) {
++ if (unlikely(all_mapped)) {
+ printk("__find_get_block_slow() failed. "
+ "block=%llu, b_blocknr=%llu\n",
+ (unsigned long long)block, (unsigned long long)bh->b_blocknr);
+@@ -544,7 +549,10 @@ __find_get_block_slow(struct block_devic
+ printk("device blocksize: %d\n", 1 << bd_inode->i_blkbits);
+ }
+ out_unlock:
++ if (unlikely(spinlock))
+ spin_unlock(&bd_mapping->private_lock);
++ else
++ unlock_page(page);
+ page_cache_release(page);
+ out:
+ return ret;