diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/btrfs/file.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 757 |
1 files changed, 344 insertions, 413 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 06550affbd27..29ff749ff4ca 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/writeback.h> | 28 | #include <linux/writeback.h> |
29 | #include <linux/statfs.h> | 29 | #include <linux/statfs.h> |
30 | #include <linux/compat.h> | 30 | #include <linux/compat.h> |
31 | #include <linux/slab.h> | ||
31 | #include "ctree.h" | 32 | #include "ctree.h" |
32 | #include "disk-io.h" | 33 | #include "disk-io.h" |
33 | #include "transaction.h" | 34 | #include "transaction.h" |
@@ -123,7 +124,8 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
123 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | 124 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
124 | 125 | ||
125 | end_of_last_block = start_pos + num_bytes - 1; | 126 | end_of_last_block = start_pos + num_bytes - 1; |
126 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block); | 127 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
128 | NULL); | ||
127 | if (err) | 129 | if (err) |
128 | return err; | 130 | return err; |
129 | 131 | ||
@@ -179,18 +181,14 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
179 | } | 181 | } |
180 | flags = em->flags; | 182 | flags = em->flags; |
181 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { | 183 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { |
182 | if (em->start <= start && | 184 | if (testend && em->start + em->len >= start + len) { |
183 | (!testend || em->start + em->len >= start + len)) { | ||
184 | free_extent_map(em); | 185 | free_extent_map(em); |
185 | write_unlock(&em_tree->lock); | 186 | write_unlock(&em_tree->lock); |
186 | break; | 187 | break; |
187 | } | 188 | } |
188 | if (start < em->start) { | 189 | start = em->start + em->len; |
189 | len = em->start - start; | 190 | if (testend) |
190 | } else { | ||
191 | len = start + len - (em->start + em->len); | 191 | len = start + len - (em->start + em->len); |
192 | start = em->start + em->len; | ||
193 | } | ||
194 | free_extent_map(em); | 192 | free_extent_map(em); |
195 | write_unlock(&em_tree->lock); | 193 | write_unlock(&em_tree->lock); |
196 | continue; | 194 | continue; |
@@ -265,324 +263,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 | 263 | * 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 | 264 | * it is either truncated or split. Anything entirely inside the range |
267 | * is deleted from the tree. | 265 | * 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 | */ | 266 | */ |
272 | noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, | 267 | int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, |
273 | struct btrfs_root *root, struct inode *inode, | 268 | 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 | { | 269 | { |
277 | u64 extent_end = 0; | 270 | 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; | 271 | struct extent_buffer *leaf; |
286 | struct btrfs_file_extent_item *extent; | 272 | struct btrfs_file_extent_item *fi; |
287 | struct btrfs_path *path; | 273 | struct btrfs_path *path; |
288 | struct btrfs_key key; | 274 | struct btrfs_key key; |
289 | struct btrfs_file_extent_item old; | 275 | struct btrfs_key new_key; |
290 | int keep; | 276 | u64 search_start = start; |
291 | int slot; | 277 | u64 disk_bytenr = 0; |
292 | int bookend; | 278 | u64 num_bytes = 0; |
293 | int found_type = 0; | 279 | u64 extent_offset = 0; |
294 | int found_extent; | 280 | u64 extent_end = 0; |
295 | int found_inline; | 281 | int del_nr = 0; |
282 | int del_slot = 0; | ||
283 | int extent_type; | ||
296 | int recow; | 284 | int recow; |
297 | int ret; | 285 | int ret; |
298 | 286 | ||
299 | inline_limit = 0; | ||
300 | if (drop_cache) | 287 | if (drop_cache) |
301 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 288 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
302 | 289 | ||
303 | path = btrfs_alloc_path(); | 290 | path = btrfs_alloc_path(); |
304 | if (!path) | 291 | if (!path) |
305 | return -ENOMEM; | 292 | return -ENOMEM; |
293 | |||
306 | while (1) { | 294 | while (1) { |
307 | recow = 0; | 295 | recow = 0; |
308 | btrfs_release_path(root, path); | ||
309 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 296 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
310 | search_start, -1); | 297 | search_start, -1); |
311 | if (ret < 0) | 298 | if (ret < 0) |
312 | goto out; | 299 | break; |
313 | if (ret > 0) { | 300 | if (ret > 0 && path->slots[0] > 0 && search_start == start) { |
314 | if (path->slots[0] == 0) { | 301 | leaf = path->nodes[0]; |
315 | ret = 0; | 302 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1); |
316 | goto out; | 303 | if (key.objectid == inode->i_ino && |
317 | } | 304 | key.type == BTRFS_EXTENT_DATA_KEY) |
318 | path->slots[0]--; | 305 | path->slots[0]--; |
319 | } | 306 | } |
307 | ret = 0; | ||
320 | next_slot: | 308 | 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]; | 309 | leaf = path->nodes[0]; |
329 | slot = path->slots[0]; | 310 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { |
330 | ret = 0; | 311 | BUG_ON(del_nr > 0); |
331 | btrfs_item_key_to_cpu(leaf, &key, slot); | 312 | ret = btrfs_next_leaf(root, path); |
332 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY && | 313 | if (ret < 0) |
333 | key.offset >= end) { | 314 | break; |
334 | goto out; | 315 | if (ret > 0) { |
335 | } | 316 | ret = 0; |
336 | if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY || | 317 | 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 | } | 318 | } |
319 | leaf = path->nodes[0]; | ||
320 | recow = 1; | ||
321 | } | ||
322 | |||
323 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
324 | if (key.objectid > inode->i_ino || | ||
325 | key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end) | ||
326 | break; | ||
327 | |||
328 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
329 | struct btrfs_file_extent_item); | ||
330 | extent_type = btrfs_file_extent_type(leaf, fi); | ||
331 | |||
332 | if (extent_type == BTRFS_FILE_EXTENT_REG || | ||
333 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
334 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | ||
335 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | ||
336 | extent_offset = btrfs_file_extent_offset(leaf, fi); | ||
337 | extent_end = key.offset + | ||
338 | btrfs_file_extent_num_bytes(leaf, fi); | ||
339 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | ||
340 | extent_end = key.offset + | ||
341 | btrfs_file_extent_inline_len(leaf, fi); | ||
372 | } else { | 342 | } else { |
343 | WARN_ON(1); | ||
373 | extent_end = search_start; | 344 | extent_end = search_start; |
374 | } | 345 | } |
375 | 346 | ||
376 | /* we found nothing we can drop */ | 347 | if (extent_end <= search_start) { |
377 | if ((!found_extent && !found_inline) || | 348 | 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; | 349 | goto next_slot; |
391 | } | 350 | } |
392 | 351 | ||
393 | if (end <= extent_end && start >= key.offset && found_inline) | 352 | search_start = max(key.offset, start); |
394 | *hint_byte = EXTENT_MAP_INLINE; | 353 | if (recow) { |
395 | 354 | btrfs_release_path(root, path); | |
396 | if (found_extent) { | 355 | 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 | } | 356 | } |
406 | 357 | ||
407 | if (bookend && found_extent) { | 358 | /* |
408 | if (locked_end < extent_end) { | 359 | * | - range to drop - | |
409 | ret = try_lock_extent(&BTRFS_I(inode)->io_tree, | 360 | * | -------- extent -------- | |
410 | locked_end, extent_end - 1, | 361 | */ |
411 | GFP_NOFS); | 362 | if (start > key.offset && end < extent_end) { |
412 | if (!ret) { | 363 | BUG_ON(del_nr > 0); |
413 | btrfs_release_path(root, path); | 364 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); |
414 | lock_extent(&BTRFS_I(inode)->io_tree, | 365 | |
415 | locked_end, extent_end - 1, | 366 | memcpy(&new_key, &key, sizeof(new_key)); |
416 | GFP_NOFS); | 367 | new_key.offset = start; |
417 | locked_end = extent_end; | 368 | ret = btrfs_duplicate_item(trans, root, path, |
418 | continue; | 369 | &new_key); |
419 | } | 370 | if (ret == -EAGAIN) { |
420 | locked_end = extent_end; | 371 | btrfs_release_path(root, path); |
372 | continue; | ||
421 | } | 373 | } |
422 | disk_bytenr = le64_to_cpu(old.disk_bytenr); | 374 | if (ret < 0) |
423 | if (disk_bytenr != 0) { | 375 | break; |
376 | |||
377 | leaf = path->nodes[0]; | ||
378 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | ||
379 | struct btrfs_file_extent_item); | ||
380 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
381 | start - key.offset); | ||
382 | |||
383 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
384 | struct btrfs_file_extent_item); | ||
385 | |||
386 | extent_offset += start - key.offset; | ||
387 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | ||
388 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
389 | extent_end - start); | ||
390 | btrfs_mark_buffer_dirty(leaf); | ||
391 | |||
392 | if (disk_bytenr > 0) { | ||
424 | ret = btrfs_inc_extent_ref(trans, root, | 393 | ret = btrfs_inc_extent_ref(trans, root, |
425 | disk_bytenr, | 394 | disk_bytenr, num_bytes, 0, |
426 | le64_to_cpu(old.disk_num_bytes), 0, | 395 | root->root_key.objectid, |
427 | root->root_key.objectid, | 396 | new_key.objectid, |
428 | key.objectid, key.offset - | 397 | start - extent_offset); |
429 | le64_to_cpu(old.offset)); | ||
430 | BUG_ON(ret); | 398 | BUG_ON(ret); |
399 | *hint_byte = disk_bytenr; | ||
431 | } | 400 | } |
401 | key.offset = start; | ||
432 | } | 402 | } |
403 | /* | ||
404 | * | ---- range to drop ----- | | ||
405 | * | -------- extent -------- | | ||
406 | */ | ||
407 | if (start <= key.offset && end < extent_end) { | ||
408 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); | ||
433 | 409 | ||
434 | if (found_inline) { | 410 | memcpy(&new_key, &key, sizeof(new_key)); |
435 | u64 mask = root->sectorsize - 1; | 411 | new_key.offset = end; |
436 | search_start = (extent_end + mask) & ~mask; | 412 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
437 | } else | 413 | |
438 | search_start = extent_end; | 414 | extent_offset += end - key.offset; |
439 | 415 | btrfs_set_file_extent_offset(leaf, fi, extent_offset); | |
440 | /* truncate existing extent */ | 416 | btrfs_set_file_extent_num_bytes(leaf, fi, |
441 | if (start > key.offset) { | 417 | extent_end - end); |
442 | u64 new_num; | 418 | btrfs_mark_buffer_dirty(leaf); |
443 | u64 old_num; | 419 | if (disk_bytenr > 0) { |
444 | keep = 1; | 420 | inode_sub_bytes(inode, end - key.offset); |
445 | WARN_ON(start & (root->sectorsize - 1)); | 421 | *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 | } | 422 | } |
423 | break; | ||
476 | } | 424 | } |
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 | 425 | ||
508 | btrfs_release_path(root, path); | 426 | search_start = extent_end; |
509 | path->leave_spinning = 1; | 427 | /* |
510 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 428 | * | ---- range to drop ----- | |
511 | sizeof(*extent)); | 429 | * | -------- extent -------- | |
512 | BUG_ON(ret); | 430 | */ |
431 | if (start > key.offset && end >= extent_end) { | ||
432 | BUG_ON(del_nr > 0); | ||
433 | BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); | ||
513 | 434 | ||
514 | leaf = path->nodes[0]; | 435 | btrfs_set_file_extent_num_bytes(leaf, fi, |
515 | extent = btrfs_item_ptr(leaf, path->slots[0], | 436 | start - key.offset); |
516 | struct btrfs_file_extent_item); | 437 | btrfs_mark_buffer_dirty(leaf); |
517 | write_extent_buffer(leaf, &old, | 438 | if (disk_bytenr > 0) { |
518 | (unsigned long)extent, sizeof(old)); | 439 | inode_sub_bytes(inode, extent_end - start); |
519 | 440 | *hint_byte = disk_bytenr; | |
520 | btrfs_set_file_extent_compression(leaf, extent, | 441 | } |
521 | compression); | 442 | if (end == extent_end) |
522 | btrfs_set_file_extent_encryption(leaf, extent, | 443 | 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 | 444 | ||
533 | /* | 445 | path->slots[0]++; |
534 | * set the ram bytes to the size of the full extent | 446 | 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 | } | 447 | } |
552 | 448 | ||
553 | if (found_extent && !keep) { | 449 | /* |
554 | u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr); | 450 | * | ---- range to drop ----- | |
451 | * | ------ extent ------ | | ||
452 | */ | ||
453 | if (start <= key.offset && end >= extent_end) { | ||
454 | if (del_nr == 0) { | ||
455 | del_slot = path->slots[0]; | ||
456 | del_nr = 1; | ||
457 | } else { | ||
458 | BUG_ON(del_slot + del_nr != path->slots[0]); | ||
459 | del_nr++; | ||
460 | } | ||
555 | 461 | ||
556 | if (old_disk_bytenr != 0) { | 462 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
557 | inode_sub_bytes(inode, | 463 | inode_sub_bytes(inode, |
558 | le64_to_cpu(old.num_bytes)); | 464 | extent_end - key.offset); |
465 | extent_end = ALIGN(extent_end, | ||
466 | root->sectorsize); | ||
467 | } else if (disk_bytenr > 0) { | ||
559 | ret = btrfs_free_extent(trans, root, | 468 | ret = btrfs_free_extent(trans, root, |
560 | old_disk_bytenr, | 469 | disk_bytenr, num_bytes, 0, |
561 | le64_to_cpu(old.disk_num_bytes), | 470 | root->root_key.objectid, |
562 | 0, root->root_key.objectid, | ||
563 | key.objectid, key.offset - | 471 | key.objectid, key.offset - |
564 | le64_to_cpu(old.offset)); | 472 | extent_offset); |
565 | BUG_ON(ret); | 473 | BUG_ON(ret); |
566 | *hint_byte = old_disk_bytenr; | 474 | inode_sub_bytes(inode, |
475 | extent_end - key.offset); | ||
476 | *hint_byte = disk_bytenr; | ||
567 | } | 477 | } |
568 | } | ||
569 | 478 | ||
570 | if (search_start >= end) { | 479 | if (end == extent_end) |
571 | ret = 0; | 480 | break; |
572 | goto out; | 481 | |
482 | if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) { | ||
483 | path->slots[0]++; | ||
484 | goto next_slot; | ||
485 | } | ||
486 | |||
487 | ret = btrfs_del_items(trans, root, path, del_slot, | ||
488 | del_nr); | ||
489 | BUG_ON(ret); | ||
490 | |||
491 | del_nr = 0; | ||
492 | del_slot = 0; | ||
493 | |||
494 | btrfs_release_path(root, path); | ||
495 | continue; | ||
573 | } | 496 | } |
497 | |||
498 | BUG_ON(1); | ||
574 | } | 499 | } |
575 | out: | 500 | |
576 | btrfs_free_path(path); | 501 | if (del_nr > 0) { |
577 | if (locked_end > orig_locked_end) { | 502 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); |
578 | unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end, | 503 | BUG_ON(ret); |
579 | locked_end - 1, GFP_NOFS); | ||
580 | } | 504 | } |
505 | |||
506 | btrfs_free_path(path); | ||
581 | return ret; | 507 | return ret; |
582 | } | 508 | } |
583 | 509 | ||
584 | static int extent_mergeable(struct extent_buffer *leaf, int slot, | 510 | static int extent_mergeable(struct extent_buffer *leaf, int slot, |
585 | u64 objectid, u64 bytenr, u64 *start, u64 *end) | 511 | u64 objectid, u64 bytenr, u64 orig_offset, |
512 | u64 *start, u64 *end) | ||
586 | { | 513 | { |
587 | struct btrfs_file_extent_item *fi; | 514 | struct btrfs_file_extent_item *fi; |
588 | struct btrfs_key key; | 515 | struct btrfs_key key; |
@@ -598,6 +525,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
598 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 525 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
599 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || | 526 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || |
600 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || | 527 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || |
528 | btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset || | ||
601 | btrfs_file_extent_compression(leaf, fi) || | 529 | btrfs_file_extent_compression(leaf, fi) || |
602 | btrfs_file_extent_encryption(leaf, fi) || | 530 | btrfs_file_extent_encryption(leaf, fi) || |
603 | btrfs_file_extent_other_encoding(leaf, fi)) | 531 | btrfs_file_extent_other_encoding(leaf, fi)) |
@@ -620,23 +548,24 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
620 | * two or three. | 548 | * two or three. |
621 | */ | 549 | */ |
622 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | 550 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, |
623 | struct btrfs_root *root, | ||
624 | struct inode *inode, u64 start, u64 end) | 551 | struct inode *inode, u64 start, u64 end) |
625 | { | 552 | { |
553 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
626 | struct extent_buffer *leaf; | 554 | struct extent_buffer *leaf; |
627 | struct btrfs_path *path; | 555 | struct btrfs_path *path; |
628 | struct btrfs_file_extent_item *fi; | 556 | struct btrfs_file_extent_item *fi; |
629 | struct btrfs_key key; | 557 | struct btrfs_key key; |
558 | struct btrfs_key new_key; | ||
630 | u64 bytenr; | 559 | u64 bytenr; |
631 | u64 num_bytes; | 560 | u64 num_bytes; |
632 | u64 extent_end; | 561 | u64 extent_end; |
633 | u64 orig_offset; | 562 | u64 orig_offset; |
634 | u64 other_start; | 563 | u64 other_start; |
635 | u64 other_end; | 564 | u64 other_end; |
636 | u64 split = start; | 565 | u64 split; |
637 | u64 locked_end = end; | 566 | int del_nr = 0; |
638 | int extent_type; | 567 | int del_slot = 0; |
639 | int split_end = 1; | 568 | int recow; |
640 | int ret; | 569 | int ret; |
641 | 570 | ||
642 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 571 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
@@ -644,12 +573,11 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
644 | path = btrfs_alloc_path(); | 573 | path = btrfs_alloc_path(); |
645 | BUG_ON(!path); | 574 | BUG_ON(!path); |
646 | again: | 575 | again: |
576 | recow = 0; | ||
577 | split = start; | ||
647 | key.objectid = inode->i_ino; | 578 | key.objectid = inode->i_ino; |
648 | key.type = BTRFS_EXTENT_DATA_KEY; | 579 | key.type = BTRFS_EXTENT_DATA_KEY; |
649 | if (split == start) | 580 | key.offset = split; |
650 | key.offset = split; | ||
651 | else | ||
652 | key.offset = split - 1; | ||
653 | 581 | ||
654 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 582 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
655 | if (ret > 0 && path->slots[0] > 0) | 583 | if (ret > 0 && path->slots[0] > 0) |
@@ -661,159 +589,158 @@ again: | |||
661 | key.type != BTRFS_EXTENT_DATA_KEY); | 589 | key.type != BTRFS_EXTENT_DATA_KEY); |
662 | fi = btrfs_item_ptr(leaf, path->slots[0], | 590 | fi = btrfs_item_ptr(leaf, path->slots[0], |
663 | struct btrfs_file_extent_item); | 591 | struct btrfs_file_extent_item); |
664 | extent_type = btrfs_file_extent_type(leaf, fi); | 592 | BUG_ON(btrfs_file_extent_type(leaf, fi) != |
665 | BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC); | 593 | BTRFS_FILE_EXTENT_PREALLOC); |
666 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); | 594 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); |
667 | BUG_ON(key.offset > start || extent_end < end); | 595 | BUG_ON(key.offset > start || extent_end < end); |
668 | 596 | ||
669 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 597 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
670 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | 598 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); |
671 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); | 599 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); |
600 | memcpy(&new_key, &key, sizeof(new_key)); | ||
672 | 601 | ||
673 | if (key.offset == start) | 602 | 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; | 603 | other_start = 0; |
692 | other_end = start; | 604 | other_end = start; |
693 | if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, | 605 | if (extent_mergeable(leaf, path->slots[0] - 1, |
694 | bytenr, &other_start, &other_end)) { | 606 | inode->i_ino, bytenr, orig_offset, |
695 | key.offset = other_start; | 607 | &other_start, &other_end)) { |
696 | del_slot = path->slots[0]; | 608 | new_key.offset = end; |
697 | del_nr++; | 609 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
698 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | 610 | fi = btrfs_item_ptr(leaf, path->slots[0], |
699 | 0, root->root_key.objectid, | 611 | struct btrfs_file_extent_item); |
700 | inode->i_ino, orig_offset); | 612 | btrfs_set_file_extent_num_bytes(leaf, fi, |
701 | BUG_ON(ret); | 613 | extent_end - end); |
702 | } | 614 | btrfs_set_file_extent_offset(leaf, fi, |
703 | split_end = 0; | 615 | end - orig_offset); |
704 | if (del_nr == 0) { | 616 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
705 | btrfs_set_file_extent_type(leaf, fi, | 617 | struct btrfs_file_extent_item); |
706 | BTRFS_FILE_EXTENT_REG); | 618 | btrfs_set_file_extent_num_bytes(leaf, fi, |
707 | goto done; | 619 | end - other_start); |
708 | } | 620 | btrfs_mark_buffer_dirty(leaf); |
709 | 621 | 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 | } | 622 | } |
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 | } | 623 | } |
743 | 624 | ||
744 | if (extent_end == end) { | 625 | 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; | 626 | other_start = end; |
750 | other_end = 0; | 627 | other_end = 0; |
751 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | 628 | if (extent_mergeable(leaf, path->slots[0] + 1, |
752 | bytenr, &other_start, &other_end)) { | 629 | inode->i_ino, bytenr, orig_offset, |
753 | path->slots[0]++; | 630 | &other_start, &other_end)) { |
754 | fi = btrfs_item_ptr(leaf, path->slots[0], | 631 | fi = btrfs_item_ptr(leaf, path->slots[0], |
755 | struct btrfs_file_extent_item); | 632 | 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, | 633 | btrfs_set_file_extent_num_bytes(leaf, fi, |
761 | other_end - split); | 634 | start - key.offset); |
762 | goto done; | 635 | path->slots[0]++; |
763 | } | 636 | new_key.offset = start; |
764 | } | 637 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
765 | if (extent_end == end && split == end) { | 638 | |
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], | 639 | fi = btrfs_item_ptr(leaf, path->slots[0], |
772 | struct btrfs_file_extent_item); | 640 | struct btrfs_file_extent_item); |
773 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - | 641 | btrfs_set_file_extent_num_bytes(leaf, fi, |
774 | other_start); | 642 | other_end - start); |
775 | goto done; | 643 | btrfs_set_file_extent_offset(leaf, fi, |
644 | start - orig_offset); | ||
645 | btrfs_mark_buffer_dirty(leaf); | ||
646 | goto out; | ||
776 | } | 647 | } |
777 | } | 648 | } |
778 | 649 | ||
779 | btrfs_mark_buffer_dirty(leaf); | 650 | while (start > key.offset || end < extent_end) { |
651 | if (key.offset == start) | ||
652 | split = end; | ||
780 | 653 | ||
781 | ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0, | 654 | new_key.offset = split; |
782 | root->root_key.objectid, | 655 | ret = btrfs_duplicate_item(trans, root, path, &new_key); |
783 | inode->i_ino, orig_offset); | 656 | if (ret == -EAGAIN) { |
784 | BUG_ON(ret); | 657 | btrfs_release_path(root, path); |
785 | btrfs_release_path(root, path); | 658 | goto again; |
659 | } | ||
660 | BUG_ON(ret < 0); | ||
786 | 661 | ||
787 | key.offset = start; | 662 | leaf = path->nodes[0]; |
788 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi)); | 663 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
789 | BUG_ON(ret); | 664 | struct btrfs_file_extent_item); |
665 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
666 | split - key.offset); | ||
790 | 667 | ||
791 | leaf = path->nodes[0]; | 668 | fi = btrfs_item_ptr(leaf, path->slots[0], |
792 | fi = btrfs_item_ptr(leaf, path->slots[0], | 669 | struct btrfs_file_extent_item); |
793 | struct btrfs_file_extent_item); | 670 | |
794 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | 671 | btrfs_set_file_extent_offset(leaf, fi, split - orig_offset); |
795 | btrfs_set_file_extent_type(leaf, fi, extent_type); | 672 | btrfs_set_file_extent_num_bytes(leaf, fi, |
796 | btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr); | 673 | extent_end - split); |
797 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes); | 674 | btrfs_mark_buffer_dirty(leaf); |
798 | btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset); | 675 | |
799 | btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset); | 676 | ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0, |
800 | btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes); | 677 | root->root_key.objectid, |
801 | btrfs_set_file_extent_compression(leaf, fi, 0); | 678 | inode->i_ino, orig_offset); |
802 | btrfs_set_file_extent_encryption(leaf, fi, 0); | 679 | BUG_ON(ret); |
803 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); | 680 | |
804 | done: | 681 | if (split == start) { |
805 | btrfs_mark_buffer_dirty(leaf); | 682 | key.offset = start; |
806 | 683 | } else { | |
807 | release: | 684 | BUG_ON(start != key.offset); |
808 | btrfs_release_path(root, path); | 685 | path->slots[0]--; |
809 | if (split_end && split == start) { | 686 | extent_end = end; |
810 | split = end; | 687 | } |
811 | goto again; | 688 | recow = 1; |
689 | } | ||
690 | |||
691 | other_start = end; | ||
692 | other_end = 0; | ||
693 | if (extent_mergeable(leaf, path->slots[0] + 1, | ||
694 | inode->i_ino, bytenr, orig_offset, | ||
695 | &other_start, &other_end)) { | ||
696 | if (recow) { | ||
697 | btrfs_release_path(root, path); | ||
698 | goto again; | ||
699 | } | ||
700 | extent_end = other_end; | ||
701 | del_slot = path->slots[0] + 1; | ||
702 | del_nr++; | ||
703 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
704 | 0, root->root_key.objectid, | ||
705 | inode->i_ino, orig_offset); | ||
706 | BUG_ON(ret); | ||
707 | } | ||
708 | other_start = 0; | ||
709 | other_end = start; | ||
710 | if (extent_mergeable(leaf, path->slots[0] - 1, | ||
711 | inode->i_ino, bytenr, orig_offset, | ||
712 | &other_start, &other_end)) { | ||
713 | if (recow) { | ||
714 | btrfs_release_path(root, path); | ||
715 | goto again; | ||
716 | } | ||
717 | key.offset = other_start; | ||
718 | del_slot = path->slots[0]; | ||
719 | del_nr++; | ||
720 | ret = btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
721 | 0, root->root_key.objectid, | ||
722 | inode->i_ino, orig_offset); | ||
723 | BUG_ON(ret); | ||
812 | } | 724 | } |
813 | if (locked_end > end) { | 725 | if (del_nr == 0) { |
814 | unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1, | 726 | fi = btrfs_item_ptr(leaf, path->slots[0], |
815 | GFP_NOFS); | 727 | struct btrfs_file_extent_item); |
728 | btrfs_set_file_extent_type(leaf, fi, | ||
729 | BTRFS_FILE_EXTENT_REG); | ||
730 | btrfs_mark_buffer_dirty(leaf); | ||
731 | } else { | ||
732 | fi = btrfs_item_ptr(leaf, del_slot - 1, | ||
733 | struct btrfs_file_extent_item); | ||
734 | btrfs_set_file_extent_type(leaf, fi, | ||
735 | BTRFS_FILE_EXTENT_REG); | ||
736 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
737 | extent_end - key.offset); | ||
738 | btrfs_mark_buffer_dirty(leaf); | ||
739 | |||
740 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | ||
741 | BUG_ON(ret); | ||
816 | } | 742 | } |
743 | out: | ||
817 | btrfs_free_path(path); | 744 | btrfs_free_path(path); |
818 | return 0; | 745 | return 0; |
819 | } | 746 | } |
@@ -828,6 +755,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
828 | loff_t pos, unsigned long first_index, | 755 | loff_t pos, unsigned long first_index, |
829 | unsigned long last_index, size_t write_bytes) | 756 | unsigned long last_index, size_t write_bytes) |
830 | { | 757 | { |
758 | struct extent_state *cached_state = NULL; | ||
831 | int i; | 759 | int i; |
832 | unsigned long index = pos >> PAGE_CACHE_SHIFT; | 760 | unsigned long index = pos >> PAGE_CACHE_SHIFT; |
833 | struct inode *inode = fdentry(file)->d_inode; | 761 | struct inode *inode = fdentry(file)->d_inode; |
@@ -856,16 +784,18 @@ again: | |||
856 | } | 784 | } |
857 | if (start_pos < inode->i_size) { | 785 | if (start_pos < inode->i_size) { |
858 | struct btrfs_ordered_extent *ordered; | 786 | struct btrfs_ordered_extent *ordered; |
859 | lock_extent(&BTRFS_I(inode)->io_tree, | 787 | lock_extent_bits(&BTRFS_I(inode)->io_tree, |
860 | start_pos, last_pos - 1, GFP_NOFS); | 788 | start_pos, last_pos - 1, 0, &cached_state, |
789 | GFP_NOFS); | ||
861 | ordered = btrfs_lookup_first_ordered_extent(inode, | 790 | ordered = btrfs_lookup_first_ordered_extent(inode, |
862 | last_pos - 1); | 791 | last_pos - 1); |
863 | if (ordered && | 792 | if (ordered && |
864 | ordered->file_offset + ordered->len > start_pos && | 793 | ordered->file_offset + ordered->len > start_pos && |
865 | ordered->file_offset < last_pos) { | 794 | ordered->file_offset < last_pos) { |
866 | btrfs_put_ordered_extent(ordered); | 795 | btrfs_put_ordered_extent(ordered); |
867 | unlock_extent(&BTRFS_I(inode)->io_tree, | 796 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, |
868 | start_pos, last_pos - 1, GFP_NOFS); | 797 | start_pos, last_pos - 1, |
798 | &cached_state, GFP_NOFS); | ||
869 | for (i = 0; i < num_pages; i++) { | 799 | for (i = 0; i < num_pages; i++) { |
870 | unlock_page(pages[i]); | 800 | unlock_page(pages[i]); |
871 | page_cache_release(pages[i]); | 801 | page_cache_release(pages[i]); |
@@ -877,12 +807,13 @@ again: | |||
877 | if (ordered) | 807 | if (ordered) |
878 | btrfs_put_ordered_extent(ordered); | 808 | btrfs_put_ordered_extent(ordered); |
879 | 809 | ||
880 | clear_extent_bits(&BTRFS_I(inode)->io_tree, start_pos, | 810 | clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos, |
881 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC | | 811 | last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC | |
882 | EXTENT_DO_ACCOUNTING, | 812 | EXTENT_DO_ACCOUNTING, 0, 0, &cached_state, |
883 | GFP_NOFS); | 813 | GFP_NOFS); |
884 | unlock_extent(&BTRFS_I(inode)->io_tree, | 814 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, |
885 | start_pos, last_pos - 1, GFP_NOFS); | 815 | start_pos, last_pos - 1, &cached_state, |
816 | GFP_NOFS); | ||
886 | } | 817 | } |
887 | for (i = 0; i < num_pages; i++) { | 818 | for (i = 0; i < num_pages; i++) { |
888 | clear_page_dirty_for_io(pages[i]); | 819 | clear_page_dirty_for_io(pages[i]); |
@@ -909,7 +840,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
909 | unsigned long last_index; | 840 | unsigned long last_index; |
910 | int will_write; | 841 | int will_write; |
911 | 842 | ||
912 | will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) || | 843 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || |
913 | (file->f_flags & O_DIRECT)); | 844 | (file->f_flags & O_DIRECT)); |
914 | 845 | ||
915 | nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, | 846 | nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, |
@@ -1076,7 +1007,7 @@ out_nolock: | |||
1076 | if (err) | 1007 | if (err) |
1077 | num_written = err; | 1008 | num_written = err; |
1078 | 1009 | ||
1079 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { | 1010 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { |
1080 | trans = btrfs_start_transaction(root, 1); | 1011 | trans = btrfs_start_transaction(root, 1); |
1081 | ret = btrfs_log_dentry_safe(trans, root, | 1012 | ret = btrfs_log_dentry_safe(trans, root, |
1082 | file->f_dentry); | 1013 | file->f_dentry); |
@@ -1210,7 +1141,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1210 | } | 1141 | } |
1211 | mutex_lock(&dentry->d_inode->i_mutex); | 1142 | mutex_lock(&dentry->d_inode->i_mutex); |
1212 | out: | 1143 | out: |
1213 | return ret > 0 ? EIO : ret; | 1144 | return ret > 0 ? -EIO : ret; |
1214 | } | 1145 | } |
1215 | 1146 | ||
1216 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 1147 | static const struct vm_operations_struct btrfs_file_vm_ops = { |