aboutsummaryrefslogtreecommitdiffstats
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 13:06:44 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 13:06:44 -0500
commit0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch)
treedcced72d230d69fd0c5816ac6dd03ab84799a93e /fs/buffer.c
parente138a5d2356729b8752e88520cc1525fae9794ac (diff)
parentf26b90440cd74c78fe10c9bd5160809704a9627c (diff)
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index eeb8ac1aa856..35527dca1dbc 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -452,6 +452,7 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
452 bdevname(bh->b_bdev, b)); 452 bdevname(bh->b_bdev, b));
453 } 453 }
454 set_bit(AS_EIO, &page->mapping->flags); 454 set_bit(AS_EIO, &page->mapping->flags);
455 set_buffer_write_io_error(bh);
455 clear_buffer_uptodate(bh); 456 clear_buffer_uptodate(bh);
456 SetPageError(page); 457 SetPageError(page);
457 } 458 }
@@ -571,6 +572,10 @@ EXPORT_SYMBOL(mark_buffer_async_write);
571static inline void __remove_assoc_queue(struct buffer_head *bh) 572static inline void __remove_assoc_queue(struct buffer_head *bh)
572{ 573{
573 list_del_init(&bh->b_assoc_buffers); 574 list_del_init(&bh->b_assoc_buffers);
575 WARN_ON(!bh->b_assoc_map);
576 if (buffer_write_io_error(bh))
577 set_bit(AS_EIO, &bh->b_assoc_map->flags);
578 bh->b_assoc_map = NULL;
574} 579}
575 580
576int inode_has_buffers(struct inode *inode) 581int inode_has_buffers(struct inode *inode)
@@ -669,6 +674,7 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
669 spin_lock(&buffer_mapping->private_lock); 674 spin_lock(&buffer_mapping->private_lock);
670 list_move_tail(&bh->b_assoc_buffers, 675 list_move_tail(&bh->b_assoc_buffers,
671 &mapping->private_list); 676 &mapping->private_list);
677 bh->b_assoc_map = mapping;
672 spin_unlock(&buffer_mapping->private_lock); 678 spin_unlock(&buffer_mapping->private_lock);
673 } 679 }
674} 680}
@@ -765,7 +771,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
765 spin_lock(lock); 771 spin_lock(lock);
766 while (!list_empty(list)) { 772 while (!list_empty(list)) {
767 bh = BH_ENTRY(list->next); 773 bh = BH_ENTRY(list->next);
768 list_del_init(&bh->b_assoc_buffers); 774 __remove_assoc_queue(bh);
769 if (buffer_dirty(bh) || buffer_locked(bh)) { 775 if (buffer_dirty(bh) || buffer_locked(bh)) {
770 list_add(&bh->b_assoc_buffers, &tmp); 776 list_add(&bh->b_assoc_buffers, &tmp);
771 if (buffer_dirty(bh)) { 777 if (buffer_dirty(bh)) {
@@ -786,7 +792,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
786 792
787 while (!list_empty(&tmp)) { 793 while (!list_empty(&tmp)) {
788 bh = BH_ENTRY(tmp.prev); 794 bh = BH_ENTRY(tmp.prev);
789 __remove_assoc_queue(bh); 795 list_del_init(&bh->b_assoc_buffers);
790 get_bh(bh); 796 get_bh(bh);
791 spin_unlock(lock); 797 spin_unlock(lock);
792 wait_on_buffer(bh); 798 wait_on_buffer(bh);
@@ -1042,8 +1048,21 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
1042 } while ((size << sizebits) < PAGE_SIZE); 1048 } while ((size << sizebits) < PAGE_SIZE);
1043 1049
1044 index = block >> sizebits; 1050 index = block >> sizebits;
1045 block = index << sizebits;
1046 1051
1052 /*
1053 * Check for a block which wants to lie outside our maximum possible
1054 * pagecache index. (this comparison is done using sector_t types).
1055 */
1056 if (unlikely(index != block >> sizebits)) {
1057 char b[BDEVNAME_SIZE];
1058
1059 printk(KERN_ERR "%s: requested out-of-range block %llu for "
1060 "device %s\n",
1061 __FUNCTION__, (unsigned long long)block,
1062 bdevname(bdev, b));
1063 return -EIO;
1064 }
1065 block = index << sizebits;
1047 /* Create a page with the proper size buffers.. */ 1066 /* Create a page with the proper size buffers.. */
1048 page = grow_dev_page(bdev, block, index, size); 1067 page = grow_dev_page(bdev, block, index, size);
1049 if (!page) 1068 if (!page)
@@ -1070,12 +1089,16 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
1070 1089
1071 for (;;) { 1090 for (;;) {
1072 struct buffer_head * bh; 1091 struct buffer_head * bh;
1092 int ret;
1073 1093
1074 bh = __find_get_block(bdev, block, size); 1094 bh = __find_get_block(bdev, block, size);
1075 if (bh) 1095 if (bh)
1076 return bh; 1096 return bh;
1077 1097
1078 if (!grow_buffers(bdev, block, size)) 1098 ret = grow_buffers(bdev, block, size);
1099 if (ret < 0)
1100 return NULL;
1101 if (ret == 0)
1079 free_more_memory(); 1102 free_more_memory();
1080 } 1103 }
1081} 1104}
@@ -1150,6 +1173,7 @@ void __bforget(struct buffer_head *bh)
1150 1173
1151 spin_lock(&buffer_mapping->private_lock); 1174 spin_lock(&buffer_mapping->private_lock);
1152 list_del_init(&bh->b_assoc_buffers); 1175 list_del_init(&bh->b_assoc_buffers);
1176 bh->b_assoc_map = NULL;
1153 spin_unlock(&buffer_mapping->private_lock); 1177 spin_unlock(&buffer_mapping->private_lock);
1154 } 1178 }
1155 __brelse(bh); 1179 __brelse(bh);
@@ -1837,6 +1861,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
1837 clear_buffer_new(bh); 1861 clear_buffer_new(bh);
1838 kaddr = kmap_atomic(page, KM_USER0); 1862 kaddr = kmap_atomic(page, KM_USER0);
1839 memset(kaddr+block_start, 0, bh->b_size); 1863 memset(kaddr+block_start, 0, bh->b_size);
1864 flush_dcache_page(page);
1840 kunmap_atomic(kaddr, KM_USER0); 1865 kunmap_atomic(kaddr, KM_USER0);
1841 set_buffer_uptodate(bh); 1866 set_buffer_uptodate(bh);
1842 mark_buffer_dirty(bh); 1867 mark_buffer_dirty(bh);
@@ -2343,6 +2368,7 @@ failed:
2343 */ 2368 */
2344 kaddr = kmap_atomic(page, KM_USER0); 2369 kaddr = kmap_atomic(page, KM_USER0);
2345 memset(kaddr, 0, PAGE_CACHE_SIZE); 2370 memset(kaddr, 0, PAGE_CACHE_SIZE);
2371 flush_dcache_page(page);
2346 kunmap_atomic(kaddr, KM_USER0); 2372 kunmap_atomic(kaddr, KM_USER0);
2347 SetPageUptodate(page); 2373 SetPageUptodate(page);
2348 set_page_dirty(page); 2374 set_page_dirty(page);