aboutsummaryrefslogtreecommitdiffstats
path: root/fs/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index f95805019639..38653e36e225 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -580,7 +580,7 @@ EXPORT_SYMBOL(mark_buffer_async_write);
580/* 580/*
581 * The buffer's backing address_space's private_lock must be held 581 * The buffer's backing address_space's private_lock must be held
582 */ 582 */
583static inline void __remove_assoc_queue(struct buffer_head *bh) 583static void __remove_assoc_queue(struct buffer_head *bh)
584{ 584{
585 list_del_init(&bh->b_assoc_buffers); 585 list_del_init(&bh->b_assoc_buffers);
586 WARN_ON(!bh->b_assoc_map); 586 WARN_ON(!bh->b_assoc_map);
@@ -1720,7 +1720,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
1720 */ 1720 */
1721 if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { 1721 if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
1722 lock_buffer(bh); 1722 lock_buffer(bh);
1723 } else if (test_set_buffer_locked(bh)) { 1723 } else if (!trylock_buffer(bh)) {
1724 redirty_page_for_writepage(wbc, page); 1724 redirty_page_for_writepage(wbc, page);
1725 continue; 1725 continue;
1726 } 1726 }
@@ -2096,6 +2096,52 @@ int generic_write_end(struct file *file, struct address_space *mapping,
2096EXPORT_SYMBOL(generic_write_end); 2096EXPORT_SYMBOL(generic_write_end);
2097 2097
2098/* 2098/*
2099 * block_is_partially_uptodate checks whether buffers within a page are
2100 * uptodate or not.
2101 *
2102 * Returns true if all buffers which correspond to a file portion
2103 * we want to read are uptodate.
2104 */
2105int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
2106 unsigned long from)
2107{
2108 struct inode *inode = page->mapping->host;
2109 unsigned block_start, block_end, blocksize;
2110 unsigned to;
2111 struct buffer_head *bh, *head;
2112 int ret = 1;
2113
2114 if (!page_has_buffers(page))
2115 return 0;
2116
2117 blocksize = 1 << inode->i_blkbits;
2118 to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count);
2119 to = from + to;
2120 if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)
2121 return 0;
2122
2123 head = page_buffers(page);
2124 bh = head;
2125 block_start = 0;
2126 do {
2127 block_end = block_start + blocksize;
2128 if (block_end > from && block_start < to) {
2129 if (!buffer_uptodate(bh)) {
2130 ret = 0;
2131 break;
2132 }
2133 if (block_end >= to)
2134 break;
2135 }
2136 block_start = block_end;
2137 bh = bh->b_this_page;
2138 } while (bh != head);
2139
2140 return ret;
2141}
2142EXPORT_SYMBOL(block_is_partially_uptodate);
2143
2144/*
2099 * Generic "read page" function for block devices that have the normal 2145 * Generic "read page" function for block devices that have the normal
2100 * get_block functionality. This is most of the block device filesystems. 2146 * get_block functionality. This is most of the block device filesystems.
2101 * Reads the page asynchronously --- the unlock_buffer() and 2147 * Reads the page asynchronously --- the unlock_buffer() and
@@ -2954,7 +3000,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
2954 3000
2955 if (rw == SWRITE || rw == SWRITE_SYNC) 3001 if (rw == SWRITE || rw == SWRITE_SYNC)
2956 lock_buffer(bh); 3002 lock_buffer(bh);
2957 else if (test_set_buffer_locked(bh)) 3003 else if (!trylock_buffer(bh))
2958 continue; 3004 continue;
2959 3005
2960 if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC) { 3006 if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC) {