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;