aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:19:22 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit19c00ddcc31ad4bdfb86b57085e06d6135b9b1d7 (patch)
treea48cbaac47070057912c1b35d270b61b7e14386c /fs
parent0f82731fc56448c2733f58e1f5db6c2cbfc90652 (diff)
Btrfs: Add back metadata checksumming
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c215
-rw-r--r--fs/btrfs/extent-tree.c4
-rw-r--r--fs/btrfs/extent_map.c83
-rw-r--r--fs/btrfs/extent_map.h18
-rw-r--r--fs/btrfs/inode.c4
6 files changed, 245 insertions, 81 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d1c6f023a302..1af0a966f85b 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -310,9 +310,11 @@ struct btrfs_fs_info {
310 struct extent_buffer *sb_buffer; 310 struct extent_buffer *sb_buffer;
311 struct super_block *sb; 311 struct super_block *sb;
312 struct inode *btree_inode; 312 struct inode *btree_inode;
313 spinlock_t hash_lock;
313 struct mutex trans_mutex; 314 struct mutex trans_mutex;
314 struct mutex fs_mutex; 315 struct mutex fs_mutex;
315 struct list_head trans_list; 316 struct list_head trans_list;
317 struct list_head hashers;
316 struct list_head dead_roots; 318 struct list_head dead_roots;
317 struct delayed_work trans_work; 319 struct delayed_work trans_work;
318 struct kobject super_kobj; 320 struct kobject super_kobj;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 16f0260fca66..1176e5420c56 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -60,7 +60,7 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
60 struct extent_buffer *eb; 60 struct extent_buffer *eb;
61 61
62 eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, 62 eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree,
63 bytenr, blocksize, GFP_NOFS); 63 bytenr, blocksize, NULL, GFP_NOFS);
64 return eb; 64 return eb;
65} 65}
66 66
@@ -99,10 +99,102 @@ out:
99 return em; 99 return em;
100} 100}
101 101
102u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
103{
104 return crc32c(seed, data, len);
105}
106
107void btrfs_csum_final(u32 crc, char *result)
108{
109 *(__le32 *)result = ~cpu_to_le32(crc);
110}
111
112static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
113 int verify)
114{
115 char result[BTRFS_CRC32_SIZE];
116 unsigned long len;
117 unsigned long cur_len;
118 unsigned long offset = BTRFS_CSUM_SIZE;
119 char *map_token = NULL;
120 char *kaddr;
121 unsigned long map_start;
122 unsigned long map_len;
123 int err;
124 u32 crc = ~(u32)0;
125
126 len = buf->len - offset;
127 while(len > 0) {
128 err = map_private_extent_buffer(buf, offset, 32,
129 &map_token, &kaddr,
130 &map_start, &map_len, KM_USER0);
131 if (err) {
132 printk("failed to map extent buffer! %lu\n",
133 offset);
134 return 1;
135 }
136 cur_len = min(len, map_len - (offset - map_start));
137 crc = btrfs_csum_data(root, kaddr + offset - map_start,
138 crc, cur_len);
139 len -= cur_len;
140 offset += cur_len;
141 unmap_extent_buffer(buf, map_token, KM_USER0);
142 }
143 btrfs_csum_final(crc, result);
144
145 if (verify) {
146 if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
147 printk("btrfs: %s checksum verify failed on %llu\n",
148 root->fs_info->sb->s_id,
149 buf->start);
150 return 1;
151 }
152 } else {
153 write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE);
154 }
155 return 0;
156}
157
158
159int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
160{
161 struct extent_map_tree *tree;
162 u64 start = page->index << PAGE_CACHE_SHIFT;
163 u64 found_start;
164 int found_level;
165 unsigned long len;
166 struct extent_buffer *eb;
167 tree = &BTRFS_I(page->mapping->host)->extent_tree;
168
169 if (page->private == EXTENT_PAGE_PRIVATE)
170 goto out;
171 if (!page->private)
172 goto out;
173 len = page->private >> 2;
174 if (len == 0) {
175 WARN_ON(1);
176 }
177 eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS);
178 read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1);
179 found_start = btrfs_header_bytenr(eb);
180 if (found_start != start) {
181 printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n",
182 start, found_start, len);
183 }
184 found_level = btrfs_header_level(eb);
185 csum_tree_block(root, eb, 0);
186 free_extent_buffer(eb);
187out:
188 return 0;
189}
190
102static int btree_writepage(struct page *page, struct writeback_control *wbc) 191static int btree_writepage(struct page *page, struct writeback_control *wbc)
103{ 192{
104 struct extent_map_tree *tree; 193 struct extent_map_tree *tree;
194 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
105 tree = &BTRFS_I(page->mapping->host)->extent_tree; 195 tree = &BTRFS_I(page->mapping->host)->extent_tree;
196
197 csum_dirty_buffer(root, page);
106 return extent_write_full_page(tree, page, btree_get_extent, wbc); 198 return extent_write_full_page(tree, page, btree_get_extent, wbc);
107} 199}
108int btree_readpage(struct file *file, struct page *page) 200int btree_readpage(struct file *file, struct page *page)
@@ -117,7 +209,6 @@ static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags)
117 struct extent_map_tree *tree; 209 struct extent_map_tree *tree;
118 int ret; 210 int ret;
119 211
120 BUG_ON(page->private != 1);
121 tree = &BTRFS_I(page->mapping->host)->extent_tree; 212 tree = &BTRFS_I(page->mapping->host)->extent_tree;
122 ret = try_release_extent_mapping(tree, page); 213 ret = try_release_extent_mapping(tree, page);
123 if (ret == 1) { 214 if (ret == 1) {
@@ -136,46 +227,6 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
136 btree_releasepage(page, GFP_NOFS); 227 btree_releasepage(page, GFP_NOFS);
137} 228}
138 229
139int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
140 char *result)
141{
142 return 0;
143#if 0
144 u32 crc;
145 crc = crc32c(0, data, len);
146 memcpy(result, &crc, BTRFS_CRC32_SIZE);
147 return 0;
148#endif
149}
150
151#if 0
152static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
153 int verify)
154{
155 return 0;
156 char result[BTRFS_CRC32_SIZE];
157 int ret;
158 struct btrfs_node *node;
159
160 ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE,
161 bh->b_size - BTRFS_CSUM_SIZE, result);
162 if (ret)
163 return ret;
164 if (verify) {
165 if (memcmp(bh->b_data, result, BTRFS_CRC32_SIZE)) {
166 printk("btrfs: %s checksum verify failed on %llu\n",
167 root->fs_info->sb->s_id,
168 (unsigned long long)bh_blocknr(bh));
169 return 1;
170 }
171 } else {
172 node = btrfs_buffer_node(bh);
173 memcpy(node->header.csum, result, BTRFS_CRC32_SIZE);
174 }
175 return 0;
176}
177#endif
178
179#if 0 230#if 0
180static int btree_writepage(struct page *page, struct writeback_control *wbc) 231static int btree_writepage(struct page *page, struct writeback_control *wbc)
181{ 232{
@@ -215,7 +266,7 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
215 if (!buf) 266 if (!buf)
216 return 0; 267 return 0;
217 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 268 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
218 buf, 0); 269 buf, 0, 0);
219 free_extent_buffer(buf); 270 free_extent_buffer(buf);
220 return ret; 271 return ret;
221} 272}
@@ -225,12 +276,29 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
225{ 276{
226 struct extent_buffer *buf = NULL; 277 struct extent_buffer *buf = NULL;
227 struct inode *btree_inode = root->fs_info->btree_inode; 278 struct inode *btree_inode = root->fs_info->btree_inode;
279 struct extent_map_tree *extent_tree;
280 int ret;
281
282 extent_tree = &BTRFS_I(btree_inode)->extent_tree;
228 283
229 buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 284 buf = btrfs_find_create_tree_block(root, bytenr, blocksize);
230 if (!buf) 285 if (!buf)
231 return NULL; 286 return NULL;
232 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 287 read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
233 buf, 1); 288 buf, 0, 1);
289 if (buf->flags & EXTENT_CSUM) {
290 return buf;
291 }
292 if (test_range_bit(extent_tree, buf->start, buf->start + buf->len - 1,
293 EXTENT_CSUM, 1)) {
294 buf->flags |= EXTENT_CSUM;
295 return buf;
296 }
297 ret = csum_tree_block(root, buf, 1);
298 set_extent_bits(extent_tree, buf->start,
299 buf->start + buf->len - 1,
300 EXTENT_CSUM, GFP_NOFS);
301 buf->flags |= EXTENT_CSUM;
234 return buf; 302 return buf;
235} 303}
236 304
@@ -251,13 +319,6 @@ int wait_on_tree_block_writeback(struct btrfs_root *root,
251 return 0; 319 return 0;
252} 320}
253 321
254int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf)
255{
256 struct inode *btree_inode = root->fs_info->btree_inode;
257 set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
258 return 0;
259}
260
261static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 322static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
262 struct btrfs_root *root, 323 struct btrfs_root *root,
263 struct btrfs_fs_info *fs_info, 324 struct btrfs_fs_info *fs_info,
@@ -416,7 +477,24 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
416 477
417 return root; 478 return root;
418} 479}
419 480#if 0
481static int add_hasher(struct btrfs_fs_info *info, char *type) {
482 struct btrfs_hasher *hasher;
483
484 hasher = kmalloc(sizeof(*hasher), GFP_NOFS);
485 if (!hasher)
486 return -ENOMEM;
487 hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC);
488 if (!hasher->hash_tfm) {
489 kfree(hasher);
490 return -EINVAL;
491 }
492 spin_lock(&info->hash_lock);
493 list_add(&hasher->list, &info->hashers);
494 spin_unlock(&info->hash_lock);
495 return 0;
496}
497#endif
420struct btrfs_root *open_ctree(struct super_block *sb) 498struct btrfs_root *open_ctree(struct super_block *sb)
421{ 499{
422 u32 sectorsize; 500 u32 sectorsize;
@@ -440,6 +518,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
440 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 518 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS);
441 INIT_LIST_HEAD(&fs_info->trans_list); 519 INIT_LIST_HEAD(&fs_info->trans_list);
442 INIT_LIST_HEAD(&fs_info->dead_roots); 520 INIT_LIST_HEAD(&fs_info->dead_roots);
521 INIT_LIST_HEAD(&fs_info->hashers);
522 spin_lock_init(&fs_info->hash_lock);
523
443 memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj)); 524 memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj));
444 init_completion(&fs_info->kobj_unregister); 525 init_completion(&fs_info->kobj_unregister);
445 sb_set_blocksize(sb, 4096); 526 sb_set_blocksize(sb, 4096);
@@ -479,6 +560,14 @@ struct btrfs_root *open_ctree(struct super_block *sb)
479 mutex_init(&fs_info->trans_mutex); 560 mutex_init(&fs_info->trans_mutex);
480 mutex_init(&fs_info->fs_mutex); 561 mutex_init(&fs_info->fs_mutex);
481 562
563#if 0
564 ret = add_hasher(fs_info, "crc32c");
565 if (ret) {
566 printk("btrfs: failed hash setup, modprobe cryptomgr?\n");
567 err = -ENOMEM;
568 goto fail_iput;
569 }
570#endif
482 __setup_root(512, 512, 512, tree_root, 571 __setup_root(512, 512, 512, tree_root,
483 fs_info, BTRFS_ROOT_TREE_OBJECTID); 572 fs_info, BTRFS_ROOT_TREE_OBJECTID);
484 573
@@ -509,25 +598,21 @@ struct btrfs_root *open_ctree(struct super_block *sb)
509 i_size_write(fs_info->btree_inode, 598 i_size_write(fs_info->btree_inode,
510 btrfs_super_total_bytes(disk_super)); 599 btrfs_super_total_bytes(disk_super));
511 600
512
513 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 601 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
514 sizeof(disk_super->magic))) { 602 sizeof(disk_super->magic))) {
515 printk("btrfs: valid FS not found on %s\n", sb->s_id); 603 printk("btrfs: valid FS not found on %s\n", sb->s_id);
516 goto fail_sb_buffer; 604 goto fail_sb_buffer;
517 } 605 }
606
518 blocksize = btrfs_level_size(tree_root, 607 blocksize = btrfs_level_size(tree_root,
519 btrfs_super_root_level(disk_super)); 608 btrfs_super_root_level(disk_super));
609
520 tree_root->node = read_tree_block(tree_root, 610 tree_root->node = read_tree_block(tree_root,
521 btrfs_super_root(disk_super), 611 btrfs_super_root(disk_super),
522 blocksize); 612 blocksize);
523 if (!tree_root->node) 613 if (!tree_root->node)
524 goto fail_sb_buffer; 614 goto fail_sb_buffer;
525 615
526#if 0
527 btrfs_print_leaf(tree_root, tree_root->node);
528 err = -EIO;
529 goto fail_tree_root;
530#endif
531 mutex_lock(&fs_info->fs_mutex); 616 mutex_lock(&fs_info->fs_mutex);
532 617
533 ret = find_and_setup_root(tree_root, fs_info, 618 ret = find_and_setup_root(tree_root, fs_info,
@@ -634,9 +719,19 @@ int close_ctree(struct btrfs_root *root)
634 719
635 btrfs_free_block_groups(root->fs_info); 720 btrfs_free_block_groups(root->fs_info);
636 del_fs_roots(fs_info); 721 del_fs_roots(fs_info);
637 extent_map_tree_cleanup(&BTRFS_I(fs_info->btree_inode)->extent_tree); 722 extent_map_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->extent_tree);
638 truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 723 truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
639 iput(fs_info->btree_inode); 724 iput(fs_info->btree_inode);
725#if 0
726 while(!list_empty(&fs_info->hashers)) {
727 struct btrfs_hasher *hasher;
728 hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher,
729 hashers);
730 list_del(&hasher->hashers);
731 crypto_free_hash(&fs_info->hash_tfm);
732 kfree(hasher);
733 }
734#endif
640 kfree(fs_info->extent_root); 735 kfree(fs_info->extent_root);
641 kfree(fs_info->tree_root); 736 kfree(fs_info->tree_root);
642 return 0; 737 return 0;
@@ -733,5 +828,5 @@ int btrfs_read_buffer(struct extent_buffer *buf)
733 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 828 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
734 struct inode *btree_inode = root->fs_info->btree_inode; 829 struct inode *btree_inode = root->fs_info->btree_inode;
735 return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 830 return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
736 buf, 1); 831 buf, 0, 1);
737} 832}
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e4e68ea96483..6b2f2b414fa1 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1178,6 +1178,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1178 btrfs_set_buffer_uptodate(buf); 1178 btrfs_set_buffer_uptodate(buf);
1179 set_extent_dirty(&trans->transaction->dirty_pages, buf->start, 1179 set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
1180 buf->start + buf->len - 1, GFP_NOFS); 1180 buf->start + buf->len - 1, GFP_NOFS);
1181 set_extent_bits(&BTRFS_I(root->fs_info->btree_inode)->extent_tree,
1182 buf->start, buf->start + buf->len - 1,
1183 EXTENT_CSUM, GFP_NOFS);
1184 buf->flags |= EXTENT_CSUM;
1181 btrfs_set_buffer_defrag(buf); 1185 btrfs_set_buffer_defrag(buf);
1182 trans->blocks_used++; 1186 trans->blocks_used++;
1183 return buf; 1187 return buf;
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index f8aaba8a30a2..2a8bc4bd43a9 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -81,7 +81,7 @@ void extent_map_tree_init(struct extent_map_tree *tree,
81} 81}
82EXPORT_SYMBOL(extent_map_tree_init); 82EXPORT_SYMBOL(extent_map_tree_init);
83 83
84void extent_map_tree_cleanup(struct extent_map_tree *tree) 84void extent_map_tree_empty_lru(struct extent_map_tree *tree)
85{ 85{
86 struct extent_buffer *eb; 86 struct extent_buffer *eb;
87 while(!list_empty(&tree->buffer_lru)) { 87 while(!list_empty(&tree->buffer_lru)) {
@@ -91,7 +91,7 @@ void extent_map_tree_cleanup(struct extent_map_tree *tree)
91 free_extent_buffer(eb); 91 free_extent_buffer(eb);
92 } 92 }
93} 93}
94EXPORT_SYMBOL(extent_map_tree_cleanup); 94EXPORT_SYMBOL(extent_map_tree_empty_lru);
95 95
96struct extent_map *alloc_extent_map(gfp_t mask) 96struct extent_map *alloc_extent_map(gfp_t mask)
97{ 97{
@@ -1464,7 +1464,7 @@ void set_page_extent_mapped(struct page *page)
1464 if (!PagePrivate(page)) { 1464 if (!PagePrivate(page)) {
1465 SetPagePrivate(page); 1465 SetPagePrivate(page);
1466 WARN_ON(!page->mapping->a_ops->invalidatepage); 1466 WARN_ON(!page->mapping->a_ops->invalidatepage);
1467 set_page_private(page, 1); 1467 set_page_private(page, EXTENT_PAGE_PRIVATE);
1468 page_cache_get(page); 1468 page_cache_get(page);
1469 } 1469 }
1470} 1470}
@@ -1979,8 +1979,9 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_map_tree *tree,
1979 1979
1980 spin_lock(&tree->lru_lock); 1980 spin_lock(&tree->lru_lock);
1981 eb = find_lru(tree, start, len); 1981 eb = find_lru(tree, start, len);
1982 if (eb) 1982 if (eb) {
1983 goto lru_add; 1983 goto lru_add;
1984 }
1984 spin_unlock(&tree->lru_lock); 1985 spin_unlock(&tree->lru_lock);
1985 1986
1986 if (eb) { 1987 if (eb) {
@@ -2007,6 +2008,7 @@ static void __free_extent_buffer(struct extent_buffer *eb)
2007 2008
2008struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, 2009struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
2009 u64 start, unsigned long len, 2010 u64 start, unsigned long len,
2011 struct page *page0,
2010 gfp_t mask) 2012 gfp_t mask)
2011{ 2013{
2012 unsigned long num_pages = num_extent_pages(start, len); 2014 unsigned long num_pages = num_extent_pages(start, len);
@@ -2024,7 +2026,18 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
2024 if (eb->flags & EXTENT_BUFFER_FILLED) 2026 if (eb->flags & EXTENT_BUFFER_FILLED)
2025 return eb; 2027 return eb;
2026 2028
2027 for (i = 0; i < num_pages; i++, index++) { 2029 if (page0) {
2030 eb->first_page = page0;
2031 i = 1;
2032 index++;
2033 page_cache_get(page0);
2034 set_page_extent_mapped(page0);
2035 set_page_private(page0, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
2036 len << 2);
2037 } else {
2038 i = 0;
2039 }
2040 for (; i < num_pages; i++, index++) {
2028 p = find_or_create_page(mapping, index, mask | __GFP_HIGHMEM); 2041 p = find_or_create_page(mapping, index, mask | __GFP_HIGHMEM);
2029 if (!p) { 2042 if (!p) {
2030 WARN_ON(1); 2043 WARN_ON(1);
@@ -2036,8 +2049,13 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
2036 goto fail; 2049 goto fail;
2037 } 2050 }
2038 set_page_extent_mapped(p); 2051 set_page_extent_mapped(p);
2039 if (i == 0) 2052 if (i == 0) {
2040 eb->first_page = p; 2053 eb->first_page = p;
2054 set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
2055 len << 2);
2056 } else {
2057 set_page_private(p, EXTENT_PAGE_PRIVATE);
2058 }
2041 if (!PageUptodate(p)) 2059 if (!PageUptodate(p))
2042 uptodate = 0; 2060 uptodate = 0;
2043 unlock_page(p); 2061 unlock_page(p);
@@ -2057,8 +2075,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
2057 gfp_t mask) 2075 gfp_t mask)
2058{ 2076{
2059 unsigned long num_pages = num_extent_pages(start, len); 2077 unsigned long num_pages = num_extent_pages(start, len);
2060 unsigned long i; 2078 unsigned long i; unsigned long index = start >> PAGE_CACHE_SHIFT;
2061 unsigned long index = start >> PAGE_CACHE_SHIFT;
2062 struct extent_buffer *eb; 2079 struct extent_buffer *eb;
2063 struct page *p; 2080 struct page *p;
2064 struct address_space *mapping = tree->mapping; 2081 struct address_space *mapping = tree->mapping;
@@ -2082,8 +2099,15 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
2082 goto fail; 2099 goto fail;
2083 } 2100 }
2084 set_page_extent_mapped(p); 2101 set_page_extent_mapped(p);
2085 if (i == 0) 2102
2103 if (i == 0) {
2086 eb->first_page = p; 2104 eb->first_page = p;
2105 set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
2106 len << 2);
2107 } else {
2108 set_page_private(p, EXTENT_PAGE_PRIVATE);
2109 }
2110
2087 if (!PageUptodate(p)) 2111 if (!PageUptodate(p))
2088 uptodate = 0; 2112 uptodate = 0;
2089 unlock_page(p); 2113 unlock_page(p);
@@ -2174,7 +2198,21 @@ int set_extent_buffer_dirty(struct extent_map_tree *tree,
2174 2198
2175 num_pages = num_extent_pages(eb->start, eb->len); 2199 num_pages = num_extent_pages(eb->start, eb->len);
2176 for (i = 0; i < num_pages; i++) { 2200 for (i = 0; i < num_pages; i++) {
2201 struct page *page = extent_buffer_page(eb, i);
2202 /* writepage may need to do something special for the
2203 * first page, we have to make sure page->private is
2204 * properly set. releasepage may drop page->private
2205 * on us if the page isn't already dirty.
2206 */
2207 if (i == 0) {
2208 lock_page(page);
2209 set_page_private(page,
2210 EXTENT_PAGE_PRIVATE_FIRST_PAGE |
2211 eb->len << 2);
2212 }
2177 __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); 2213 __set_page_dirty_nobuffers(extent_buffer_page(eb, i));
2214 if (i == 0)
2215 unlock_page(page);
2178 } 2216 }
2179 return set_extent_dirty(tree, eb->start, 2217 return set_extent_dirty(tree, eb->start,
2180 eb->start + eb->len - 1, GFP_NOFS); 2218 eb->start + eb->len - 1, GFP_NOFS);
@@ -2217,9 +2255,12 @@ int extent_buffer_uptodate(struct extent_map_tree *tree,
2217EXPORT_SYMBOL(extent_buffer_uptodate); 2255EXPORT_SYMBOL(extent_buffer_uptodate);
2218 2256
2219int read_extent_buffer_pages(struct extent_map_tree *tree, 2257int read_extent_buffer_pages(struct extent_map_tree *tree,
2220 struct extent_buffer *eb, int wait) 2258 struct extent_buffer *eb,
2259 u64 start,
2260 int wait)
2221{ 2261{
2222 unsigned long i; 2262 unsigned long i;
2263 unsigned long start_i;
2223 struct page *page; 2264 struct page *page;
2224 int err; 2265 int err;
2225 int ret = 0; 2266 int ret = 0;
@@ -2232,9 +2273,16 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
2232 EXTENT_UPTODATE, 1)) { 2273 EXTENT_UPTODATE, 1)) {
2233 return 0; 2274 return 0;
2234 } 2275 }
2276 if (start) {
2277 WARN_ON(start < eb->start);
2278 start_i = (start >> PAGE_CACHE_SHIFT) -
2279 (eb->start >> PAGE_CACHE_SHIFT);
2280 } else {
2281 start_i = 0;
2282 }
2235 2283
2236 num_pages = num_extent_pages(eb->start, eb->len); 2284 num_pages = num_extent_pages(eb->start, eb->len);
2237 for (i = 0; i < num_pages; i++) { 2285 for (i = start_i; i < num_pages; i++) {
2238 page = extent_buffer_page(eb, i); 2286 page = extent_buffer_page(eb, i);
2239 if (PageUptodate(page)) { 2287 if (PageUptodate(page)) {
2240 continue; 2288 continue;
@@ -2260,7 +2308,7 @@ int read_extent_buffer_pages(struct extent_map_tree *tree,
2260 return ret; 2308 return ret;
2261 } 2309 }
2262 2310
2263 for (i = 0; i < num_pages; i++) { 2311 for (i = start_i; i < num_pages; i++) {
2264 page = extent_buffer_page(eb, i); 2312 page = extent_buffer_page(eb, i);
2265 wait_on_page_locked(page); 2313 wait_on_page_locked(page);
2266 if (!PageUptodate(page)) { 2314 if (!PageUptodate(page)) {
@@ -2314,7 +2362,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
2314} 2362}
2315EXPORT_SYMBOL(read_extent_buffer); 2363EXPORT_SYMBOL(read_extent_buffer);
2316 2364
2317static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start, 2365int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
2318 unsigned long min_len, char **token, char **map, 2366 unsigned long min_len, char **token, char **map,
2319 unsigned long *map_start, 2367 unsigned long *map_start,
2320 unsigned long *map_len, int km) 2368 unsigned long *map_len, int km)
@@ -2337,6 +2385,10 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2337 offset = 0; 2385 offset = 0;
2338 *map_start = (i << PAGE_CACHE_SHIFT) - start_offset; 2386 *map_start = (i << PAGE_CACHE_SHIFT) - start_offset;
2339 } 2387 }
2388 if (start + min_len >= eb->len) {
2389printk("bad mapping eb start %Lu len %lu, wanted %lu %lu\n", eb->start, eb->len, start, min_len);
2390 WARN_ON(1);
2391 }
2340 2392
2341 p = extent_buffer_page(eb, i); 2393 p = extent_buffer_page(eb, i);
2342 WARN_ON(!PageUptodate(p)); 2394 WARN_ON(!PageUptodate(p));
@@ -2346,6 +2398,7 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2346 *map_len = PAGE_CACHE_SIZE - offset; 2398 *map_len = PAGE_CACHE_SIZE - offset;
2347 return 0; 2399 return 0;
2348} 2400}
2401EXPORT_SYMBOL(map_private_extent_buffer);
2349 2402
2350int map_extent_buffer(struct extent_buffer *eb, unsigned long start, 2403int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2351 unsigned long min_len, 2404 unsigned long min_len,
@@ -2360,8 +2413,8 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2360 eb->map_token = NULL; 2413 eb->map_token = NULL;
2361 save = 1; 2414 save = 1;
2362 } 2415 }
2363 err = __map_extent_buffer(eb, start, min_len, token, map, 2416 err = map_private_extent_buffer(eb, start, min_len, token, map,
2364 map_start, map_len, km); 2417 map_start, map_len, km);
2365 if (!err && save) { 2418 if (!err && save) {
2366 eb->map_token = *token; 2419 eb->map_token = *token;
2367 eb->kaddr = *map; 2420 eb->kaddr = *map;
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index f1dc28d260eb..39d78d31b6a2 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -17,8 +17,17 @@
17#define EXTENT_DEFRAG (1 << 6) 17#define EXTENT_DEFRAG (1 << 6)
18#define EXTENT_DEFRAG_DONE (1 << 7) 18#define EXTENT_DEFRAG_DONE (1 << 7)
19#define EXTENT_BUFFER_FILLED (1 << 8) 19#define EXTENT_BUFFER_FILLED (1 << 8)
20#define EXTENT_CSUM (1 << 9)
20#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) 21#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
21 22
23/*
24 * page->private values. Every page that is controlled by the extent
25 * map has page->private set to one.
26 */
27
28#define EXTENT_PAGE_PRIVATE 1
29#define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3
30
22 31
23struct extent_map_ops { 32struct extent_map_ops {
24 int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); 33 int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
@@ -89,7 +98,7 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode,
89 98
90void extent_map_tree_init(struct extent_map_tree *tree, 99void extent_map_tree_init(struct extent_map_tree *tree,
91 struct address_space *mapping, gfp_t mask); 100 struct address_space *mapping, gfp_t mask);
92void extent_map_tree_cleanup(struct extent_map_tree *tree); 101void extent_map_tree_empty_lru(struct extent_map_tree *tree);
93struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, 102struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
94 u64 start, u64 end); 103 u64 start, u64 end);
95int add_extent_mapping(struct extent_map_tree *tree, 104int add_extent_mapping(struct extent_map_tree *tree,
@@ -143,13 +152,14 @@ void set_page_extent_mapped(struct page *page);
143 152
144struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, 153struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
145 u64 start, unsigned long len, 154 u64 start, unsigned long len,
155 struct page *page0,
146 gfp_t mask); 156 gfp_t mask);
147struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, 157struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
148 u64 start, unsigned long len, 158 u64 start, unsigned long len,
149 gfp_t mask); 159 gfp_t mask);
150void free_extent_buffer(struct extent_buffer *eb); 160void free_extent_buffer(struct extent_buffer *eb);
151int read_extent_buffer_pages(struct extent_map_tree *tree, 161int read_extent_buffer_pages(struct extent_map_tree *tree,
152 struct extent_buffer *eb, int wait); 162 struct extent_buffer *eb, u64 start, int wait);
153 163
154static inline void extent_buffer_get(struct extent_buffer *eb) 164static inline void extent_buffer_get(struct extent_buffer *eb)
155{ 165{
@@ -187,5 +197,9 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
187 unsigned long min_len, char **token, char **map, 197 unsigned long min_len, char **token, char **map,
188 unsigned long *map_start, 198 unsigned long *map_start,
189 unsigned long *map_len, int km); 199 unsigned long *map_len, int km);
200int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
201 unsigned long min_len, char **token, char **map,
202 unsigned long *map_start,
203 unsigned long *map_len, int km);
190void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); 204void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);
191#endif 205#endif
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 84f496c838c9..80f84b48a70f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1713,10 +1713,6 @@ static int btrfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
1713 struct extent_map_tree *tree; 1713 struct extent_map_tree *tree;
1714 int ret; 1714 int ret;
1715 1715
1716 if (page->private != 1) {
1717 WARN_ON(1);
1718 return try_to_free_buffers(page);
1719 }
1720 tree = &BTRFS_I(page->mapping->host)->extent_tree; 1716 tree = &BTRFS_I(page->mapping->host)->extent_tree;
1721 ret = try_release_extent_mapping(tree, page); 1717 ret = try_release_extent_mapping(tree, page);
1722 if (ret == 1) { 1718 if (ret == 1) {