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 | ||