diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
| commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
| tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /fs/buffer.c | |
| parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
| parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) | |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'fs/buffer.c')
| -rw-r--r-- | fs/buffer.c | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index d48caee12e2a..6569fda5cfed 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -76,8 +76,7 @@ EXPORT_SYMBOL(__lock_buffer); | |||
| 76 | 76 | ||
| 77 | void unlock_buffer(struct buffer_head *bh) | 77 | void unlock_buffer(struct buffer_head *bh) |
| 78 | { | 78 | { |
| 79 | smp_mb__before_clear_bit(); | 79 | clear_bit_unlock(BH_Lock, &bh->b_state); |
| 80 | clear_buffer_locked(bh); | ||
| 81 | smp_mb__after_clear_bit(); | 80 | smp_mb__after_clear_bit(); |
| 82 | wake_up_bit(&bh->b_state, BH_Lock); | 81 | wake_up_bit(&bh->b_state, BH_Lock); |
| 83 | } | 82 | } |
| @@ -580,7 +579,7 @@ EXPORT_SYMBOL(mark_buffer_async_write); | |||
| 580 | /* | 579 | /* |
| 581 | * The buffer's backing address_space's private_lock must be held | 580 | * The buffer's backing address_space's private_lock must be held |
| 582 | */ | 581 | */ |
| 583 | static inline void __remove_assoc_queue(struct buffer_head *bh) | 582 | static void __remove_assoc_queue(struct buffer_head *bh) |
| 584 | { | 583 | { |
| 585 | list_del_init(&bh->b_assoc_buffers); | 584 | list_del_init(&bh->b_assoc_buffers); |
| 586 | WARN_ON(!bh->b_assoc_map); | 585 | WARN_ON(!bh->b_assoc_map); |
| @@ -706,7 +705,7 @@ static int __set_page_dirty(struct page *page, | |||
| 706 | if (TestSetPageDirty(page)) | 705 | if (TestSetPageDirty(page)) |
| 707 | return 0; | 706 | return 0; |
| 708 | 707 | ||
| 709 | write_lock_irq(&mapping->tree_lock); | 708 | spin_lock_irq(&mapping->tree_lock); |
| 710 | if (page->mapping) { /* Race with truncate? */ | 709 | if (page->mapping) { /* Race with truncate? */ |
| 711 | WARN_ON_ONCE(warn && !PageUptodate(page)); | 710 | WARN_ON_ONCE(warn && !PageUptodate(page)); |
| 712 | 711 | ||
| @@ -719,7 +718,7 @@ static int __set_page_dirty(struct page *page, | |||
| 719 | radix_tree_tag_set(&mapping->page_tree, | 718 | radix_tree_tag_set(&mapping->page_tree, |
| 720 | page_index(page), PAGECACHE_TAG_DIRTY); | 719 | page_index(page), PAGECACHE_TAG_DIRTY); |
| 721 | } | 720 | } |
| 722 | write_unlock_irq(&mapping->tree_lock); | 721 | spin_unlock_irq(&mapping->tree_lock); |
| 723 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 722 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); |
| 724 | 723 | ||
| 725 | return 1; | 724 | return 1; |
| @@ -1214,8 +1213,7 @@ void __brelse(struct buffer_head * buf) | |||
| 1214 | put_bh(buf); | 1213 | put_bh(buf); |
| 1215 | return; | 1214 | return; |
| 1216 | } | 1215 | } |
| 1217 | printk(KERN_ERR "VFS: brelse: Trying to free free buffer\n"); | 1216 | WARN(1, KERN_ERR "VFS: brelse: Trying to free free buffer\n"); |
| 1218 | WARN_ON(1); | ||
| 1219 | } | 1217 | } |
| 1220 | 1218 | ||
| 1221 | /* | 1219 | /* |
| @@ -1721,7 +1719,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, | |||
| 1721 | */ | 1719 | */ |
| 1722 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { | 1720 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { |
| 1723 | lock_buffer(bh); | 1721 | lock_buffer(bh); |
| 1724 | } else if (test_set_buffer_locked(bh)) { | 1722 | } else if (!trylock_buffer(bh)) { |
| 1725 | redirty_page_for_writepage(wbc, page); | 1723 | redirty_page_for_writepage(wbc, page); |
| 1726 | continue; | 1724 | continue; |
| 1727 | } | 1725 | } |
| @@ -2097,6 +2095,52 @@ int generic_write_end(struct file *file, struct address_space *mapping, | |||
| 2097 | EXPORT_SYMBOL(generic_write_end); | 2095 | EXPORT_SYMBOL(generic_write_end); |
| 2098 | 2096 | ||
| 2099 | /* | 2097 | /* |
| 2098 | * block_is_partially_uptodate checks whether buffers within a page are | ||
| 2099 | * uptodate or not. | ||
| 2100 | * | ||
| 2101 | * Returns true if all buffers which correspond to a file portion | ||
| 2102 | * we want to read are uptodate. | ||
| 2103 | */ | ||
| 2104 | int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, | ||
| 2105 | unsigned long from) | ||
| 2106 | { | ||
| 2107 | struct inode *inode = page->mapping->host; | ||
| 2108 | unsigned block_start, block_end, blocksize; | ||
| 2109 | unsigned to; | ||
| 2110 | struct buffer_head *bh, *head; | ||
| 2111 | int ret = 1; | ||
| 2112 | |||
| 2113 | if (!page_has_buffers(page)) | ||
| 2114 | return 0; | ||
| 2115 | |||
| 2116 | blocksize = 1 << inode->i_blkbits; | ||
| 2117 | to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count); | ||
| 2118 | to = from + to; | ||
| 2119 | if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize) | ||
| 2120 | return 0; | ||
| 2121 | |||
| 2122 | head = page_buffers(page); | ||
| 2123 | bh = head; | ||
| 2124 | block_start = 0; | ||
| 2125 | do { | ||
| 2126 | block_end = block_start + blocksize; | ||
| 2127 | if (block_end > from && block_start < to) { | ||
| 2128 | if (!buffer_uptodate(bh)) { | ||
| 2129 | ret = 0; | ||
| 2130 | break; | ||
| 2131 | } | ||
| 2132 | if (block_end >= to) | ||
| 2133 | break; | ||
| 2134 | } | ||
| 2135 | block_start = block_end; | ||
| 2136 | bh = bh->b_this_page; | ||
| 2137 | } while (bh != head); | ||
| 2138 | |||
| 2139 | return ret; | ||
| 2140 | } | ||
| 2141 | EXPORT_SYMBOL(block_is_partially_uptodate); | ||
| 2142 | |||
| 2143 | /* | ||
| 2100 | * Generic "read page" function for block devices that have the normal | 2144 | * Generic "read page" function for block devices that have the normal |
| 2101 | * get_block functionality. This is most of the block device filesystems. | 2145 | * get_block functionality. This is most of the block device filesystems. |
| 2102 | * Reads the page asynchronously --- the unlock_buffer() and | 2146 | * Reads the page asynchronously --- the unlock_buffer() and |
| @@ -2881,14 +2925,17 @@ int submit_bh(int rw, struct buffer_head * bh) | |||
| 2881 | BUG_ON(!buffer_mapped(bh)); | 2925 | BUG_ON(!buffer_mapped(bh)); |
| 2882 | BUG_ON(!bh->b_end_io); | 2926 | BUG_ON(!bh->b_end_io); |
| 2883 | 2927 | ||
| 2884 | if (buffer_ordered(bh) && (rw == WRITE)) | 2928 | /* |
| 2885 | rw = WRITE_BARRIER; | 2929 | * Mask in barrier bit for a write (could be either a WRITE or a |
| 2930 | * WRITE_SYNC | ||
| 2931 | */ | ||
| 2932 | if (buffer_ordered(bh) && (rw & WRITE)) | ||
| 2933 | rw |= WRITE_BARRIER; | ||
| 2886 | 2934 | ||
| 2887 | /* | 2935 | /* |
| 2888 | * Only clear out a write error when rewriting, should this | 2936 | * Only clear out a write error when rewriting |
| 2889 | * include WRITE_SYNC as well? | ||
| 2890 | */ | 2937 | */ |
| 2891 | if (test_set_buffer_req(bh) && (rw == WRITE || rw == WRITE_BARRIER)) | 2938 | if (test_set_buffer_req(bh) && (rw & WRITE)) |
| 2892 | clear_buffer_write_io_error(bh); | 2939 | clear_buffer_write_io_error(bh); |
| 2893 | 2940 | ||
| 2894 | /* | 2941 | /* |
| @@ -2955,7 +3002,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) | |||
| 2955 | 3002 | ||
| 2956 | if (rw == SWRITE || rw == SWRITE_SYNC) | 3003 | if (rw == SWRITE || rw == SWRITE_SYNC) |
| 2957 | lock_buffer(bh); | 3004 | lock_buffer(bh); |
| 2958 | else if (test_set_buffer_locked(bh)) | 3005 | else if (!trylock_buffer(bh)) |
| 2959 | continue; | 3006 | continue; |
| 2960 | 3007 | ||
| 2961 | if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC) { | 3008 | if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC) { |
| @@ -3272,7 +3319,7 @@ int bh_submit_read(struct buffer_head *bh) | |||
| 3272 | EXPORT_SYMBOL(bh_submit_read); | 3319 | EXPORT_SYMBOL(bh_submit_read); |
| 3273 | 3320 | ||
| 3274 | static void | 3321 | static void |
| 3275 | init_buffer_head(struct kmem_cache *cachep, void *data) | 3322 | init_buffer_head(void *data) |
| 3276 | { | 3323 | { |
| 3277 | struct buffer_head *bh = data; | 3324 | struct buffer_head *bh = data; |
| 3278 | 3325 | ||
