diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 729 |
1 files changed, 327 insertions, 402 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 77f759302e12..6ed434ac037f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -179,18 +179,14 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
179 | } | 179 | } |
180 | flags = em->flags; | 180 | flags = em->flags; |
181 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { | 181 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { |
182 | if (em->start <= start && | 182 | if (testend && em->start + em->len >= start + len) { |
183 | (!testend || em->start + em->len >= start + len)) { | ||
184 | free_extent_map(em); | 183 | free_extent_map(em); |
185 | write_unlock(&em_tree->lock); | 184 | write_unlock(&em_tree->lock); |
186 | break; | 185 | break; |
187 | } | 186 | } |
188 | if (start < em->start) { | 187 | start = em->start + em->len; |
189 | len = em->start - start; | 188 | if (testend) |
190 | } else { | ||
191 | len = start + len - (em->start + em->len); | 189 | len = start + len - (em->start + em->len); |
192 | start = em->start + em->len; | ||
193 | } | ||
194 | free_extent_map(em); | 190 | free_extent_map(em); |
195 | write_unlock(&em_tree->lock); | 191 | write_unlock(&em_tree->lock); |
196 | continue; | 192 | continue; |
@@ -265,324 +261,253 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
265 | * If an extent intersects the range but is not entirely inside the range | 261 | * If an extent intersects the range but is not entirely inside the range |
266 | * it is either truncated or split. Anything entirely inside the range | 262 | * it is either truncated or split. Anything entirely inside the range |
267 | * is deleted from the tree. | 263 | * is deleted from the tree. |
268 | * | ||
269 | * inline_limit is used to tell this code which offsets in the file to keep | ||
270 | * if they contain inline extents. | ||
271 | */ | 264 | */ |
272 | noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, | 265 | int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, |
273 | struct btrfs_root *root, struct inode *inode, | 266 | u64 start, u64 end, u64 *hint_byte, int drop_cache) |
274 | u64 start, u64 end, u64 locked_end, | ||
275 | u64 inline_limit, u64 *hint_byte, int drop_cache) | ||
276 | { | 267 | { |
277 | u64 extent_end = 0; | 268 | struct btrfs_root *root = BTRFS_I(inode)->root; |
278 | u64 search_start = start; | ||
279 | u64 ram_bytes = 0; | ||
280 | u64 disk_bytenr = 0; | ||
281 | u64 orig_locked_end = locked_end; | ||
282 | u8 compression; | ||
283 | u8 encryption; | ||
284 | u16 other_encoding = 0; | ||
285 | struct extent_buffer *leaf; | 269 | struct extent_buffer *leaf; |
286 | struct btrfs_file_extent_item *extent; | 270 | struct btrfs_file_extent_item *fi; |
287 | struct btrfs_path *path; | 271 | struct btrfs_path *path; |
288 | struct btrfs_key key; | 272 | struct btrfs_key key; |
289 | struct btrfs_file_extent_item old; | 273 | struct btrfs_key new_key; |
290 | int keep; | 274 | u64 search_start = start; |
291 | int slot; | 275 | u64 disk_bytenr = 0; |
292 | int bookend; | 276 | u64 num_bytes = 0; |
293 | int found_type = 0; | 277 | u64 extent_offset = 0; |
294 | int found_extent; | 278 | u64 extent_end = 0; |
295 | int found_inline; | 279 | int del_nr = 0; |
280 | int del_slot = 0; | ||
281 | int extent_type; | ||
296 | int recow; | 282 | int recow; |
297 | int ret; | 283 | int ret; |
298 | 284 | ||
299 | inline_limit = 0; | ||
300 | if (drop_cache) | 285 | if (drop_cache) |
301 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 286 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
302 | 287 | ||
303 | path = btrfs_alloc_path(); | 288 | path = btrfs_alloc_path(); |
304 | if (!path) | 289 | if (!path) |
305 | return -ENOMEM; | 290 | return -ENOMEM; |
291 | |||
306 | while (1) { | 292 | while (1) { |
307 | recow = 0; | 293 | recow = 0; |
308 | btrfs_release_path(root, path); | ||
309 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 294 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
310 | search_start, -1); | 295 | search_start, -1); |
311 | if (ret < 0) | 296 | if (ret < 0) |
312 | goto out; | 297 | break; |
313 | if (ret > 0) { | 298 | if (ret > 0 && path->slots[0] > 0 && search_start == start) { |
314 | if (path->slots[0] == 0) { | 299 | leaf = path->nodes[0]; |
315 | ret = 0; | 300 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1); |
316 | goto out; | 301 | if (key.objectid == inode->i_ino && |
317 | } | 302 | key.type == BTRFS_EXTENT_DATA_KEY) |
318 | path->slots[0]--; | 303 | path->slots[0]--; |
319 | } | 304 | } |
305 | ret = 0; | ||
320 | next_slot: | 306 | next_slot: |
321 | keep = 0; | ||
322 | bookend = 0; | ||
323 | found_extent = 0; | ||
324 | found_inline = 0; | ||
325 | compression = 0; | ||
326 | encryption = 0; | ||
327 | extent = NULL; | ||
328 | leaf = path->nodes[0]; | 307 | leaf = path->nodes[0]; |
329 | slot = path->slots[0]; | 308 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { |
330 | ret = 0; | 309 | BUG_ON(del_nr > 0); |
331 | btrfs_item_key_to_cpu(leaf, &key, slot); | 310 | ret = btrfs_next_leaf(root, path); |
332 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY && | 311 | if (ret < 0) |
333 | key.offset >= end) { | 312 | break; |
334 | goto out; | 313 | if (ret > 0) { |
335 | } | 314 | ret = 0; |
336 | if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY || | 315 | break; |
337 | key.objectid != inode->i_ino) { | ||
338 | goto out; | ||
339 | } | ||
340 | if (recow) { | ||
341 | search_start = max(key.offset, start); | ||
342 | continue; | ||
343 | } | ||
344 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { | ||
345 | extent = btrfs_item_ptr(leaf, slot, | ||
346 | struct btrfs_file_extent_item); | ||
347 | found_type = btrfs_file_extent_type(leaf, extent); | ||
348 | compression = btrfs_file_extent_compression(leaf, | ||
349 | extent); | ||
350 | encryption = btrfs_file_extent_encryption(leaf, | ||
351 | extent); | ||
352 | other_encoding = btrfs_file_extent_other_encoding(leaf, | ||
353 | extent); | ||
354 | if (found_type == BTRFS_FILE_EXTENT_REG || | ||
355 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
356 | extent_end = | ||
357 | btrfs_file_extent_disk_bytenr(leaf, | ||
358 | extent); | ||
359 | if (extent_end) | ||
360 | *hint_byte = extent_end; | ||
361 | |||
362 | extent_end = key.offset + | ||
363 | btrfs_file_extent_num_bytes(leaf, extent); | ||
364 | ram_bytes = btrfs_file_extent_ram_bytes(leaf, | ||
365 | extent); | ||
366 | found_extent = 1; | ||
367 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | ||
368 | found_inline = 1; | ||
369 | extent_end = key.offset + | ||
370 | btrfs_file_extent_inline_len(leaf, extent); | ||
371 | } | 316 | } |
317 | leaf = path->nodes[0]; | ||
318 | recow = 1; | ||
319 | } | ||
320 | |||
321 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
322 | if (key.objectid > inode->i_ino || | ||
323 | key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end) | ||
324 | break; | ||
325 | |||
326 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
327 | struct btrfs_file_extent_item); | ||
328 | extent_type = btrfs_file_extent_type(leaf, fi); | ||
329 | |||
330 | if (extent_type == BTRFS_FILE_EXTENT_REG || | ||
331 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
332 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | ||
333 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | ||
334 | extent_offset = btrfs_file_extent_offset(leaf, fi); | ||
335 | extent_end = key.offset + | ||
336 | btrfs_file_extent_num_bytes(leaf, fi); | ||
337 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | ||
338 | extent_end = key.offset + | ||
339 | btrfs_file_extent_inline_len(leaf, fi); | ||
372 | } else { | 340 | } else { |
341 | WARN_ON(1); | ||
373 | extent_end = search_start; | 342 | extent_end = search_start; |
374 | } | 343 | } |
375 | 344 | ||
376 | /* we found nothing we can drop */ | 345 | if (extent_end <= search_start) { |
377 | if ((!found_extent && !found_inline) || | 346 | path->slots[0]++; |
378 | search_start >= extent_end) { | ||
379 | int nextret; | ||
380 | u32 nritems; | ||
381 | nritems = btrfs_header_nritems(leaf); | ||
382 | if (slot >= nritems - 1) { | ||
383 | nextret = btrfs_next_leaf(root, path); | ||
384 | if (nextret) | ||
385 | goto out; | ||
386 | recow = 1; | ||
387 | } else { | ||
388 | path->slots[0]++; | ||
389 | } | ||
390 | goto next_slot; | 347 | goto next_slot; |
391 | } | 348 | } |
392 | 349 | ||
393 | if (end <= extent_end && start >= key.offset && found_inline) | 350 | search_start = max(key.offset, start); |
394 | *hint_byte = EXTENT_MAP_INLINE; | 351 | if (recow) { |
395 | 352 | btrfs_release_path(root, path); | |
396 | if (found_extent) { | 353 | continue; |
397 | read_extent_buffer(leaf, &old, (unsigned long)extent, | ||
398 | sizeof(old)); | ||
399 | } | ||
400 | |||
401 | if (end < extent_end && end >= key.offset) { | ||
402 | bookend = 1; | ||
403 | if (found_inline && start <= key.offset) | ||
404 | keep = 1; | ||
405 | } | 354 | } |
406 | 355 | ||
407 | if (bookend && found_extent) { | 356 | /* |
408 | if (locked_end < extent_end) { | 357 | * | - range to drop - | |
409 | ret = try_lock_extent(&BTRFS_I(inode)->io_tree, | 358 | * | -------- extent -------- | |
410 | locked_end, extent_end - 1, | 359 | */ |
411 | GFP_NOFS); | 360 | if (start > key.offset && end < extent_end) { |
412 | if (!ret) { | 361 | BUG_ON(del_nr > 0); |
413 | btrfs_release_path(root, path); | 362 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); |
414 | lock_extent(&BTRFS_I(inode)->io_tree, | 363 | |
415 | locked_end, extent_end - 1, | 364 | memcpy(&new_key, &key, sizeof(new_key)); |
416 | GFP_NOFS); | 365 | new_key.offset = start; |
417 | locked_end = extent_end; | 366 | ret = btrfs_duplicate_item(trans, root, path, |
418 | continue; | 367 | &new_key); |
419 | } | 368 | if (ret == -EAGAIN) { |
420 | locked_end = extent_end; | 369 | btrfs_release_path(root, path); |
370 | continue; | ||
421 | } | 371 | } |
422 | disk_bytenr = le64_to_cpu(old.disk_bytenr); | 372 | if (ret < 0) |
423 | if (disk_bytenr != 0) { | 373 | break; |
374 | |||
375 | leaf = path->nodes[0]; | ||
376 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | ||
377 | struct btrfs_file_extent_item); | ||
378 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
379 | start - key.offset); | ||
380 | |||
381 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
382 | struct btrfs_file_extent_item); | ||
383 | |||
384 | extent_offset += start - key.offset; | ||
385 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | ||
386 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
387 | extent_end - start); | ||
388 | btrfs_mark_buffer_dirty(leaf); | ||
389 | |||
390 | if (disk_bytenr > 0) { | ||
424 | ret = btrfs_inc_extent_ref(trans, root, | 391 | ret = btrfs_inc_extent_ref(trans, root, |
425 | disk_bytenr, | 392 | disk_bytenr, num_bytes, 0, |
426 | le64_to_cpu(old.disk_num_bytes), 0, | 393 | root->root_key.objectid, |
427 | root->root_key.objectid, | 394 | new_key.objectid, |
428 | key.objectid, key.offset - | 395 | start - extent_offset); |
429 | le64_to_cpu(old.offset)); | ||
430 | BUG_ON(ret); | 396 | BUG_ON(ret); |
397 | *hint_byte = disk_bytenr; | ||
431 | } | 398 | } |
399 | key.offset = start; | ||
432 | } | 400 | } |
401 | /* | ||
402 | * | ---- range to drop ----- | | ||
403 | * | -------- extent -------- | | ||
404 | */ | ||
405 | if (start <= key.offset && end < extent_end) { | ||
406 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); | ||
433 | 407 | ||
434 | if (found_inline) { | 408 | memcpy(&new_key, &key, sizeof(new_key)); |
435 | u64 mask = root->sectorsize - 1; | 409 | new_key.offset = end; |
436 | search_start = (extent_end + mask) & ~mask; | 410 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
437 | } else | 411 | |
438 | search_start = extent_end; | 412 | extent_offset += end - key.offset; |
439 | 413 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | |
440 | /* truncate existing extent */ | 414 | btrfs_set_file_extent_num_bytes(leaf, fi, |
441 | if (start > key.offset) { | 415 | extent_end - end); |
442 | u64 new_num; | 416 | btrfs_mark_buffer_dirty(leaf); |
443 | u64 old_num; | 417 | if (disk_bytenr > 0) { |
444 | keep = 1; | 418 | inode_sub_bytes(inode, end - key.offset); |
445 | WARN_ON(start & (root->sectorsize - 1)); | 419 | *hint_byte = disk_bytenr; |
446 | if (found_extent) { | ||
447 | new_num = start - key.offset; | ||
448 | old_num = btrfs_file_extent_num_bytes(leaf, | ||
449 | extent); | ||
450 | *hint_byte = | ||
451 | btrfs_file_extent_disk_bytenr(leaf, | ||
452 | extent); | ||
453 | if (btrfs_file_extent_disk_bytenr(leaf, | ||
454 | extent)) { | ||
455 | inode_sub_bytes(inode, old_num - | ||
456 | new_num); | ||
457 | } | ||
458 | btrfs_set_file_extent_num_bytes(leaf, | ||
459 | extent, new_num); | ||
460 | btrfs_mark_buffer_dirty(leaf); | ||
461 | } else if (key.offset < inline_limit && | ||
462 | (end > extent_end) && | ||
463 | (inline_limit < extent_end)) { | ||
464 | u32 new_size; | ||
465 | new_size = btrfs_file_extent_calc_inline_size( | ||
466 | inline_limit - key.offset); | ||
467 | inode_sub_bytes(inode, extent_end - | ||
468 | inline_limit); | ||
469 | btrfs_set_file_extent_ram_bytes(leaf, extent, | ||
470 | new_size); | ||
471 | if (!compression && !encryption) { | ||
472 | btrfs_truncate_item(trans, root, path, | ||
473 | new_size, 1); | ||
474 | } | ||
475 | } | 420 | } |
421 | break; | ||
476 | } | 422 | } |
477 | /* delete the entire extent */ | ||
478 | if (!keep) { | ||
479 | if (found_inline) | ||
480 | inode_sub_bytes(inode, extent_end - | ||
481 | key.offset); | ||
482 | ret = btrfs_del_item(trans, root, path); | ||
483 | /* TODO update progress marker and return */ | ||
484 | BUG_ON(ret); | ||
485 | extent = NULL; | ||
486 | btrfs_release_path(root, path); | ||
487 | /* the extent will be freed later */ | ||
488 | } | ||
489 | if (bookend && found_inline && start <= key.offset) { | ||
490 | u32 new_size; | ||
491 | new_size = btrfs_file_extent_calc_inline_size( | ||
492 | extent_end - end); | ||
493 | inode_sub_bytes(inode, end - key.offset); | ||
494 | btrfs_set_file_extent_ram_bytes(leaf, extent, | ||
495 | new_size); | ||
496 | if (!compression && !encryption) | ||
497 | ret = btrfs_truncate_item(trans, root, path, | ||
498 | new_size, 0); | ||
499 | BUG_ON(ret); | ||
500 | } | ||
501 | /* create bookend, splitting the extent in two */ | ||
502 | if (bookend && found_extent) { | ||
503 | struct btrfs_key ins; | ||
504 | ins.objectid = inode->i_ino; | ||
505 | ins.offset = end; | ||
506 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | ||
507 | 423 | ||
508 | btrfs_release_path(root, path); | 424 | search_start = extent_end; |
509 | path->leave_spinning = 1; | 425 | /* |
510 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 426 | * | ---- range to drop ----- | |
511 | sizeof(*extent)); | 427 | * | -------- extent -------- | |
512 | BUG_ON(ret); | 428 | */ |
429 | if (start > key.offset && end >= extent_end) { | ||
430 | BUG_ON(del_nr > 0); | ||
431 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); | ||
513 | 432 | ||
514 | leaf = path->nodes[0]; | 433 | btrfs_set_file_extent_num_bytes(leaf, fi, |
515 | extent = btrfs_item_ptr(leaf, path->slots[0], | 434 | start - key.offset); |
516 | struct btrfs_file_extent_item); | 435 | btrfs_mark_buffer_dirty(leaf); |
517 | write_extent_buffer(leaf, &old, | 436 | if (disk_bytenr > 0) { |
518 | (unsigned long)extent, sizeof(old)); | 437 | inode_sub_bytes(inode, extent_end - start); |
519 | 438 | *hint_byte = disk_bytenr; | |
520 | btrfs_set_file_extent_compression(leaf, extent, | 439 | } |
521 | compression); | 440 | if (end == extent_end) |
522 | btrfs_set_file_extent_encryption(leaf, extent, | 441 | break; |
523 | encryption); | ||
524 | btrfs_set_file_extent_other_encoding(leaf, extent, | ||
525 | other_encoding); | ||
526 | btrfs_set_file_extent_offset(leaf, extent, | ||
527 | le64_to_cpu(old.offset) + end - key.offset); | ||
528 | WARN_ON(le64_to_cpu(old.num_bytes) < | ||
529 | (extent_end - end)); | ||
530 | btrfs_set_file_extent_num_bytes(leaf, extent, | ||
531 | extent_end - end); | ||
532 | 442 | ||
533 | /* | 443 | path->slots[0]++; |
534 | * set the ram bytes to the size of the full extent | 444 | goto next_slot; |
535 | * before splitting. This is a worst case flag, | ||
536 | * but its the best we can do because we don't know | ||
537 | * how splitting affects compression | ||
538 | */ | ||
539 | btrfs_set_file_extent_ram_bytes(leaf, extent, | ||
540 | ram_bytes); | ||
541 | btrfs_set_file_extent_type(leaf, extent, found_type); | ||
542 | |||
543 | btrfs_unlock_up_safe(path, 1); | ||
544 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
545 | btrfs_set_lock_blocking(path->nodes[0]); | ||
546 | |||
547 | path->leave_spinning = 0; | ||
548 | btrfs_release_path(root, path); | ||
549 | if (disk_bytenr != 0) | ||
550 | inode_add_bytes(inode, extent_end - end); | ||
551 | } | 445 | } |
552 | 446 | ||
553 | if (found_extent && !keep) { | 447 | /* |
554 | u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr); | 448 | * | ---- range to drop ----- | |
449 | * | ------ extent ------ | | ||
450 | */ | ||
451 | if (start <= key.offset && end >= extent_end) { | ||
452 | if (del_nr == 0) { | ||
453 | del_slot = path->slots[0]; | ||
454 | del_nr = 1; | ||
455 | } else { | ||
456 | BUG_ON(del_slot + del_nr != path->slots[0]); | ||
457 | del_nr++; | ||
458 | } | ||
555 | 459 | ||
556 | if (old_disk_bytenr != 0) { | 460 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
557 | inode_sub_bytes(inode, | 461 | inode_sub_bytes(inode, |
558 | le64_to_cpu(old.num_bytes)); | 462 | extent_end - key.offset); |
463 | extent_end = ALIGN(extent_end, | ||
464 | root->sectorsize); | ||
465 | } else if (disk_bytenr > 0) { | ||
559 | ret = btrfs_free_extent(trans, root, | 466 | ret = btrfs_free_extent(trans, root, |
560 | old_disk_bytenr, | 467 | disk_bytenr, num_bytes, 0, |
561 | le64_to_cpu(old.disk_num_bytes), | 468 | root->root_key.objectid, |
562 | 0, root->root_key.objectid, | ||
563 | key.objectid, key.offset - | 469 | key.objectid, key.offset - |
564 | le64_to_cpu(old.offset)); | 470 | extent_offset); |
565 | BUG_ON(ret); | 471 | BUG_ON(ret); |
566 | *hint_byte = old_disk_bytenr; | 472 | inode_sub_bytes(inode, |
473 | extent_end - key.offset); | ||
474 | *hint_byte = disk_bytenr; | ||
567 | } | 475 | } |
568 | } | ||
569 | 476 | ||
570 | if (search_start >= end) { | 477 | if (end == extent_end) |
571 | ret = 0; | 478 | break; |
572 | goto out; | 479 | |
480 | if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) { | ||
481 | path->slots[0]++; | ||
482 | goto next_slot; | ||
483 | } | ||
484 | |||
485 | ret = btrfs_del_items(trans, root, path, del_slot, | ||
486 | del_nr); | ||
487 | BUG_ON(ret); | ||
488 | |||
489 | del_nr = 0; | ||
490 | del_slot = 0; | ||
491 | |||
492 | btrfs_release_path(root, path); | ||
493 | continue; | ||
573 | } | 494 | } |
495 | |||
496 | BUG_ON(1); | ||
574 | } | 497 | } |
575 | out: | 498 | |
576 | btrfs_free_path(path); | 499 | if (del_nr > 0) { |
577 | if (locked_end > orig_locked_end) { | 500 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); |
578 | unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end, | 501 | BUG_ON(ret); |
579 | locked_end - 1, GFP_NOFS); | ||
580 | } | 502 | } |
503 | |||
504 | btrfs_free_path(path); | ||
581 | return ret; | 505 | return ret; |
582 | } | 506 | } |
583 | 507 | ||
584 | static int extent_mergeable(struct extent_buffer *leaf, int slot, | 508 | static int extent_mergeable(struct extent_buffer *leaf, int slot, |
585 | u64 objectid, u64 bytenr, u64 *start, u64 *end) | 509 | u64 objectid, u64 bytenr, u64 orig_offset, |
510 | u64 *start, u64 *end) | ||
586 | { | 511 | { |
587 | struct btrfs_file_extent_item *fi; | 512 | struct btrfs_file_extent_item *fi; |
588 | struct btrfs_key key; | 513 | struct btrfs_key key; |
@@ -598,6 +523,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
598 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 523 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
599 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || | 524 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || |
600 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || | 525 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || |
526 | btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset || | ||
601 | btrfs_file_extent_compression(leaf, fi) || | 527 | btrfs_file_extent_compression(leaf, fi) || |
602 | btrfs_file_extent_encryption(leaf, fi) || | 528 | btrfs_file_extent_encryption(leaf, fi) || |
603 | btrfs_file_extent_other_encoding(leaf, fi)) | 529 | btrfs_file_extent_other_encoding(leaf, fi)) |
@@ -620,23 +546,24 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
620 | * two or three. | 546 | * two or three. |
621 | */ | 547 | */ |
622 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | 548 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, |
623 | struct btrfs_root *root, | ||
624 | struct inode *inode, u64 start, u64 end) | 549 | struct inode *inode, u64 start, u64 end) |
625 | { | 550 | { |
551 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
626 | struct extent_buffer *leaf; | 552 | struct extent_buffer *leaf; |
627 | struct btrfs_path *path; | 553 | struct btrfs_path *path; |
628 | struct btrfs_file_extent_item *fi; | 554 | struct btrfs_file_extent_item *fi; |
629 | struct btrfs_key key; | 555 | struct btrfs_key key; |
556 | struct btrfs_key new_key; | ||
630 | u64 bytenr; | 557 | u64 bytenr; |
631 | u64 num_bytes; | 558 | u64 num_bytes; |
632 | u64 extent_end; | 559 | u64 extent_end; |
633 | u64 orig_offset; | 560 | u64 orig_offset; |
634 | u64 other_start; | 561 | u64 other_start; |
635 | u64 other_end; | 562 | u64 other_end; |
636 | u64 split = start; | 563 | u64 split; |
637 | u64 locked_end = end; | 564 | int del_nr = 0; |
638 | int extent_type; | 565 | int del_slot = 0; |
639 | int split_end = 1; | 566 | int recow; |
640 | int ret; | 567 | int ret; |
641 | 568 | ||
642 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 569 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
@@ -644,12 +571,11 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
644 | path = btrfs_alloc_path(); | 571 | path = btrfs_alloc_path(); |
645 | BUG_ON(!path); | 572 | BUG_ON(!path); |
646 | again: | 573 | again: |
574 | recow = 0; | ||
575 | split = start; | ||
647 | key.objectid = inode->i_ino; | 576 | key.objectid = inode->i_ino; |
648 | key.type = BTRFS_EXTENT_DATA_KEY; | 577 | key.type = BTRFS_EXTENT_DATA_KEY; |
649 | if (split == start) | 578 | key.offset = split; |
650 | key.offset = split; | ||
651 | else | ||
652 | key.offset = split - 1; | ||
653 | 579 | ||
654 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 580 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
655 | if (ret > 0 && path->slots[0] > 0) | 581 | if (ret > 0 && path->slots[0] > 0) |
@@ -661,159 +587,158 @@ again: | |||
661 | key.type != BTRFS_EXTENT_DATA_KEY); | 587 | key.type != BTRFS_EXTENT_DATA_KEY); |
662 | fi = btrfs_item_ptr(leaf, path->slots[0], | 588 | fi = btrfs_item_ptr(leaf, path->slots[0], |
663 | struct btrfs_file_extent_item); | 589 | struct btrfs_file_extent_item); |
664 | extent_type = btrfs_file_extent_type(leaf, fi); | 590 | BUG_ON(btrfs_file_extent_type(leaf, fi) != |
665 | BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC); | 591 | BTRFS_FILE_EXTENT_PREALLOC); |
666 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); | 592 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); |
667 | BUG_ON(key.offset > start || extent_end < end); | 593 | BUG_ON(key.offset > start || extent_end < end); |
668 | 594 | ||
669 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 595 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
670 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | 596 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); |
671 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); | 597 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); |
598 | memcpy(&new_key, &key, sizeof(new_key)); | ||
672 | 599 | ||
673 | if (key.offset == start) | 600 | if (start == key.offset && end < extent_end) { |
674 | split = end; | ||
675 | |||
676 | if (key.offset == start && extent_end == end) { | ||
677 | int del_nr = 0; | ||
678 | int del_slot = 0; | ||
679 | other_start = end; | ||
680 | other_end = 0; | ||
681 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | ||
682 | bytenr, &other_start, &other_end)) { | ||
683 | extent_end = other_end; | ||
684 | del_slot = path->slots[0] + 1; | ||
685 | del_nr++; | ||
686 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
687 | 0, root->root_key.objectid, | ||
688 | inode->i_ino, orig_offset); | ||
689 | BUG_ON(ret); | ||
690 | } | ||
691 | other_start = 0; | 601 | other_start = 0; |
692 | other_end = start; | 602 | other_end = start; |
693 | if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, | 603 | if (extent_mergeable(leaf, path->slots[0] - 1, |
694 | bytenr, &other_start, &other_end)) { | 604 | inode->i_ino, bytenr, orig_offset, |
695 | key.offset = other_start; | 605 | &other_start, &other_end)) { |
696 | del_slot = path->slots[0]; | 606 | new_key.offset = end; |
697 | del_nr++; | 607 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
698 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | 608 | fi = btrfs_item_ptr(leaf, path->slots[0], |
699 | 0, root->root_key.objectid, | 609 | struct btrfs_file_extent_item); |
700 | inode->i_ino, orig_offset); | 610 | btrfs_set_file_extent_num_bytes(leaf, fi, |
701 | BUG_ON(ret); | 611 | extent_end - end); |
702 | } | 612 | btrfs_set_file_extent_offset(leaf, fi, |
703 | split_end = 0; | 613 | end - orig_offset); |
704 | if (del_nr == 0) { | 614 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
705 | btrfs_set_file_extent_type(leaf, fi, | 615 | struct btrfs_file_extent_item); |
706 | BTRFS_FILE_EXTENT_REG); | 616 | btrfs_set_file_extent_num_bytes(leaf, fi, |
707 | goto done; | 617 | end - other_start); |
708 | } | 618 | btrfs_mark_buffer_dirty(leaf); |
709 | 619 | goto out; | |
710 | fi = btrfs_item_ptr(leaf, del_slot - 1, | ||
711 | struct btrfs_file_extent_item); | ||
712 | btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); | ||
713 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
714 | extent_end - key.offset); | ||
715 | btrfs_mark_buffer_dirty(leaf); | ||
716 | |||
717 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | ||
718 | BUG_ON(ret); | ||
719 | goto release; | ||
720 | } else if (split == start) { | ||
721 | if (locked_end < extent_end) { | ||
722 | ret = try_lock_extent(&BTRFS_I(inode)->io_tree, | ||
723 | locked_end, extent_end - 1, GFP_NOFS); | ||
724 | if (!ret) { | ||
725 | btrfs_release_path(root, path); | ||
726 | lock_extent(&BTRFS_I(inode)->io_tree, | ||
727 | locked_end, extent_end - 1, GFP_NOFS); | ||
728 | locked_end = extent_end; | ||
729 | goto again; | ||
730 | } | ||
731 | locked_end = extent_end; | ||
732 | } | 620 | } |
733 | btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset); | ||
734 | } else { | ||
735 | BUG_ON(key.offset != start); | ||
736 | key.offset = split; | ||
737 | btrfs_set_file_extent_offset(leaf, fi, key.offset - | ||
738 | orig_offset); | ||
739 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split); | ||
740 | btrfs_set_item_key_safe(trans, root, path, &key); | ||
741 | extent_end = split; | ||
742 | } | 621 | } |
743 | 622 | ||
744 | if (extent_end == end) { | 623 | if (start > key.offset && end == extent_end) { |
745 | split_end = 0; | ||
746 | extent_type = BTRFS_FILE_EXTENT_REG; | ||
747 | } | ||
748 | if (extent_end == end && split == start) { | ||
749 | other_start = end; | 624 | other_start = end; |
750 | other_end = 0; | 625 | other_end = 0; |
751 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | 626 | if (extent_mergeable(leaf, path->slots[0] + 1, |
752 | bytenr, &other_start, &other_end)) { | 627 | inode->i_ino, bytenr, orig_offset, |
753 | path->slots[0]++; | 628 | &other_start, &other_end)) { |
754 | fi = btrfs_item_ptr(leaf, path->slots[0], | 629 | fi = btrfs_item_ptr(leaf, path->slots[0], |
755 | struct btrfs_file_extent_item); | 630 | struct btrfs_file_extent_item); |
756 | key.offset = split; | ||
757 | btrfs_set_item_key_safe(trans, root, path, &key); | ||
758 | btrfs_set_file_extent_offset(leaf, fi, key.offset - | ||
759 | orig_offset); | ||
760 | btrfs_set_file_extent_num_bytes(leaf, fi, | 631 | btrfs_set_file_extent_num_bytes(leaf, fi, |
761 | other_end - split); | 632 | start - key.offset); |
762 | goto done; | 633 | path->slots[0]++; |
763 | } | 634 | new_key.offset = start; |
764 | } | 635 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
765 | if (extent_end == end && split == end) { | 636 | |
766 | other_start = 0; | ||
767 | other_end = start; | ||
768 | if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino, | ||
769 | bytenr, &other_start, &other_end)) { | ||
770 | path->slots[0]--; | ||
771 | fi = btrfs_item_ptr(leaf, path->slots[0], | 637 | fi = btrfs_item_ptr(leaf, path->slots[0], |
772 | struct btrfs_file_extent_item); | 638 | struct btrfs_file_extent_item); |
773 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - | 639 | btrfs_set_file_extent_num_bytes(leaf, fi, |
774 | other_start); | 640 | other_end - start); |
775 | goto done; | 641 | btrfs_set_file_extent_offset(leaf, fi, |
642 | start - orig_offset); | ||
643 | btrfs_mark_buffer_dirty(leaf); | ||
644 | goto out; | ||
776 | } | 645 | } |
777 | } | 646 | } |
778 | 647 | ||
779 | btrfs_mark_buffer_dirty(leaf); | 648 | while (start > key.offset || end < extent_end) { |
649 | if (key.offset == start) | ||
650 | split = end; | ||
780 | 651 | ||
781 | ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0, | 652 | new_key.offset = split; |
782 | root->root_key.objectid, | 653 | ret = btrfs_duplicate_item(trans, root, path, &new_key); |
783 | inode->i_ino, orig_offset); | 654 | if (ret == -EAGAIN) { |
784 | BUG_ON(ret); | 655 | btrfs_release_path(root, path); |
785 | btrfs_release_path(root, path); | 656 | goto again; |
657 | } | ||
658 | BUG_ON(ret < 0); | ||
786 | 659 | ||
787 | key.offset = start; | 660 | leaf = path->nodes[0]; |
788 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi)); | 661 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
789 | BUG_ON(ret); | 662 | struct btrfs_file_extent_item); |
663 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
664 | split - key.offset); | ||
790 | 665 | ||
791 | leaf = path->nodes[0]; | 666 | fi = btrfs_item_ptr(leaf, path->slots[0], |
792 | fi = btrfs_item_ptr(leaf, path->slots[0], | 667 | struct btrfs_file_extent_item); |
793 | struct btrfs_file_extent_item); | 668 | |
794 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | 669 | btrfs_set_file_extent_offset(leaf, fi, split - orig_offset); |
795 | btrfs_set_file_extent_type(leaf, fi, extent_type); | 670 | btrfs_set_file_extent_num_bytes(leaf, fi, |
796 | btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr); | 671 | extent_end - split); |
797 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes); | 672 | btrfs_mark_buffer_dirty(leaf); |
798 | btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset); | 673 | |
799 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset); | 674 | ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0, |
800 | btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes); | 675 | root->root_key.objectid, |
801 | btrfs_set_file_extent_compression(leaf, fi, 0); | 676 | inode->i_ino, orig_offset); |
802 | btrfs_set_file_extent_encryption(leaf, fi, 0); | 677 | BUG_ON(ret); |
803 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); | 678 | |
804 | done: | 679 | if (split == start) { |
805 | btrfs_mark_buffer_dirty(leaf); | 680 | key.offset = start; |
806 | 681 | } else { | |
807 | release: | 682 | BUG_ON(start != key.offset); |
808 | btrfs_release_path(root, path); | 683 | path->slots[0]--; |
809 | if (split_end && split == start) { | 684 | extent_end = end; |
810 | split = end; | 685 | } |
811 | goto again; | 686 | recow = 1; |
687 | } | ||
688 | |||
689 | other_start = end; | ||
690 | other_end = 0; | ||
691 | if (extent_mergeable(leaf, path->slots[0] + 1, | ||
692 | inode->i_ino, bytenr, orig_offset, | ||
693 | &other_start, &other_end)) { | ||
694 | if (recow) { | ||
695 | btrfs_release_path(root, path); | ||
696 | goto again; | ||
697 | } | ||
698 | extent_end = other_end; | ||
699 | del_slot = path->slots[0] + 1; | ||
700 | del_nr++; | ||
701 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
702 | 0, root->root_key.objectid, | ||
703 | inode->i_ino, orig_offset); | ||
704 | BUG_ON(ret); | ||
705 | } | ||
706 | other_start = 0; | ||
707 | other_end = start; | ||
708 | if (extent_mergeable(leaf, path->slots[0] - 1, | ||
709 | inode->i_ino, bytenr, orig_offset, | ||
710 | &other_start, &other_end)) { | ||
711 | if (recow) { | ||
712 | btrfs_release_path(root, path); | ||
713 | goto again; | ||
714 | } | ||
715 | key.offset = other_start; | ||
716 | del_slot = path->slots[0]; | ||
717 | del_nr++; | ||
718 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
719 | 0, root->root_key.objectid, | ||
720 | inode->i_ino, orig_offset); | ||
721 | BUG_ON(ret); | ||
812 | } | 722 | } |
813 | if (locked_end > end) { | 723 | if (del_nr == 0) { |
814 | unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1, | 724 | fi = btrfs_item_ptr(leaf, path->slots[0], |
815 | GFP_NOFS); | 725 | struct btrfs_file_extent_item); |
726 | btrfs_set_file_extent_type(leaf, fi, | ||
727 | BTRFS_FILE_EXTENT_REG); | ||
728 | btrfs_mark_buffer_dirty(leaf); | ||
729 | } else { | ||
730 | fi = btrfs_item_ptr(leaf, del_slot - 1, | ||
731 | struct btrfs_file_extent_item); | ||
732 | btrfs_set_file_extent_type(leaf, fi, | ||
733 | BTRFS_FILE_EXTENT_REG); | ||
734 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
735 | extent_end - key.offset); | ||
736 | btrfs_mark_buffer_dirty(leaf); | ||
737 | |||
738 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | ||
739 | BUG_ON(ret); | ||
816 | } | 740 | } |
741 | out: | ||
817 | btrfs_free_path(path); | 742 | btrfs_free_path(path); |
818 | return 0; | 743 | return 0; |
819 | } | 744 | } |
@@ -1210,7 +1135,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1210 | } | 1135 | } |
1211 | mutex_lock(&dentry->d_inode->i_mutex); | 1136 | mutex_lock(&dentry->d_inode->i_mutex); |
1212 | out: | 1137 | out: |
1213 | return ret > 0 ? EIO : ret; | 1138 | return ret > 0 ? -EIO : ret; |
1214 | } | 1139 | } |
1215 | 1140 | ||
1216 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 1141 | static const struct vm_operations_struct btrfs_file_vm_ops = { |