diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-08-30 08:50:51 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-08-30 08:50:51 -0400 |
commit | 07157aacb1ecd394a5494910b5f80d7e7d407d37 (patch) | |
tree | dc27c45e8b24167b13d89b0e7c3c3a94b293ce29 /fs/btrfs/extent_map.c | |
parent | 95e0528919cb0c7635b37496e0ad1c41e4c0dd7c (diff) |
Btrfs: Add file data csums back in via hooks in the extent map code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_map.c')
-rw-r--r-- | fs/btrfs/extent_map.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index a9c7419615b9..6053f9db0739 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -57,7 +57,7 @@ void extent_map_tree_init(struct extent_map_tree *tree, | |||
57 | { | 57 | { |
58 | tree->map.rb_node = NULL; | 58 | tree->map.rb_node = NULL; |
59 | tree->state.rb_node = NULL; | 59 | tree->state.rb_node = NULL; |
60 | tree->fill_delalloc = NULL; | 60 | tree->ops = NULL; |
61 | rwlock_init(&tree->lock); | 61 | rwlock_init(&tree->lock); |
62 | tree->mapping = mapping; | 62 | tree->mapping = mapping; |
63 | } | 63 | } |
@@ -93,6 +93,7 @@ struct extent_state *alloc_extent_state(gfp_t mask) | |||
93 | return state; | 93 | return state; |
94 | state->state = 0; | 94 | state->state = 0; |
95 | state->in_tree = 0; | 95 | state->in_tree = 0; |
96 | state->private = 0; | ||
96 | atomic_set(&state->refs, 1); | 97 | atomic_set(&state->refs, 1); |
97 | init_waitqueue_head(&state->wq); | 98 | init_waitqueue_head(&state->wq); |
98 | return state; | 99 | return state; |
@@ -1034,6 +1035,61 @@ int unlock_range(struct extent_map_tree *tree, u64 start, u64 end) | |||
1034 | } | 1035 | } |
1035 | EXPORT_SYMBOL(unlock_range); | 1036 | EXPORT_SYMBOL(unlock_range); |
1036 | 1037 | ||
1038 | int set_state_private(struct extent_map_tree *tree, u64 start, u64 private) | ||
1039 | { | ||
1040 | struct rb_node *node; | ||
1041 | struct extent_state *state; | ||
1042 | int ret = 0; | ||
1043 | |||
1044 | write_lock_irq(&tree->lock); | ||
1045 | /* | ||
1046 | * this search will find all the extents that end after | ||
1047 | * our range starts. | ||
1048 | */ | ||
1049 | node = tree_search(&tree->state, start); | ||
1050 | if (!node || IS_ERR(node)) { | ||
1051 | ret = -ENOENT; | ||
1052 | goto out; | ||
1053 | } | ||
1054 | state = rb_entry(node, struct extent_state, rb_node); | ||
1055 | if (state->start != start) { | ||
1056 | ret = -ENOENT; | ||
1057 | goto out; | ||
1058 | } | ||
1059 | state->private = private; | ||
1060 | out: | ||
1061 | write_unlock_irq(&tree->lock); | ||
1062 | return ret; | ||
1063 | |||
1064 | } | ||
1065 | |||
1066 | int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private) | ||
1067 | { | ||
1068 | struct rb_node *node; | ||
1069 | struct extent_state *state; | ||
1070 | int ret = 0; | ||
1071 | |||
1072 | read_lock_irq(&tree->lock); | ||
1073 | /* | ||
1074 | * this search will find all the extents that end after | ||
1075 | * our range starts. | ||
1076 | */ | ||
1077 | node = tree_search(&tree->state, start); | ||
1078 | if (!node || IS_ERR(node)) { | ||
1079 | ret = -ENOENT; | ||
1080 | goto out; | ||
1081 | } | ||
1082 | state = rb_entry(node, struct extent_state, rb_node); | ||
1083 | if (state->start != start) { | ||
1084 | ret = -ENOENT; | ||
1085 | goto out; | ||
1086 | } | ||
1087 | *private = state->private; | ||
1088 | out: | ||
1089 | read_unlock_irq(&tree->lock); | ||
1090 | return ret; | ||
1091 | } | ||
1092 | |||
1037 | /* | 1093 | /* |
1038 | * searches a range in the state tree for a given mask. | 1094 | * searches a range in the state tree for a given mask. |
1039 | * If 'filled' == 1, this returns 1 only if ever extent in the tree | 1095 | * If 'filled' == 1, this returns 1 only if ever extent in the tree |
@@ -1185,12 +1241,13 @@ static int end_bio_extent_writepage(struct bio *bio, | |||
1185 | static int end_bio_extent_readpage(struct bio *bio, | 1241 | static int end_bio_extent_readpage(struct bio *bio, |
1186 | unsigned int bytes_done, int err) | 1242 | unsigned int bytes_done, int err) |
1187 | { | 1243 | { |
1188 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 1244 | int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
1189 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 1245 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
1190 | struct extent_map_tree *tree = bio->bi_private; | 1246 | struct extent_map_tree *tree = bio->bi_private; |
1191 | u64 start; | 1247 | u64 start; |
1192 | u64 end; | 1248 | u64 end; |
1193 | int whole_page; | 1249 | int whole_page; |
1250 | int ret; | ||
1194 | 1251 | ||
1195 | if (bio->bi_size) | 1252 | if (bio->bi_size) |
1196 | return 1; | 1253 | return 1; |
@@ -1208,6 +1265,11 @@ static int end_bio_extent_readpage(struct bio *bio, | |||
1208 | if (--bvec >= bio->bi_io_vec) | 1265 | if (--bvec >= bio->bi_io_vec) |
1209 | prefetchw(&bvec->bv_page->flags); | 1266 | prefetchw(&bvec->bv_page->flags); |
1210 | 1267 | ||
1268 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { | ||
1269 | ret = tree->ops->readpage_end_io_hook(page, start, end); | ||
1270 | if (ret) | ||
1271 | uptodate = 0; | ||
1272 | } | ||
1211 | if (uptodate) { | 1273 | if (uptodate) { |
1212 | set_extent_uptodate(tree, start, end, GFP_ATOMIC); | 1274 | set_extent_uptodate(tree, start, end, GFP_ATOMIC); |
1213 | if (whole_page) | 1275 | if (whole_page) |
@@ -1388,9 +1450,16 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page, | |||
1388 | continue; | 1450 | continue; |
1389 | } | 1451 | } |
1390 | 1452 | ||
1391 | ret = submit_extent_page(READ, tree, page, | 1453 | ret = 0; |
1392 | sector, iosize, page_offset, bdev, | 1454 | if (tree->ops && tree->ops->readpage_io_hook) { |
1393 | end_bio_extent_readpage); | 1455 | ret = tree->ops->readpage_io_hook(page, cur, |
1456 | cur + iosize - 1); | ||
1457 | } | ||
1458 | if (!ret) { | ||
1459 | ret = submit_extent_page(READ, tree, page, | ||
1460 | sector, iosize, page_offset, | ||
1461 | bdev, end_bio_extent_readpage); | ||
1462 | } | ||
1394 | if (ret) | 1463 | if (ret) |
1395 | SetPageError(page); | 1464 | SetPageError(page); |
1396 | cur = cur + iosize; | 1465 | cur = cur + iosize; |
@@ -1462,7 +1531,7 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1462 | &delalloc_end, | 1531 | &delalloc_end, |
1463 | 128 * 1024 * 1024); | 1532 | 128 * 1024 * 1024); |
1464 | if (nr_delalloc) { | 1533 | if (nr_delalloc) { |
1465 | tree->fill_delalloc(inode, start, delalloc_end); | 1534 | tree->ops->fill_delalloc(inode, start, delalloc_end); |
1466 | if (delalloc_end >= page_end + 1) { | 1535 | if (delalloc_end >= page_end + 1) { |
1467 | clear_extent_bit(tree, page_end + 1, delalloc_end, | 1536 | clear_extent_bit(tree, page_end + 1, delalloc_end, |
1468 | EXTENT_LOCKED | EXTENT_DELALLOC, | 1537 | EXTENT_LOCKED | EXTENT_DELALLOC, |
@@ -1528,12 +1597,17 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1528 | continue; | 1597 | continue; |
1529 | } | 1598 | } |
1530 | clear_extent_dirty(tree, cur, cur + iosize - 1, GFP_NOFS); | 1599 | clear_extent_dirty(tree, cur, cur + iosize - 1, GFP_NOFS); |
1531 | set_range_writeback(tree, cur, cur + iosize - 1); | 1600 | ret = tree->ops->writepage_io_hook(page, cur, cur + iosize - 1); |
1532 | ret = submit_extent_page(WRITE, tree, page, | ||
1533 | sector, iosize, page_offset, bdev, | ||
1534 | end_bio_extent_writepage); | ||
1535 | if (ret) | 1601 | if (ret) |
1536 | SetPageError(page); | 1602 | SetPageError(page); |
1603 | else { | ||
1604 | set_range_writeback(tree, cur, cur + iosize - 1); | ||
1605 | ret = submit_extent_page(WRITE, tree, page, sector, | ||
1606 | iosize, page_offset, bdev, | ||
1607 | end_bio_extent_writepage); | ||
1608 | if (ret) | ||
1609 | SetPageError(page); | ||
1610 | } | ||
1537 | cur = cur + iosize; | 1611 | cur = cur + iosize; |
1538 | page_offset += iosize; | 1612 | page_offset += iosize; |
1539 | nr++; | 1613 | nr++; |