file.c (5f39d397dfbe140a14edecd4e73c34ce23c4f9ee) | file.c (db94535db75e67fab12ccbb7f5ee548e33fed891) |
---|---|
1/* 2 * Copyright (C) 2007 Oracle. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, --- 106 unchanged lines hidden (view full) --- 115 } 116 leaf = path->nodes[0]; 117 ei = btrfs_item_ptr(leaf, path->slots[0], 118 struct btrfs_file_extent_item); 119 btrfs_set_file_extent_generation(leaf, ei, trans->transid); 120 btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE); 121 ptr = btrfs_file_extent_inline_start(ei); 122 | 1/* 2 * Copyright (C) 2007 Oracle. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, --- 106 unchanged lines hidden (view full) --- 115 } 116 leaf = path->nodes[0]; 117 ei = btrfs_item_ptr(leaf, path->slots[0], 118 struct btrfs_file_extent_item); 119 btrfs_set_file_extent_generation(leaf, ei, trans->transid); 120 btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE); 121 ptr = btrfs_file_extent_inline_start(ei); 122 |
123 kaddr = kmap_atomic(page, KM_USER0); | 123 kaddr = kmap_atomic(page, KM_USER1); |
124 write_extent_buffer(leaf, kaddr + page_offset, ptr, size); | 124 write_extent_buffer(leaf, kaddr + page_offset, ptr, size); |
125 kunmap_atomic(kaddr, KM_USER0); | 125 kunmap_atomic(kaddr, KM_USER1); |
126 btrfs_mark_buffer_dirty(leaf); 127fail: 128 btrfs_free_path(path); 129 return err; 130} 131 132static int dirty_and_release_pages(struct btrfs_trans_handle *trans, 133 struct btrfs_root *root, 134 struct file *file, 135 struct page **pages, 136 size_t num_pages, 137 loff_t pos, 138 size_t write_bytes) 139{ 140 int err = 0; 141 int i; 142 struct inode *inode = file->f_path.dentry->d_inode; 143 struct extent_map *em; 144 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 126 btrfs_mark_buffer_dirty(leaf); 127fail: 128 btrfs_free_path(path); 129 return err; 130} 131 132static int dirty_and_release_pages(struct btrfs_trans_handle *trans, 133 struct btrfs_root *root, 134 struct file *file, 135 struct page **pages, 136 size_t num_pages, 137 loff_t pos, 138 size_t write_bytes) 139{ 140 int err = 0; 141 int i; 142 struct inode *inode = file->f_path.dentry->d_inode; 143 struct extent_map *em; 144 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
145 u64 hint_block; 146 u64 num_blocks; | 145 u64 hint_byte; 146 u64 num_bytes; |
147 u64 start_pos; 148 u64 end_of_last_block; 149 u64 end_pos = pos + write_bytes; | 147 u64 start_pos; 148 u64 end_of_last_block; 149 u64 end_pos = pos + write_bytes; |
150 u32 inline_size; |
|
150 loff_t isize = i_size_read(inode); 151 152 em = alloc_extent_map(GFP_NOFS); 153 if (!em) 154 return -ENOMEM; 155 156 em->bdev = inode->i_sb->s_bdev; 157 158 start_pos = pos & ~((u64)root->sectorsize - 1); | 151 loff_t isize = i_size_read(inode); 152 153 em = alloc_extent_map(GFP_NOFS); 154 if (!em) 155 return -ENOMEM; 156 157 em->bdev = inode->i_sb->s_bdev; 158 159 start_pos = pos & ~((u64)root->sectorsize - 1); |
159 num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> 160 inode->i_blkbits; | 160 num_bytes = (write_bytes + pos - start_pos + 161 root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
161 162 down_read(&BTRFS_I(inode)->root->snap_sem); | 162 163 down_read(&BTRFS_I(inode)->root->snap_sem); |
163 end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1; | 164 end_of_last_block = start_pos + num_bytes - 1; 165 |
164 lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS); 165 mutex_lock(&root->fs_info->fs_mutex); 166 trans = btrfs_start_transaction(root, 1); 167 if (!trans) { 168 err = -ENOMEM; 169 goto out_unlock; 170 } 171 btrfs_set_trans_block_group(trans, inode); | 166 lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS); 167 mutex_lock(&root->fs_info->fs_mutex); 168 trans = btrfs_start_transaction(root, 1); 169 if (!trans) { 170 err = -ENOMEM; 171 goto out_unlock; 172 } 173 btrfs_set_trans_block_group(trans, inode); |
172 inode->i_blocks += num_blocks << 3; 173 hint_block = 0; | 174 inode->i_blocks += num_bytes >> 9; 175 hint_byte = 0; |
174 175 if ((end_of_last_block & 4095) == 0) { 176 printk("strange end of last %Lu %zu %Lu\n", start_pos, write_bytes, end_of_last_block); 177 } 178 set_extent_uptodate(em_tree, start_pos, end_of_last_block, GFP_NOFS); 179 180 /* FIXME...EIEIO, ENOSPC and more */ 181 --- 4 unchanged lines hidden (view full) --- 186 u64 mask = root->sectorsize - 1; 187 last_pos_in_file = (isize + mask) & ~mask; 188 hole_size = (start_pos - last_pos_in_file + mask) & ~mask; 189 190 if (last_pos_in_file < start_pos) { 191 err = btrfs_drop_extents(trans, root, inode, 192 last_pos_in_file, 193 last_pos_in_file + hole_size, | 176 177 if ((end_of_last_block & 4095) == 0) { 178 printk("strange end of last %Lu %zu %Lu\n", start_pos, write_bytes, end_of_last_block); 179 } 180 set_extent_uptodate(em_tree, start_pos, end_of_last_block, GFP_NOFS); 181 182 /* FIXME...EIEIO, ENOSPC and more */ 183 --- 4 unchanged lines hidden (view full) --- 188 u64 mask = root->sectorsize - 1; 189 last_pos_in_file = (isize + mask) & ~mask; 190 hole_size = (start_pos - last_pos_in_file + mask) & ~mask; 191 192 if (last_pos_in_file < start_pos) { 193 err = btrfs_drop_extents(trans, root, inode, 194 last_pos_in_file, 195 last_pos_in_file + hole_size, |
194 &hint_block); | 196 &hint_byte); |
195 if (err) 196 goto failed; 197 | 197 if (err) 198 goto failed; 199 |
198 hole_size >>= inode->i_blkbits; | |
199 err = btrfs_insert_file_extent(trans, root, 200 inode->i_ino, 201 last_pos_in_file, 202 0, 0, hole_size); 203 } 204 if (err) 205 goto failed; 206 } 207 208 /* 209 * either allocate an extent for the new bytes or setup the key 210 * to show we are doing inline data in the extent 211 */ | 200 err = btrfs_insert_file_extent(trans, root, 201 inode->i_ino, 202 last_pos_in_file, 203 0, 0, hole_size); 204 } 205 if (err) 206 goto failed; 207 } 208 209 /* 210 * either allocate an extent for the new bytes or setup the key 211 * to show we are doing inline data in the extent 212 */ |
213 inline_size = end_pos - start_pos; |
|
212 if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size || | 214 if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size || |
213 pos + write_bytes - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { | 215 inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root) || 216 inline_size >= PAGE_CACHE_SIZE) { |
214 u64 last_end; 215 for (i = 0; i < num_pages; i++) { 216 struct page *p = pages[i]; 217 SetPageUptodate(p); 218 set_page_dirty(p); 219 } 220 last_end = pages[num_pages -1]->index << PAGE_CACHE_SHIFT; 221 last_end += PAGE_CACHE_SIZE - 1; 222 set_extent_delalloc(em_tree, start_pos, end_of_last_block, 223 GFP_NOFS); 224 } else { 225 struct page *p = pages[0]; 226 /* step one, delete the existing extents in this range */ | 217 u64 last_end; 218 for (i = 0; i < num_pages; i++) { 219 struct page *p = pages[i]; 220 SetPageUptodate(p); 221 set_page_dirty(p); 222 } 223 last_end = pages[num_pages -1]->index << PAGE_CACHE_SHIFT; 224 last_end += PAGE_CACHE_SIZE - 1; 225 set_extent_delalloc(em_tree, start_pos, end_of_last_block, 226 GFP_NOFS); 227 } else { 228 struct page *p = pages[0]; 229 /* step one, delete the existing extents in this range */ |
227 /* FIXME blocksize != pagesize */ | |
228 err = btrfs_drop_extents(trans, root, inode, start_pos, 229 (pos + write_bytes + root->sectorsize -1) & | 230 err = btrfs_drop_extents(trans, root, inode, start_pos, 231 (pos + write_bytes + root->sectorsize -1) & |
230 ~((u64)root->sectorsize - 1), &hint_block); | 232 ~((u64)root->sectorsize - 1), &hint_byte); |
231 if (err) 232 goto failed; 233 234 err = insert_inline_extent(trans, root, inode, start_pos, 235 end_pos - start_pos, p, 0); 236 BUG_ON(err); 237 em->start = start_pos; 238 em->end = end_pos - 1; --- 39 unchanged lines hidden (view full) --- 278 * that would be a good hint to the block allocator for this file. 279 * 280 * If an extent intersects the range but is not entirely inside the range 281 * it is either truncated or split. Anything entirely inside the range 282 * is deleted from the tree. 283 */ 284int btrfs_drop_extents(struct btrfs_trans_handle *trans, 285 struct btrfs_root *root, struct inode *inode, | 233 if (err) 234 goto failed; 235 236 err = insert_inline_extent(trans, root, inode, start_pos, 237 end_pos - start_pos, p, 0); 238 BUG_ON(err); 239 em->start = start_pos; 240 em->end = end_pos - 1; --- 39 unchanged lines hidden (view full) --- 280 * that would be a good hint to the block allocator for this file. 281 * 282 * If an extent intersects the range but is not entirely inside the range 283 * it is either truncated or split. Anything entirely inside the range 284 * is deleted from the tree. 285 */ 286int btrfs_drop_extents(struct btrfs_trans_handle *trans, 287 struct btrfs_root *root, struct inode *inode, |
286 u64 start, u64 end, u64 *hint_block) | 288 u64 start, u64 end, u64 *hint_byte) |
287{ 288 int ret; 289 struct btrfs_key key; 290 struct extent_buffer *leaf; 291 int slot; 292 struct btrfs_file_extent_item *extent; 293 u64 extent_end = 0; 294 int keep; --- 46 unchanged lines hidden (view full) --- 341 continue; 342 } 343 if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { 344 extent = btrfs_item_ptr(leaf, slot, 345 struct btrfs_file_extent_item); 346 found_type = btrfs_file_extent_type(leaf, extent); 347 if (found_type == BTRFS_FILE_EXTENT_REG) { 348 extent_end = key.offset + | 289{ 290 int ret; 291 struct btrfs_key key; 292 struct extent_buffer *leaf; 293 int slot; 294 struct btrfs_file_extent_item *extent; 295 u64 extent_end = 0; 296 int keep; --- 46 unchanged lines hidden (view full) --- 343 continue; 344 } 345 if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { 346 extent = btrfs_item_ptr(leaf, slot, 347 struct btrfs_file_extent_item); 348 found_type = btrfs_file_extent_type(leaf, extent); 349 if (found_type == BTRFS_FILE_EXTENT_REG) { 350 extent_end = key.offset + |
349 (btrfs_file_extent_num_blocks(leaf, extent) << 350 inode->i_blkbits); | 351 btrfs_file_extent_num_bytes(leaf, extent); |
351 found_extent = 1; 352 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { 353 struct btrfs_item *item; 354 item = btrfs_item_nr(leaf, slot); 355 found_inline = 1; 356 extent_end = key.offset + 357 btrfs_file_extent_inline_len(leaf, item); 358 } --- 22 unchanged lines hidden (view full) --- 381 if (found_inline) { 382 u64 mask = root->sectorsize - 1; 383 search_start = (extent_end + mask) & ~mask; 384 } else 385 search_start = extent_end; 386 387 if (end < extent_end && end >= key.offset) { 388 if (found_extent) { | 352 found_extent = 1; 353 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { 354 struct btrfs_item *item; 355 item = btrfs_item_nr(leaf, slot); 356 found_inline = 1; 357 extent_end = key.offset + 358 btrfs_file_extent_inline_len(leaf, item); 359 } --- 22 unchanged lines hidden (view full) --- 382 if (found_inline) { 383 u64 mask = root->sectorsize - 1; 384 search_start = (extent_end + mask) & ~mask; 385 } else 386 search_start = extent_end; 387 388 if (end < extent_end && end >= key.offset) { 389 if (found_extent) { |
389 u64 disk_blocknr = 390 btrfs_file_extent_disk_blocknr(leaf,extent); 391 u64 disk_num_blocks = 392 btrfs_file_extent_disk_num_blocks(leaf, | 390 u64 disk_bytenr = 391 btrfs_file_extent_disk_bytenr(leaf, extent); 392 u64 disk_num_bytes = 393 btrfs_file_extent_disk_num_bytes(leaf, |
393 extent); 394 read_extent_buffer(leaf, &old, 395 (unsigned long)extent, 396 sizeof(old)); | 394 extent); 395 read_extent_buffer(leaf, &old, 396 (unsigned long)extent, 397 sizeof(old)); |
397 if (disk_blocknr != 0) { | 398 if (disk_bytenr != 0) { |
398 ret = btrfs_inc_extent_ref(trans, root, | 399 ret = btrfs_inc_extent_ref(trans, root, |
399 disk_blocknr, disk_num_blocks); | 400 disk_bytenr, disk_num_bytes); |
400 BUG_ON(ret); 401 } 402 } 403 WARN_ON(found_inline); 404 bookend = 1; 405 } 406 /* truncate existing extent */ 407 if (start > key.offset) { 408 u64 new_num; 409 u64 old_num; 410 keep = 1; 411 WARN_ON(start & (root->sectorsize - 1)); 412 if (found_extent) { | 401 BUG_ON(ret); 402 } 403 } 404 WARN_ON(found_inline); 405 bookend = 1; 406 } 407 /* truncate existing extent */ 408 if (start > key.offset) { 409 u64 new_num; 410 u64 old_num; 411 keep = 1; 412 WARN_ON(start & (root->sectorsize - 1)); 413 if (found_extent) { |
413 new_num = (start - key.offset) >> 414 inode->i_blkbits; 415 old_num = btrfs_file_extent_num_blocks(leaf, 416 extent); 417 *hint_block = 418 btrfs_file_extent_disk_blocknr(leaf, 419 extent); 420 if (btrfs_file_extent_disk_blocknr(leaf, 421 extent)) { | 414 new_num = start - key.offset; 415 old_num = btrfs_file_extent_num_bytes(leaf, 416 extent); 417 *hint_byte = 418 btrfs_file_extent_disk_bytenr(leaf, 419 extent); 420 if (btrfs_file_extent_disk_bytenr(leaf, 421 extent)) { |
422 inode->i_blocks -= | 422 inode->i_blocks -= |
423 (old_num - new_num) << 3; | 423 (old_num - new_num) >> 9; |
424 } | 424 } |
425 btrfs_set_file_extent_num_blocks(leaf, 426 extent, 427 new_num); | 425 btrfs_set_file_extent_num_bytes(leaf, extent, 426 new_num); |
428 btrfs_mark_buffer_dirty(leaf); 429 } else { 430 WARN_ON(1); 431 } 432 } 433 /* delete the entire extent */ 434 if (!keep) { | 427 btrfs_mark_buffer_dirty(leaf); 428 } else { 429 WARN_ON(1); 430 } 431 } 432 /* delete the entire extent */ 433 if (!keep) { |
435 u64 disk_blocknr = 0; 436 u64 disk_num_blocks = 0; 437 u64 extent_num_blocks = 0; | 434 u64 disk_bytenr = 0; 435 u64 disk_num_bytes = 0; 436 u64 extent_num_bytes = 0; |
438 if (found_extent) { | 437 if (found_extent) { |
439 disk_blocknr = 440 btrfs_file_extent_disk_blocknr(leaf, | 438 disk_bytenr = 439 btrfs_file_extent_disk_bytenr(leaf, |
441 extent); | 440 extent); |
442 disk_num_blocks = 443 btrfs_file_extent_disk_num_blocks(leaf, 444 extent); 445 extent_num_blocks = 446 btrfs_file_extent_num_blocks(leaf, 447 extent); 448 *hint_block = 449 btrfs_file_extent_disk_blocknr(leaf, | 441 disk_num_bytes = 442 btrfs_file_extent_disk_num_bytes(leaf, |
450 extent); | 443 extent); |
444 extent_num_bytes = 445 btrfs_file_extent_num_bytes(leaf, extent); 446 *hint_byte = 447 btrfs_file_extent_disk_bytenr(leaf, 448 extent); |
|
451 } 452 ret = btrfs_del_item(trans, root, path); 453 /* TODO update progress marker and return */ 454 BUG_ON(ret); 455 btrfs_release_path(root, path); 456 extent = NULL; | 449 } 450 ret = btrfs_del_item(trans, root, path); 451 /* TODO update progress marker and return */ 452 BUG_ON(ret); 453 btrfs_release_path(root, path); 454 extent = NULL; |
457 if (found_extent && disk_blocknr != 0) { 458 inode->i_blocks -= extent_num_blocks << 3; | 455 if (found_extent && disk_bytenr != 0) { 456 inode->i_blocks -= extent_num_bytes >> 9; |
459 ret = btrfs_free_extent(trans, root, | 457 ret = btrfs_free_extent(trans, root, |
460 disk_blocknr, 461 disk_num_blocks, 0); | 458 disk_bytenr, 459 disk_num_bytes, 0); |
462 } 463 464 BUG_ON(ret); 465 if (!bookend && search_start >= end) { 466 ret = 0; 467 goto out; 468 } 469 if (!bookend) --- 16 unchanged lines hidden (view full) --- 486 } 487 BUG_ON(ret); 488 extent = btrfs_item_ptr(leaf, path->slots[0], 489 struct btrfs_file_extent_item); 490 write_extent_buffer(leaf, &old, 491 (unsigned long)extent, sizeof(old)); 492 493 btrfs_set_file_extent_offset(leaf, extent, | 460 } 461 462 BUG_ON(ret); 463 if (!bookend && search_start >= end) { 464 ret = 0; 465 goto out; 466 } 467 if (!bookend) --- 16 unchanged lines hidden (view full) --- 484 } 485 BUG_ON(ret); 486 extent = btrfs_item_ptr(leaf, path->slots[0], 487 struct btrfs_file_extent_item); 488 write_extent_buffer(leaf, &old, 489 (unsigned long)extent, sizeof(old)); 490 491 btrfs_set_file_extent_offset(leaf, extent, |
494 le64_to_cpu(old.offset) + 495 ((end - key.offset) >> inode->i_blkbits)); 496 WARN_ON(le64_to_cpu(old.num_blocks) < 497 (extent_end - end) >> inode->i_blkbits); 498 btrfs_set_file_extent_num_blocks(leaf, extent, 499 (extent_end - end) >> inode->i_blkbits); 500 | 492 le64_to_cpu(old.offset) + end - key.offset); 493 WARN_ON(le64_to_cpu(old.num_bytes) < 494 (extent_end - end)); 495 btrfs_set_file_extent_num_bytes(leaf, extent, 496 extent_end - end); |
501 btrfs_set_file_extent_type(leaf, extent, 502 BTRFS_FILE_EXTENT_REG); | 497 btrfs_set_file_extent_type(leaf, extent, 498 BTRFS_FILE_EXTENT_REG); |
499 |
|
503 btrfs_mark_buffer_dirty(path->nodes[0]); | 500 btrfs_mark_buffer_dirty(path->nodes[0]); |
504 if (le64_to_cpu(old.disk_blocknr) != 0) { | 501 if (le64_to_cpu(old.disk_bytenr) != 0) { |
505 inode->i_blocks += | 502 inode->i_blocks += |
506 btrfs_file_extent_num_blocks(leaf, 507 extent) << 3; | 503 btrfs_file_extent_num_bytes(leaf, 504 extent) >> 9; |
508 } 509 ret = 0; 510 goto out; 511 } 512 } 513out: 514 btrfs_free_path(path); 515 return ret; --- 10 unchanged lines hidden (view full) --- 526 unsigned long first_index, 527 unsigned long last_index, 528 size_t write_bytes) 529{ 530 int i; 531 unsigned long index = pos >> PAGE_CACHE_SHIFT; 532 struct inode *inode = file->f_path.dentry->d_inode; 533 int err = 0; | 505 } 506 ret = 0; 507 goto out; 508 } 509 } 510out: 511 btrfs_free_path(path); 512 return ret; --- 10 unchanged lines hidden (view full) --- 523 unsigned long first_index, 524 unsigned long last_index, 525 size_t write_bytes) 526{ 527 int i; 528 unsigned long index = pos >> PAGE_CACHE_SHIFT; 529 struct inode *inode = file->f_path.dentry->d_inode; 530 int err = 0; |
534 u64 num_blocks; | |
535 u64 start_pos; 536 537 start_pos = pos & ~((u64)root->sectorsize - 1); | 531 u64 start_pos; 532 533 start_pos = pos & ~((u64)root->sectorsize - 1); |
538 num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >> 539 inode->i_blkbits; | |
540 541 memset(pages, 0, num_pages * sizeof(struct page *)); 542 543 for (i = 0; i < num_pages; i++) { 544 pages[i] = grab_cache_page(inode->i_mapping, index + i); 545 if (!pages[i]) { 546 err = -ENOMEM; 547 BUG_ON(1); --- 194 unchanged lines hidden --- | 534 535 memset(pages, 0, num_pages * sizeof(struct page *)); 536 537 for (i = 0; i < num_pages; i++) { 538 pages[i] = grab_cache_page(inode->i_mapping, index + i); 539 if (!pages[i]) { 540 err = -ENOMEM; 541 BUG_ON(1); --- 194 unchanged lines hidden --- |