aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:14:19 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit5f39d397dfbe140a14edecd4e73c34ce23c4f9ee (patch)
tree280561e4b68d573590557dd27df656869eed8023 /fs/btrfs/file.c
parent50b78c24d594e6985f36a9a8d8e2fb74e1664e90 (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.c129
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);
128fail: 127fail:
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 *));