diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 13:06:44 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 13:06:44 -0500 |
commit | 0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch) | |
tree | dcced72d230d69fd0c5816ac6dd03ab84799a93e /fs/buffer.c | |
parent | e138a5d2356729b8752e88520cc1525fae9794ac (diff) | |
parent | f26b90440cd74c78fe10c9bd5160809704a9627c (diff) |
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 34 |
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); | |||
571 | static inline void __remove_assoc_queue(struct buffer_head *bh) | 572 | static 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 | ||
576 | int inode_has_buffers(struct inode *inode) | 581 | int 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); |