diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:14:19 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | 5f39d397dfbe140a14edecd4e73c34ce23c4f9ee (patch) | |
tree | 280561e4b68d573590557dd27df656869eed8023 /fs/btrfs/file.c | |
parent | 50b78c24d594e6985f36a9a8d8e2fb74e1664e90 (diff) |
Btrfs: Create extent_buffer interface for large blocksizes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 129 |
1 files changed, 67 insertions, 62 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4cc459c943ec..1734ca695555 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/buffer_head.h> | ||
20 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
21 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
22 | #include <linux/highmem.h> | 21 | #include <linux/highmem.h> |
@@ -88,7 +87,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
88 | { | 87 | { |
89 | struct btrfs_key key; | 88 | struct btrfs_key key; |
90 | struct btrfs_path *path; | 89 | struct btrfs_path *path; |
91 | char *ptr, *kaddr; | 90 | struct extent_buffer *leaf; |
91 | char *kaddr; | ||
92 | unsigned long ptr; | ||
92 | struct btrfs_file_extent_item *ei; | 93 | struct btrfs_file_extent_item *ei; |
93 | u32 datasize; | 94 | u32 datasize; |
94 | int err = 0; | 95 | int err = 0; |
@@ -102,7 +103,6 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
102 | 103 | ||
103 | key.objectid = inode->i_ino; | 104 | key.objectid = inode->i_ino; |
104 | key.offset = offset; | 105 | key.offset = offset; |
105 | key.flags = 0; | ||
106 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | 106 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); |
107 | BUG_ON(size >= PAGE_CACHE_SIZE); | 107 | BUG_ON(size >= PAGE_CACHE_SIZE); |
108 | datasize = btrfs_file_extent_calc_inline_size(size); | 108 | datasize = btrfs_file_extent_calc_inline_size(size); |
@@ -113,18 +113,17 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
113 | err = ret; | 113 | err = ret; |
114 | goto fail; | 114 | goto fail; |
115 | } | 115 | } |
116 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 116 | leaf = path->nodes[0]; |
117 | path->slots[0], struct btrfs_file_extent_item); | 117 | ei = btrfs_item_ptr(leaf, path->slots[0], |
118 | btrfs_set_file_extent_generation(ei, trans->transid); | 118 | struct btrfs_file_extent_item); |
119 | btrfs_set_file_extent_type(ei, | 119 | btrfs_set_file_extent_generation(leaf, ei, trans->transid); |
120 | BTRFS_FILE_EXTENT_INLINE); | 120 | btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE); |
121 | ptr = btrfs_file_extent_inline_start(ei); | 121 | ptr = btrfs_file_extent_inline_start(ei); |
122 | 122 | ||
123 | kaddr = kmap_atomic(page, KM_USER0); | 123 | kaddr = kmap_atomic(page, KM_USER0); |
124 | btrfs_memcpy(root, path->nodes[0]->b_data, | 124 | write_extent_buffer(leaf, kaddr + page_offset, ptr, size); |
125 | ptr, kaddr + page_offset, size); | ||
126 | kunmap_atomic(kaddr, KM_USER0); | 125 | kunmap_atomic(kaddr, KM_USER0); |
127 | btrfs_mark_buffer_dirty(path->nodes[0]); | 126 | btrfs_mark_buffer_dirty(leaf); |
128 | fail: | 127 | fail: |
129 | btrfs_free_path(path); | 128 | btrfs_free_path(path); |
130 | return err; | 129 | return err; |
@@ -156,8 +155,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
156 | 155 | ||
157 | em->bdev = inode->i_sb->s_bdev; | 156 | em->bdev = inode->i_sb->s_bdev; |
158 | 157 | ||
159 | start_pos = pos & ~((u64)root->blocksize - 1); | 158 | start_pos = pos & ~((u64)root->sectorsize - 1); |
160 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> | 159 | num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> |
161 | inode->i_blkbits; | 160 | inode->i_blkbits; |
162 | 161 | ||
163 | down_read(&BTRFS_I(inode)->root->snap_sem); | 162 | down_read(&BTRFS_I(inode)->root->snap_sem); |
@@ -184,7 +183,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
184 | if (inode->i_size < start_pos) { | 183 | if (inode->i_size < start_pos) { |
185 | u64 last_pos_in_file; | 184 | u64 last_pos_in_file; |
186 | u64 hole_size; | 185 | u64 hole_size; |
187 | u64 mask = root->blocksize - 1; | 186 | u64 mask = root->sectorsize - 1; |
188 | last_pos_in_file = (isize + mask) & ~mask; | 187 | last_pos_in_file = (isize + mask) & ~mask; |
189 | hole_size = (start_pos - last_pos_in_file + mask) & ~mask; | 188 | hole_size = (start_pos - last_pos_in_file + mask) & ~mask; |
190 | 189 | ||
@@ -227,8 +226,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
227 | /* step one, delete the existing extents in this range */ | 226 | /* step one, delete the existing extents in this range */ |
228 | /* FIXME blocksize != pagesize */ | 227 | /* FIXME blocksize != pagesize */ |
229 | err = btrfs_drop_extents(trans, root, inode, start_pos, | 228 | err = btrfs_drop_extents(trans, root, inode, start_pos, |
230 | (pos + write_bytes + root->blocksize -1) & | 229 | (pos + write_bytes + root->sectorsize -1) & |
231 | ~((u64)root->blocksize - 1), &hint_block); | 230 | ~((u64)root->sectorsize - 1), &hint_block); |
232 | if (err) | 231 | if (err) |
233 | goto failed; | 232 | goto failed; |
234 | 233 | ||
@@ -288,7 +287,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, | |||
288 | { | 287 | { |
289 | int ret; | 288 | int ret; |
290 | struct btrfs_key key; | 289 | struct btrfs_key key; |
291 | struct btrfs_leaf *leaf; | 290 | struct extent_buffer *leaf; |
292 | int slot; | 291 | int slot; |
293 | struct btrfs_file_extent_item *extent; | 292 | struct btrfs_file_extent_item *extent; |
294 | u64 extent_end = 0; | 293 | u64 extent_end = 0; |
@@ -327,10 +326,10 @@ next_slot: | |||
327 | found_extent = 0; | 326 | found_extent = 0; |
328 | found_inline = 0; | 327 | found_inline = 0; |
329 | extent = NULL; | 328 | extent = NULL; |
330 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 329 | leaf = path->nodes[0]; |
331 | slot = path->slots[0]; | 330 | slot = path->slots[0]; |
332 | ret = 0; | 331 | ret = 0; |
333 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 332 | btrfs_item_key_to_cpu(leaf, &key, slot); |
334 | if (key.offset >= end || key.objectid != inode->i_ino) { | 333 | if (key.offset >= end || key.objectid != inode->i_ino) { |
335 | goto out; | 334 | goto out; |
336 | } | 335 | } |
@@ -344,17 +343,18 @@ next_slot: | |||
344 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { | 343 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { |
345 | extent = btrfs_item_ptr(leaf, slot, | 344 | extent = btrfs_item_ptr(leaf, slot, |
346 | struct btrfs_file_extent_item); | 345 | struct btrfs_file_extent_item); |
347 | found_type = btrfs_file_extent_type(extent); | 346 | found_type = btrfs_file_extent_type(leaf, extent); |
348 | if (found_type == BTRFS_FILE_EXTENT_REG) { | 347 | if (found_type == BTRFS_FILE_EXTENT_REG) { |
349 | extent_end = key.offset + | 348 | extent_end = key.offset + |
350 | (btrfs_file_extent_num_blocks(extent) << | 349 | (btrfs_file_extent_num_blocks(leaf, extent) << |
351 | inode->i_blkbits); | 350 | inode->i_blkbits); |
352 | found_extent = 1; | 351 | found_extent = 1; |
353 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 352 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
353 | struct btrfs_item *item; | ||
354 | item = btrfs_item_nr(leaf, slot); | ||
354 | found_inline = 1; | 355 | found_inline = 1; |
355 | extent_end = key.offset + | 356 | extent_end = key.offset + |
356 | btrfs_file_extent_inline_len(leaf->items + | 357 | btrfs_file_extent_inline_len(leaf, item); |
357 | slot); | ||
358 | } | 358 | } |
359 | } else { | 359 | } else { |
360 | extent_end = search_start; | 360 | extent_end = search_start; |
@@ -365,8 +365,7 @@ next_slot: | |||
365 | search_start >= extent_end) { | 365 | search_start >= extent_end) { |
366 | int nextret; | 366 | int nextret; |
367 | u32 nritems; | 367 | u32 nritems; |
368 | nritems = btrfs_header_nritems( | 368 | nritems = btrfs_header_nritems(leaf); |
369 | btrfs_buffer_header(path->nodes[0])); | ||
370 | if (slot >= nritems - 1) { | 369 | if (slot >= nritems - 1) { |
371 | nextret = btrfs_next_leaf(root, path); | 370 | nextret = btrfs_next_leaf(root, path); |
372 | if (nextret) | 371 | if (nextret) |
@@ -380,7 +379,7 @@ next_slot: | |||
380 | 379 | ||
381 | /* FIXME, there's only one inline extent allowed right now */ | 380 | /* FIXME, there's only one inline extent allowed right now */ |
382 | if (found_inline) { | 381 | if (found_inline) { |
383 | u64 mask = root->blocksize - 1; | 382 | u64 mask = root->sectorsize - 1; |
384 | search_start = (extent_end + mask) & ~mask; | 383 | search_start = (extent_end + mask) & ~mask; |
385 | } else | 384 | } else |
386 | search_start = extent_end; | 385 | search_start = extent_end; |
@@ -388,10 +387,13 @@ next_slot: | |||
388 | if (end < extent_end && end >= key.offset) { | 387 | if (end < extent_end && end >= key.offset) { |
389 | if (found_extent) { | 388 | if (found_extent) { |
390 | u64 disk_blocknr = | 389 | u64 disk_blocknr = |
391 | btrfs_file_extent_disk_blocknr(extent); | 390 | btrfs_file_extent_disk_blocknr(leaf,extent); |
392 | u64 disk_num_blocks = | 391 | u64 disk_num_blocks = |
393 | btrfs_file_extent_disk_num_blocks(extent); | 392 | btrfs_file_extent_disk_num_blocks(leaf, |
394 | memcpy(&old, extent, sizeof(old)); | 393 | extent); |
394 | read_extent_buffer(leaf, &old, | ||
395 | (unsigned long)extent, | ||
396 | sizeof(old)); | ||
395 | if (disk_blocknr != 0) { | 397 | if (disk_blocknr != 0) { |
396 | ret = btrfs_inc_extent_ref(trans, root, | 398 | ret = btrfs_inc_extent_ref(trans, root, |
397 | disk_blocknr, disk_num_blocks); | 399 | disk_blocknr, disk_num_blocks); |
@@ -406,20 +408,24 @@ next_slot: | |||
406 | u64 new_num; | 408 | u64 new_num; |
407 | u64 old_num; | 409 | u64 old_num; |
408 | keep = 1; | 410 | keep = 1; |
409 | WARN_ON(start & (root->blocksize - 1)); | 411 | WARN_ON(start & (root->sectorsize - 1)); |
410 | if (found_extent) { | 412 | if (found_extent) { |
411 | new_num = (start - key.offset) >> | 413 | new_num = (start - key.offset) >> |
412 | inode->i_blkbits; | 414 | inode->i_blkbits; |
413 | old_num = btrfs_file_extent_num_blocks(extent); | 415 | old_num = btrfs_file_extent_num_blocks(leaf, |
416 | extent); | ||
414 | *hint_block = | 417 | *hint_block = |
415 | btrfs_file_extent_disk_blocknr(extent); | 418 | btrfs_file_extent_disk_blocknr(leaf, |
416 | if (btrfs_file_extent_disk_blocknr(extent)) { | 419 | extent); |
420 | if (btrfs_file_extent_disk_blocknr(leaf, | ||
421 | extent)) { | ||
417 | inode->i_blocks -= | 422 | inode->i_blocks -= |
418 | (old_num - new_num) << 3; | 423 | (old_num - new_num) << 3; |
419 | } | 424 | } |
420 | btrfs_set_file_extent_num_blocks(extent, | 425 | btrfs_set_file_extent_num_blocks(leaf, |
426 | extent, | ||
421 | new_num); | 427 | new_num); |
422 | btrfs_mark_buffer_dirty(path->nodes[0]); | 428 | btrfs_mark_buffer_dirty(leaf); |
423 | } else { | 429 | } else { |
424 | WARN_ON(1); | 430 | WARN_ON(1); |
425 | } | 431 | } |
@@ -431,13 +437,17 @@ next_slot: | |||
431 | u64 extent_num_blocks = 0; | 437 | u64 extent_num_blocks = 0; |
432 | if (found_extent) { | 438 | if (found_extent) { |
433 | disk_blocknr = | 439 | disk_blocknr = |
434 | btrfs_file_extent_disk_blocknr(extent); | 440 | btrfs_file_extent_disk_blocknr(leaf, |
441 | extent); | ||
435 | disk_num_blocks = | 442 | disk_num_blocks = |
436 | btrfs_file_extent_disk_num_blocks(extent); | 443 | btrfs_file_extent_disk_num_blocks(leaf, |
444 | extent); | ||
437 | extent_num_blocks = | 445 | extent_num_blocks = |
438 | btrfs_file_extent_num_blocks(extent); | 446 | btrfs_file_extent_num_blocks(leaf, |
447 | extent); | ||
439 | *hint_block = | 448 | *hint_block = |
440 | btrfs_file_extent_disk_blocknr(extent); | 449 | btrfs_file_extent_disk_blocknr(leaf, |
450 | extent); | ||
441 | } | 451 | } |
442 | ret = btrfs_del_item(trans, root, path); | 452 | ret = btrfs_del_item(trans, root, path); |
443 | /* TODO update progress marker and return */ | 453 | /* TODO update progress marker and return */ |
@@ -464,42 +474,37 @@ next_slot: | |||
464 | struct btrfs_key ins; | 474 | struct btrfs_key ins; |
465 | ins.objectid = inode->i_ino; | 475 | ins.objectid = inode->i_ino; |
466 | ins.offset = end; | 476 | ins.offset = end; |
467 | ins.flags = 0; | ||
468 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | 477 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); |
469 | btrfs_release_path(root, path); | 478 | btrfs_release_path(root, path); |
470 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 479 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
471 | sizeof(*extent)); | 480 | sizeof(*extent)); |
472 | 481 | ||
482 | leaf = path->nodes[0]; | ||
473 | if (ret) { | 483 | if (ret) { |
474 | btrfs_print_leaf(root, btrfs_buffer_leaf(path->nodes[0])); | 484 | btrfs_print_leaf(root, leaf); |
475 | printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.flags, ins.offset, start, end, key.offset, extent_end, keep); | 485 | printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.type, ins.offset, start, end, key.offset, extent_end, keep); |
476 | } | 486 | } |
477 | BUG_ON(ret); | 487 | BUG_ON(ret); |
478 | extent = btrfs_item_ptr( | 488 | extent = btrfs_item_ptr(leaf, path->slots[0], |
479 | btrfs_buffer_leaf(path->nodes[0]), | 489 | struct btrfs_file_extent_item); |
480 | path->slots[0], | 490 | write_extent_buffer(leaf, &old, |
481 | struct btrfs_file_extent_item); | 491 | (unsigned long)extent, sizeof(old)); |
482 | btrfs_set_file_extent_disk_blocknr(extent, | 492 | |
483 | btrfs_file_extent_disk_blocknr(&old)); | 493 | btrfs_set_file_extent_offset(leaf, extent, |
484 | btrfs_set_file_extent_disk_num_blocks(extent, | 494 | le64_to_cpu(old.offset) + |
485 | btrfs_file_extent_disk_num_blocks(&old)); | ||
486 | |||
487 | btrfs_set_file_extent_offset(extent, | ||
488 | btrfs_file_extent_offset(&old) + | ||
489 | ((end - key.offset) >> inode->i_blkbits)); | 495 | ((end - key.offset) >> inode->i_blkbits)); |
490 | WARN_ON(btrfs_file_extent_num_blocks(&old) < | 496 | WARN_ON(le64_to_cpu(old.num_blocks) < |
491 | (extent_end - end) >> inode->i_blkbits); | 497 | (extent_end - end) >> inode->i_blkbits); |
492 | btrfs_set_file_extent_num_blocks(extent, | 498 | btrfs_set_file_extent_num_blocks(leaf, extent, |
493 | (extent_end - end) >> inode->i_blkbits); | 499 | (extent_end - end) >> inode->i_blkbits); |
494 | 500 | ||
495 | btrfs_set_file_extent_type(extent, | 501 | btrfs_set_file_extent_type(leaf, extent, |
496 | BTRFS_FILE_EXTENT_REG); | 502 | BTRFS_FILE_EXTENT_REG); |
497 | btrfs_set_file_extent_generation(extent, | ||
498 | btrfs_file_extent_generation(&old)); | ||
499 | btrfs_mark_buffer_dirty(path->nodes[0]); | 503 | btrfs_mark_buffer_dirty(path->nodes[0]); |
500 | if (btrfs_file_extent_disk_blocknr(&old) != 0) { | 504 | if (le64_to_cpu(old.disk_blocknr) != 0) { |
501 | inode->i_blocks += | 505 | inode->i_blocks += |
502 | btrfs_file_extent_num_blocks(extent) << 3; | 506 | btrfs_file_extent_num_blocks(leaf, |
507 | extent) << 3; | ||
503 | } | 508 | } |
504 | ret = 0; | 509 | ret = 0; |
505 | goto out; | 510 | goto out; |
@@ -529,8 +534,8 @@ static int prepare_pages(struct btrfs_root *root, | |||
529 | u64 num_blocks; | 534 | u64 num_blocks; |
530 | u64 start_pos; | 535 | u64 start_pos; |
531 | 536 | ||
532 | start_pos = pos & ~((u64)root->blocksize - 1); | 537 | start_pos = pos & ~((u64)root->sectorsize - 1); |
533 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> | 538 | num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> |
534 | inode->i_blkbits; | 539 | inode->i_blkbits; |
535 | 540 | ||
536 | memset(pages, 0, num_pages * sizeof(struct page *)); | 541 | memset(pages, 0, num_pages * sizeof(struct page *)); |